C语言入门:未完全理解指针,输入add命令触发段错误求助
C语言add命令段错误问题排查与修复
核心错误点梳理
- 野指针访问(最直接的段错误诱因)
main函数中char* cmdLine仅定义了字符指针,没有分配任何可写入的内存空间,直接调用gets(cmdLine)会向随机内存地址写入数据,直接触发段错误。同时gets函数本身是已被废弃的不安全函数,完全不限制写入长度,极易造成内存溢出。 - 空指针访问
- 当add命令没有带参数时,代码没有跳过
handleAdd(input)的调用,会直接把NULL传入处理函数,后续访问该指针直接崩溃。 handleAdd中写了循环把addCommand遍历到NULL后,又调用strlen(addCommand)对空指针求长度,直接触发段错误。
- 当add命令没有带参数时,代码没有跳过
- strtok用法错误
- main函数中
input = strtok(NULL, "");用空字符串作为分隔符,会把add后面的所有内容当成一整串,无法拆分出各个数字参数,正确分隔符应为空格" "。 - strtok依赖全局状态保存拆分进度,main中拆分过命令行后,在
handleAdd中直接调用strtok(NULL, " ")无法正确接续拆分参数,需要对传入的参数字符串重新初始化拆分。
- main函数中
- 逻辑错误
- 直接读取参数字符的ASCII值存入坐标数组,没有转成整数,就算不崩溃存储的数值也完全错误。
- 用字符值的奇偶判断是x坐标还是y坐标,逻辑完全错误,应该按参数的位置判断:第1、3、5……个参数为x坐标,第2、4、6……个为y坐标。
入门级修复方案
第一步:修复main函数的输入逻辑
int main() { printf("Create a polygon using the add command. Valid commands are add, summary, turn, shift, and quit.\n"); while (1) { // 分配固定长度的数组存储输入,不要用野指针 char cmdLine[256]; char* command; char* input; printf(">>"); // 用安全的fgets替代gets,限制最大输入长度 fgets(cmdLine, sizeof(cmdLine), stdin); // 去掉fgets读取到的末尾换行符 cmdLine[strcspn(cmdLine, "\n")] = '\0'; command = strtok(cmdLine, " "); // 处理空输入的情况 if (command == NULL) continue; if (strcmp(command, "quit") == 0) break; else if (!strcmp(command, "add")) { // 分隔符用空格,拆分第一个参数 input = strtok(NULL, " "); if (input == NULL) { printf("Too few aguments for add command! It must be in the form of add x1 y1 x2 y2 xn yn.\n"); // 没有参数就不要调用处理函数 continue; } handleAdd(input); } } return 0; }
第二步:修复handleAdd函数逻辑
// 假设你已经提前定义了全局的坐标数组和计数变量,示例定义如下: // int xCoords[100], yCoords[100]; // int pointCount = 0; void handleAdd(char* addCommand) { // 先复制参数到本地数组,避免strtok修改原字符串 char paramBuf[256]; strcpy(paramBuf, addCommand); // 初始化拆分,分隔符为空格 char* token = strtok(paramBuf, " "); int paramIndex = 0; // 循环拆分所有参数 while (token != NULL) { // 把字符串转成整数 int num = atoi(token); // 参数下标从0开始,偶数位是x,奇数位是y if (paramIndex % 2 == 0) { xCoords[pointCount] = num; } else { yCoords[pointCount] = num; // 每存完一对x y,点数计数加1 pointCount++; // 简单防止数组越界,示例中设置最多存100个点 if (pointCount >= 100) break; } paramIndex++; // 拆分下一个参数 token = strtok(NULL, " "); } }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

