求解哈佛CS50 Caesar习题时遭遇Segmentation fault (core dumped)错误
解决CS50 Caesar习题中的Segmentation Fault问题
核心问题分析
- 未校验命令行参数:程序直接读取
argv[1],如果运行时未传入密钥参数,会访问非法内存地址触发段错误。 - 密文字符串未分配有效内存:
string cipher = "";指向的是只读的空字符串常量,无法通过cipher[i]修改其内容,这是引发段错误的直接原因。 - rotate函数逻辑漏洞:未区分大小写字母,非字母字符(空格、数字等)会被错误偏移,且大写字母超出范围的情况未处理。
修复后的完整代码
#include <cs50.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> char rotate(char c, int n); int main(int argc, string argv[]) { // 检查命令行参数数量是否合法 if (argc != 2) { printf("Usage: ./caesar key\n"); return 1; } // 校验密钥是否为纯数字(符合CS50习题要求) for (int i = 0; argv[1][i] != '\0'; i++) { if (!isdigit(argv[1][i])) { printf("Usage: ./caesar key\n"); return 1; } } string plaintext = get_string("plaintext: "); int key = atoi(argv[1]); int length = strlen(plaintext); // 为密文动态分配内存,预留字符串终止符位置 string cipher = malloc(length + 1); if (cipher == NULL) { printf("Memory allocation failed\n"); return 1; } for (int i = 0; i < length; i++) { cipher[i] = rotate(plaintext[i], key); } // 添加字符串终止符,保证printf能正确识别 cipher[length] = '\0'; printf("ciphertext: %s\n", cipher); // 释放动态分配的内存,避免内存泄漏 free(cipher); return 0; } char rotate(char c, int n) { // 非字母字符直接返回,不做偏移 if (!isalpha(c)) { return c; } // 区分大小写,以对应字母为基准计算循环偏移 char base = isupper(c) ? 'A' : 'a'; return (c - base + n) % 26 + base; }
关键修复点说明
- 命令行参数校验:先判断参数数量,再验证密钥是否为纯数字,符合习题的输入规范,避免非法内存访问。
- 动态内存管理:用
malloc为密文字符串分配足够内存,使用完成后用free释放,既解决了段错误,也避免内存泄漏。 - rotate函数优化:用
isalpha和isupper区分字符类型,通过模26运算实现循环移位,逻辑简洁且覆盖所有合法输入场景。
内容的提问来源于stack exchange,提问作者rasmusschaal
相关产品推荐
相关产品推荐

