C语言使用Argv[]传参调用isdigit时触发Segmentation fault段错误
问题原因
- 入参类型不匹配是段错误的直接诱因:
argv是C语言的命令行参数数组,数组成员类型是char*(字符串指针),也就是说argv[argc-1]是一个指向字符串首地址的指针。但ctype.h中定义的isdigit()函数要求传入的参数是int类型,取值必须为EOF或unsigned char表示范围内的字符值。直接把指针值当作字符传入函数,会导致函数尝试访问非法的内存地址,直接触发段错误。 - 逻辑判断倒置:
isdigit()返回非0值代表传入字符是数字,原代码在检测到数字时反而打印参数错误提示,和预期逻辑完全相反。 - 缺失参数合法性前置校验:如果用户启动程序时没有传入任何额外参数,
argc值为1,此时argv[argc-1]取到的是argv[0]也就是程序自身的运行路径字符串,根本不是用户传入的待校验内容,判断逻辑完全失效。
修复方案
- 第一步先做参数数量校验:如果程序预期接收1个命令行参数,首先判断
argc的值是否为2(argv[0]固定为程序名,额外1个参数对应argc=2),不符合则直接打印提示退出。 - 第二步校验参数长度:命令行传入的参数都是字符串格式,哪怕用户输入单个数字,本质也是长度为1的字符串,需要先判断传入参数字符串长度是否为1,避免用户传入多字符内容。
- 第三步正确传参给
isdigit():从字符串中取出待校验的单个字符(即字符串的第一个成员argv[1][0]),强转为unsigned char后传入isdigit()(强转是为了规避有符号char值为负时触发的未定义行为),同时把判断逻辑修正为「字符不是数字时报错」。
修复后的可运行代码如下:
#include <cs50.h> #include <stdio.h> #include <ctype.h> #include <string.h> int main(int argc, string argv[]) { // 校验参数数量 if (argc != 2) { printf("Usage: %s <single-digit>\n", argv[0]); return 1; } string input = argv[1]; // 校验输入长度为单个字符 if (strlen(input) != 1) { printf("Error: please enter exactly one single character.\n"); return 1; } // 校验字符是否为数字 if (!isdigit((unsigned char)input[0])) { printf("Error: argument must be a number digit.\n"); return 1; } // 校验通过后的业务逻辑 printf("Valid digit input: %c\n", input[0]); return 0; }
内容的提问来源于stack exchange,提问作者Matt Riding
相关产品推荐
相关产品推荐

