凯撒密码程序数字密钥有效性验证异常问题求助
凯撒密码密钥验证问题分析与修复
嘿,我一眼就瞅出你代码里的核心问题了——密钥验证的逻辑完全走偏了,这就是为啥输入9判定失败、输入45却“误打误撞”成功的原因。
为啥会出现这种诡异的现象?
咱们拆解两种输入的执行过程就懂了:
- 当你输入
./caesar 9时:argv[1]是字符串"9",用atoi转成整数后得到9。- 然后你去检查
isdigit(argv[1][n])——也就是argv[1][9]。但"9"这个字符串只有1个字符(索引是0),索引9早就超出了字符串的内存范围,属于非法内存访问。此时读取到的是随机的垃圾值,大概率不是数字字符,所以条件不成立,直接跳去输出错误提示。
- 当你输入
./caesar 45时:argv[1]是字符串"45",atoi转成整数是45,argv[1][45]同样是越界访问,但这次碰巧那个内存位置的字节刚好对应一个数字字符的ASCII值,所以条件“侥幸”成立了。
这种行为完全是随机的,属于C语言里的未定义行为,换个机器或者输入其他数字,结果可能又不一样。
正确的密钥验证姿势
你真正要做的是:遍历命令行参数的每一个字符,确保所有字符都是十进制数字,而不是用转换后的整数去当索引瞎访问。另外,一定要先检查参数数量是否正确,避免没传参数时访问argv[1]导致空指针错误。
修正后的代码如下:
#include <stdio.h> #include <cs50.h> #include <string.h> #include <ctype.h> #include <stdlib.h> int main(int argc, string argv[]) { // 第一步:先检查参数数量是否符合要求 if (argc != 2) { printf("Usage: ./caesar key\n"); return 1; } string key_str = argv[1]; // 第二步:遍历密钥字符串的每一个字符,验证是否全为数字 for (int i = 0; i < strlen(key_str); i++) { if (!isdigit(key_str[i])) { printf("Usage: ./caesar key\n"); return 1; } } // 验证通过后,再将字符串转成整数使用 int key = atoi(key_str); printf("Success %d\n", key); return 0; }
关键修正点说明:
- 先判断
argc == 2,确保用户确实传了密钥参数,避免空指针访问。 - 用循环逐个检查密钥字符串的每个字符,只要有一个不是数字,就直接报错退出。
- 只有当所有字符都验证通过后,才把字符串转成整数,这样既安全又符合需求。
这样修改后,不管你输入单个数字还是多位数,都能正确验证啦。
内容的提问来源于stack exchange,提问作者Mo Ez
相关产品推荐
相关产品推荐

