CS50x中C语言替换加密脚本输出无效ASCII文本求助
替换加密脚本输出随机字符的解决办法
核心问题原因
C语言中,printf("%s")输出字符串时要求字符串必须以**空字符'\0'**作为结尾标记。你的cipher数组仅分配了与明文长度相等的空间,刚好存下所有加密后的字符,但没有预留存储终止符的位置。printf会持续读取内存直到遇到'\0',这就是输出末尾出现随机字符的原因。
修复步骤
- 调整数组长度:将
char cipher[plainlen];修改为char cipher[plainlen + 1];,多分配1个字节用于存储终止符。 - 添加终止符:在加密循环结束后,手动给
cipher数组添加终止符:cipher[plainlen] = '\0';
额外代码优化建议
你的密钥检查逻辑存在漏洞,原do-while循环会遗漏对部分字符的检查,同时参数个数判断可以更规范:
- 用
argc != 2替代argv[2] != (void *)0,直接判断参数数量是否符合要求; - 改用
for循环遍历密钥的26个字符,确保每个字符都是字母。
修改后的完整代码
#include <cs50.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <stdbool.h> int main(int argc, string argv[]) { // 检查命令行参数数量是否正确 if (argc != 2) { printf("Usage: ./substitution key\n"); return 1; } string key = argv[1]; int keylength = strlen(key); // 检查密钥长度是否为26 if(keylength != 26) { printf("Key must contain 26 characters.\n"); return 1; } // 检查密钥是否全为字母 bool key_valid = true; for (int i = 0; i < 26; i++) { if (!isalpha(key[i])) { key_valid = false; break; } } if (!key_valid) { printf("Key must contain only alphabetical characters.\n"); return 1; } // 获取明文 string plain = get_string("Plaintext: "); int plainlen = strlen(plain); char cipher[plainlen + 1]; // 多分配1个字节存终止符 char keylower[26]; char keyupper[26]; // 预转换密钥为大小写版本 for (int i = 0; i < 26; i++) { keylower[i] = tolower(key[i]); keyupper[i] = toupper(key[i]); } // 转换明文为密文 for(int k = 0; k < plainlen; k++) { if(isalpha(plain[k])) { if(islower(plain[k])) { int y = plain[k] - 'a'; cipher[k] = keylower[y]; } else { int y = plain[k] - 'A'; cipher[k] = keyupper[y]; } } else { cipher[k] = plain[k]; } } cipher[plainlen] = '\0'; // 添加字符串终止符 // 输出密文 printf("Ciphertext: %s\n", cipher); return 0; }
额外说明
- 用
'a'和'A'替代魔法数字97和65,提升代码可读性; - 提前预转换密钥的大小写版本,避免循环内重复调用
tolower/toupper,优化性能。
内容的提问来源于stack exchange,提问作者tp23
相关产品推荐
相关产品推荐

