我正在研究Caesar的密码进行在线课程,我对最终输出中的原始值有疑问,我似乎无法摆脱它。我怀疑它是由于
strcpy(str1, &final_val);
strcat(str2, str1);
以错误的方式被召唤,所以当我跑
make test && ./test 1
这为我的程序提供了参数1
,并提供了移动字母和编码消息的键。我希望看到
plaintext: asd
ciphertext: bcd
相反,我得到了
plaintext: asd
ciphertext: bacbdc
如果你想试用代码,你需要在this sanbox中进行,因为它有所需的CS50库。
码
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
bool input_valid(int count, string arg);
bool in_alphabet(int count, string arg);
int main(int argc, string argv[]) {
int key;
int ascii_val;
char final_val;
string string;
char str1[80];
char str2[80];
// check input again if validation fails
if (!input_valid(argc, argv[1])) {
printf("Invalid input!\nUSAGE: ./caesar key\n");
return 1;
}
string = get_string("plaintext: ");
// get integer from string input
key = strtol(argv[1], NULL, 10);
for (int i = 0; i < strlen(string); i++) {
ascii_val = (int)string[i];
bool valid_lower_case = (ascii_val + key) >= 97 && (ascii_val + key) <= 122;
bool valid_upper_case = (ascii_val + key) >= 65 && (ascii_val + key) <= 90;
// check if value is a letter
if (isalpha(string[i])) {
// check if value is in the valid alphabet range
if (valid_lower_case || valid_upper_case) {
final_val = ascii_val + key;
} else {
// for lowercase: wrap around if the letter passes 'z'
final_val = 97 + (key - (122 - (ascii_val - 1)));
}
} else {
final_val = ascii_val;
}
strcpy(str1, &final_val);
strcat(str2, str1);
}
for (int i = 0; i < 5; i++) {
printf("%i\n", str2[i]);
}
printf("ciphertext: %s\n", str2);
}
bool input_valid(int count, string arg) {
// input has more args than just the file name
// input is an integer
return count > 1 && isdigit(arg[0]);
}
strcpy(str1, &final_val);
是未定义的行为。 strcpy
希望这两个参数都是指向以null结尾的字符串的指针。但是,由于数组在传递给函数时会衰减为指针,因此strcpy
不知道指向字符数组的指针与单个char
变量的地址之间的区别。
它会尝试将从&final_val
开始的内存复制到str1
,只有当它遇到进程内存中其他位置的null终止符时才会停止,如果有的话。要将单个字符复制到字符串,只需使用str[x] = ch
和str[x + 1] = '\0'
。
取代了strcopy()
和strcat()
。通过像这样附加到str2
来工作:
str2[i] = final_val;