CS50凯撒密码C程序运行正常但无法通过check50校验问题
凯撒加密程序问题排查与修复
程序设计目标
实现根据用户传入密钥对明文字符串执行凯撒加密的功能,预设校验逻辑:
- 若命令行参数
argc个数不为2,或argv[1]传入的密钥不是合法正整数,打印使用提示Usage: ./caesar key并返回1 - 参数校验通过后,执行完整加密流程输出密文
初始问题代码
#include <cs50.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> int main(int argc, string argv[]) { //Get the key if (argc != 2) { printf("Usage: ./caesar key\n"); return 1; } for (int key = 0; key < strlen(argv[1]); key++) { if(isalpha(argv[1][key])) { printf("Usage: ./caesar key\n"); return 1; } } //Convert string to int int key = atoi(argv[1]); //Get the plaintext string plaintext = get_string("Plaintext: "); //Output the ciphertext printf("ciphertext: "); for (int i = 0, length = strlen(plaintext); i < length; i++) { if(!isalpha(plaintext[i])) { printf("%c", plaintext[i]); continue; } int offset = isupper(plaintext[i]); for (int j = 0; plaintext[i] != '\0'; i++) { if (isalpha(plaintext[i]) != 0) { if (isupper(plaintext[i]) != 0) { printf("%c", ((plaintext[i] - 65 + key) % 26) + 65); } else { printf("%c", ((plaintext[i] - 97 + key) % 26) + 97); } } else { printf("%c", plaintext[i]); } } int p = plaintext[i] - offset; int c = (p + key) % 26; printf("%c", c + offset); } printf("\n"); return 0; }
自动化校验报错现象
运行CS50的check50自动化校验得到如下结果:
- 基础校验通过:
caesar.c文件存在、可正常编译;缺少argv[1]、密钥为非数字、参数过多三类异常场景校验逻辑符合要求 - 所有加密测试用例未通过:
- 使用密钥3加密
"BARFOO"、密钥4加密"BaRFoo"的场景,提示输出非有效ASCII文本 - 其余加密场景提示预期输出与实际输出前缀一致但校验不通过,报错信息中展示的预期输出与实际输出可见文本完全一致,肉眼无法直接定位差异
- 使用密钥3加密
问题排查与修复步骤
- 硬编码ASCII值修复
将代码中硬编码的ASCII值65、97替换为字符常量'A'、'a',解决硬编码带来的兼容性问题。 - 删除冗余死循环
删除冗余的内层for (int j = 0; plaintext[i] != '\0'; i++)循环:该循环未使用循环变量j,进入后会持续递增外层遍历的索引i直到访问到字符串结束符,甚至越界访问栈内存的未知数据,这是输出非法ASCII字符的核心原因。 - 修正偏移量计算逻辑
原代码int offset = isupper(plaintext[i]);逻辑错误:isupper()函数仅返回0(非大写)或非0值(大写),并非大写/小写字符的ASCII基准值。修正逻辑为:判断当前字符为大写时offset = 'A',为小写时offset = 'a',保证偏移计算基准正确。 - 删除重复加密输出逻辑
内层循环删除后,原代码中int p = plaintext[i] - offset;开始的二次加密计算属于冗余逻辑,会对同一个字符重复输出一次密文,导致输出长度是预期的2倍——这就是肉眼可见文本一致但校验不通过的根本原因:输出前缀和预期完全匹配,但末尾多了重复计算的冗余字符,导致整体哈希校验不通过。
修复后核心加密逻辑参考
for (int i = 0, length = strlen(plaintext); i < length; i++) { if(!isalpha(plaintext[i])) { printf("%c", plaintext[i]); continue; } char offset = isupper(plaintext[i]) ? 'A' : 'a'; printf("%c", ((plaintext[i] - offset + key) % 26) + offset); }
替换原外层循环内的冗余逻辑后,即可通过全部check50测试用例。
内容的提问来源于stack exchange,提问作者omelias
相关产品推荐
相关产品推荐

