我正在尝试用C语言编写一个简单的Caesar密码。我正在创建一个加密函数,该函数接收一个字符串(char *,要加密的文本)和一个整数(密钥)。
在函数中,我为一个空字符串分配内存,该字符串将接收移位的字符。然后,我遍历初始字符串中的每个字符,并询问它是否是字母char(A-z)。如果是,则根据键移动。如果不是,则仅重复当前字符。问题是:当字符如!,?,。时。甚至空格出现在末尾,它会添加一些“?”对此。我已经放入了printf语句,我的猜测是正在发生未定义的行为,但我自己无法弄清楚。我希望有一个人可以帮助我。下面是我编写的代码和奇怪的结果。
char* encrypt(char* entry, int key) {
int i = 0;
key = key % 26;
char * tmp = (char *)malloc(strlen(entry));
if (!tmp) {
printf("Error during allocation.\n");
return entry;
}
//memset(tmp, 0, 1); // Tried with and without it.
char t;
while ((t = *(entry + i))) {
printf("Current letter: %c\n",*(entry+i));
if ((t >= 65 && t <= 90) || (t >= 97 && t <= 122)) { //is letter
*(tmp + i) = t + key > 90 ? t + key - 26 : t + key;
}
else { //isnt letter
printf("No letter char appeared. Code = %d\n",t);
*(tmp+i) = t;
}
printf("tmp letter: %c\n",*(tmp+i));
printf("current tmp: %s\n----------------\n",tmp);
i++;
}
printf("final tmp = %s\n",tmp);
entry = tmp;
free(tmp);
return entry;
}
调用函数: crypto(“ HELLO!你好吗?!”,13);
预期(最终)结果:URYYB! UBJ NER LBH ?! 实际(最终)结果:URYYB! UBJ NER LBH?!? (有时会添加更多的“?”)
调试printf语句:
Current letter: H
tmp letter: U
current tmp: U
----------------
Current letter: E
tmp letter: R
current tmp: UR
----------------
...
----------------
Current letter: !
No letter char appeared. Code = 33
tmp letter: !
current tmp: URYYB!
----------------
Current letter:
No letter char appeared. Code = 32
tmp letter:
current tmp: URYYB! ? // <<< It added a strange character to the string
----------------
Current letter: H
tmp letter: U
current tmp: URYYB! U // <<< '?' strange character gone
----------------
Current letter: O
tmp letter: B
current tmp: URYYB! UB
----------------
Current letter: W
tmp letter: J
current tmp: URYYB! UBJ // (I)
----------------
Current letter:
No letter char appeared. Code = 32
tmp letter:
current tmp: URYYB! UBJ // This time, space didn't raise a strange char after (I)
----------------
...
----------------
Current letter:
No letter char appeared. Code = 32
tmp letter:
current tmp: URYYB! UBJ NER ? // Missed me? I'm back
----------------
Current letter: Y
tmp letter: L
current tmp: URYYB! UBJ NER L // ...And gone again
----------------
Current letter: O
tmp letter: B
current tmp: URYYB! UBJ NER LB
----------------
Current letter: U
tmp letter: H
current tmp: URYYB! UBJ NER LBH???
----------------
Current letter: ?
No letter char appeared. Code = 63
tmp letter: ?
current tmp: URYYB! UBJ NER LBH???
----------------
Current letter: !
No letter char appeared. Code = 33
tmp letter: !
current tmp: URYYB! UBJ NER LBH?!?
----------------
final tmp = URYYB! UBJ NER LBH?!?
有人对此事有解释吗? 我的系统上的GCC信息:
gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
答案 0 :(得分:0)
tldr;您正在从从未初始化的内存中打印字符串。尝试使用calloc
代替malloc
。
我认为您的示例中出现的情况是您缺少零字节来终止字符串。为了了解发生了什么,您必须考虑以下两点:
\0
)结尾。处理C字符串的函数始终期望在字符串末尾有一个零字节。如果没有这样的终止符,他们将假定您的字符串尚未结束。malloc
不会初始化分配的内存。这意味着printf("%s", malloc(10));
可能会打印某些内容或无法打印任何内容。这取决于许多因素,因此通常称为“未定义行为”。因此,回到您的情况:分配tmp
,但不要将其初始化为零。但这是您的打印语句正常工作所必需的。因此,请使用类似calloc(1, strlen(entry)+1)
的名称。 (请注意+1
。字符串终止符(\0
还需要一个字节)
为了让您了解发生了什么,我建议您在memset(tmp, 'X', strlen(entry));
行之后添加malloc
。然后尝试了解输出。
旁注:以下内容不会将字符串从tmp
复制到entry
。
entry = tmp;
free(tmp);
return entry;
您基本上只需在此处返回tmp
,它指向已释放的内存块,这将导致函数外部的无效内存访问。您要使用的是memcpy
。