CS50x Caesar程序添加isalpha(argv[1])检查后出现段错误求助
解决Caesar密码程序中的Segmentation Fault问题
嘿,我一眼就瞅出你代码里的问题了——你误用了isalpha函数,这正是导致段错误的元凶!
问题根源
isalpha函数的设计是用来检查单个字符是否为字母的,它接受的参数是int类型(实际传入的应该是unsigned char转换后的整数值,或者EOF)。但你这里直接把argv[1](一个字符串指针,也就是内存地址)传了进去,函数会把这个指针的地址值当成字符的ASCII码来处理,这完全不符合函数的预期,直接触发了未定义行为,也就是你看到的"Segmentation fault"。
正确的参数校验方式
要验证命令行参数是不是合法的非负整数,你需要遍历argv[1]的每一个字符,确保每个字符都是数字。具体做法如下:
- 先检查命令行参数的数量是否为1(也就是
argc == 2); - 遍历
argv[1]的每个字符,用isdigit()函数检查是否为数字; - 确认所有字符都是数字后,再用
atoi()转换为整数,并确保它是非负的(纯数字字符串转换后肯定是非负的,除非出现极端溢出,CS50题目场景下一般不用考虑)。
修改后的完整代码
#include <cs50.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc, string argv[]) { int kkey = 0; // 第一步:检查命令行参数数量是否正确 if (argc != 2) { printf("./caesar key\n"); return 1; } // 第二步:遍历检查每个字符是否为数字 for (int i = 0, len = strlen(argv[1]); i < len; i++) { if (!isdigit(argv[1][i])) { printf("./caesar key\n"); return 1; } } // 第三步:转换为密钥并确认非负 kkey = atoi(argv[1]); if (kkey < 0) { printf("./caesar key\n"); return 1; } // 输入明文并加密 string plaintext = get_string("plaintext: "); printf("ciphertext: "); // 符合CS50题目的输出规范 for (int i = 0, n = strlen(plaintext); i < n; i++) { if (islower(plaintext[i])) { plaintext[i] = (plaintext[i] - 'a' + kkey) % 26 + 'a'; } else if (isupper(plaintext[i])) { plaintext[i] = (plaintext[i] - 'A' + kkey) % 26 + 'A'; } printf("%c", plaintext[i]); } printf("\n"); return 0; }
额外优化点
- 去掉了重复的
isalpha判断:islower和isupper本身就已经包含了字母检查,没必要重复判断; - 增加了
ciphertext:的输出前缀:这是CS50题目明确要求的格式,原来的代码没有这个前缀可能会导致测试不通过。
这样修改后,你的程序就能正确校验命令行参数,再也不会出现段错误啦!
内容的提问来源于stack exchange,提问作者Phonx
相关产品推荐
相关产品推荐

