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
相关产品推荐
相关产品推荐

