C语言实现CS50凯撒密码算法触发Segmentation fault段错误求解
错误原因与修复方案
核心错误(触发段错误)
cipher函数中声明的string ctext = NULL;是空指针,你直接对空指针执行ctext[i]赋值操作,访问了未申请的非法内存,这是触发段错误的直接原因。你需要先为密文字符串申请足够的内存空间,大小为明文长度+1(额外1位存储字符串结束符\0)。
其他逻辑错误
- 你把获取用户明文输入、调用加密的逻辑写在了密钥合法性校验的循环体内,会导致密钥有多少位,就会要求用户输入多少次明文,不符合需求。应该先完成所有密钥字符的合法性校验,全部为数字后再执行后续流程。
- 加密完成后没有给密文字符串末尾添加结束符
\0,输出时会出现乱码。 - 硬编码ASCII值96、65可读性差,替换为
'a'、'A'更易维护。
修复后完整代码
#include <cs50.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> string cipher(string ptext, int k); int main(int argc, string argv[]) { if (argc != 2) { printf("Usage: ./caesar key\n"); return 1; } // 先校验密钥所有字符都是数字 for (int i = 0, n = strlen(argv[1]); i < n; i++) { if (!isdigit(argv[1][i])) { printf("Usage: ./caesar key\n"); return 1; } } // 校验通过后再执行后续逻辑 int k = atoi(argv[1]) % 26; // 提前对26取模,避免k过大 string ptext = get_string("Text:"); string ctext = cipher(ptext, k); printf("Plain Text: %s \nCipher Text: %s\n", ptext, ctext); free(ctext); // 释放申请的内存,避免内存泄漏 return 0; } string cipher(string ptext, int k) { int len = strlen(ptext); string ctext = malloc(len + 1); // 申请内存,多留1位存\0 for (int i = 0; i < len; i++) { if (islower(ptext[i])) { ctext[i] = (ptext[i] - 'a' + k) % 26 + 'a'; } else if (isupper(ptext[i])) { ctext[i] = (ptext[i] - 'A' + k) % 26 + 'A'; } else { ctext[i] = ptext[i]; } } ctext[len] = '\0'; // 补字符串结束符 return ctext; }
验证效果
输入密钥为1,明文输入Hi!时,输出密文为Ij!,符合预期。
内容的提问来源于stack exchange,提问作者Vishruth
相关产品推荐
相关产品推荐

