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

Caesar密码程序编译正常但运行触发Segmentation Fault求助

Caesar密码程序段错误排查与修复

核心问题分析

  • isdigit参数错误:验证密钥是否全为数字的循环里,代码写了!isdigit(argv[1]),但isdigit需要传入单个字符,argv[1]是字符串指针,直接传指针会被强制转成int,触发未定义行为,这是导致段错误的直接原因。
  • 循环逻辑混乱:把整个加密流程(获取明文、加密输出)都套在了密钥验证的for循环里,意味着密钥有多少位,程序就会让用户重复输入多少次明文,完全不符合需求,还会放大错误影响。
  • 潜在空指针风险:如果get_string调用失败(比如输入为空),plaintext会是NULL,此时调用strlen(plaintext)也会触发段错误。

修复后的完整代码

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, string argv[])
{
    // 检查命令行参数数量是否正确
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // 验证密钥的每一位都是数字
    int key_len = strlen(argv[1]);
    for (int i = 0; i < key_len; i++)
    {
        if (!isdigit(argv[1][i]))
        {
            printf("Usage: ./caesar key\n");
            return 1;
        }
    }

    // 把密钥字符串转成整数
    int k = atoi(argv[1]);
    // 获取用户输入的明文,同时处理输入失败的情况
    string plaintext = get_string("Plain text: ");
    if (plaintext == NULL)
    {
        printf("Error: Failed to get input\n");
        return 1;
    }

    printf("Cipher text: ");
    // 对明文逐字符加密并输出
    int text_len = strlen(plaintext);
    for (int j = 0; j < text_len; j++)
    {
        if (isupper(plaintext[j]))
        {
            printf("%c", (plaintext[j] - 'A' + k) % 26 + 'A');
        }
        else if (islower(plaintext[j]))
        {
            printf("%c", (plaintext[j] - 'a' + k) % 26 + 'a');
        }
        else
        {
            printf("%c", plaintext[j]);
        }
    }
    printf("\n");

    return 0;
}

修复细节说明

  • 把isdigit(argv[1])改成isdigit(argv[1][i]),确保每次验证的是密钥的单个字符。
  • 拆分循环结构:密钥验证只执行一次,通过后再执行一次加密流程,避免重复输入明文。
  • 增加get_string返回值的NULL检查,防止空指针调用strlen触发错误。
  • 用'A'和'a'代替魔法数字65、97,代码可读性更高。

内容的提问来源于stack exchange,提问作者Ruan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:30:53