You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

凯撒密码程序数字密钥有效性验证异常问题求助

凯撒密码密钥验证问题分析与修复

嘿,我一眼就瞅出你代码里的核心问题了——密钥验证的逻辑完全走偏了,这就是为啥输入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 10:12:32