C语言程序出现Segmentation fault (core dumped),新手求问题排查
C语言问卷处理程序段错误(Segmentation fault)排查与修复
核心问题分析
你的问卷处理程序运行时触发段错误,主要由以下几个原因导致:
1. 受访者数量超出数组上限
responses数组定义为MAXR(100)行,但readresponses函数的循环未限制受访者数量上限。当输入的受访者超过100时,会访问responses[100][...]这类超出数组边界的内存,直接触发段错误。
2. 空响应导致数组越界
如果某条受访者记录的响应数量少于问题总数,未被赋值的responses[j][i]会保留全局初始值0。在calculatefrequencies中,反向计分后得到7-0=7,此时访问freq[7-1] = freq[6],但freq数组仅包含6个元素(索引0-5),越界访问触发段错误。
3. 字符串换行符干扰
fgets读取的行包含末尾换行符,strtok分割后,最后一个token会携带换行符(比如问题类型行的"Reverse"会变成"Reverse\n"),导致strcmp(token, "Reverse")匹配失败,错误将反向问题标记为正向,影响计分结果。
修复方案
- 限制受访者数量:在
readresponses循环中添加*num_respondents < MAXR判断,避免数组越界。 - 初始化响应数组:处理每个受访者前,将其对应的响应行初始化为0,明确标记无效响应。
- 去除换行符:新增
trim_newline函数,处理fgets读取的缓冲区和单个token,避免换行符干扰字符串比较。 - 过滤无效响应:在计算频率和得分时,跳过值为0的无效响应,避免越界和错误计分。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXR 100 #define MAXQ 50 #define DIRECT 0 #define REVERSE 1 char questions[MAXQ][256]; int q_type[MAXQ]; int responses[MAXR][MAXQ]; // 去除字符串末尾的换行符 void trim_newline(char *str) { size_t len = strlen(str); if (len > 0 && str[len-1] == '\n') { str[len-1] = '\0'; } } void readquestions(){ char buffer[4096]; // 读取问题 if(fgets(buffer, sizeof(buffer), stdin) != NULL){ trim_newline(buffer); char *token = strtok(buffer, ";"); int i = 0; while (token != NULL && i < MAXQ){ strncpy(questions[i], token, sizeof(questions[i])-1); questions[i][sizeof(questions[i])-1] = '\0'; // 确保字符串结束 token = strtok(NULL, ";"); i++; } // 初始化剩余问题为空 for(; i < MAXQ; i++){ questions[i][0] = '\0'; } } // 读取问题类型 if(fgets(buffer, sizeof(buffer), stdin) != NULL){ trim_newline(buffer); char *token = strtok(buffer, ";"); int i = 0; while(token != NULL && i < MAXQ){ trim_newline(token); // 去除单个token的换行(如果有) if(strcmp(token, "Reverse") == 0){ q_type[i] = REVERSE; }else{ q_type[i] = DIRECT; } token = strtok(NULL, ";"); i++; } // 初始化剩余类型为DIRECT for(; i < MAXQ; i++){ q_type[i] = DIRECT; } } } void readresponses(int *num_respondents){ char buffer[4096]; *num_respondents = 0; while(fgets(buffer, sizeof(buffer), stdin) != NULL && *num_respondents < MAXR){ if(buffer[0] == '#') continue; trim_newline(buffer); char *token = strtok(buffer, ","); // 跳过3个人口统计字段 for(int i = 0; i < 3; i++){ if(token == NULL) break; token = strtok(NULL, ","); } if(token == NULL){ continue; } // 初始化当前受访者的响应为0(无效值) memset(responses[*num_respondents], 0, sizeof(responses[*num_respondents])); // 解析响应 for(int i = 0; i < MAXQ; i++){ if(token == NULL) break; trim_newline(token); if(strcmp(token, "fully disagree") == 0){ responses[*num_respondents][i] = 1; }else if(strcmp(token, "disagree") == 0){ responses[*num_respondents][i] = 2; }else if(strcmp(token, "partially disagree") == 0) { responses[*num_respondents][i] = 3; }else if(strcmp(token, "partially agree") == 0) { responses[*num_respondents][i] = 4; }else if(strcmp(token, "agree") == 0) { responses[*num_respondents][i] = 5; }else if(strcmp(token, "fully agree") == 0) { responses[*num_respondents][i] = 6; } token = strtok(NULL, ","); } (*num_respondents)++; } } void calculatefrequencies(int num_questions, int num_respondents){ if(num_respondents == 0){ printf("No respondents to calculate frequencies\n"); return; } printf("FREQUENCIES ARE COMPUTED FOR EACH LEVEL OF AGREEMENT BELOW\n\n"); for(int i = 0; i < num_questions; i++){ int freq[6] = {0}; for(int j = 0; j < num_respondents; j++){ int response = responses[j][i]; // 跳过无效响应(0) if(response < 1 || response > 6){ continue; } if(q_type[i] == REVERSE){ response = 7 - response; } // 确保response在1-6范围内,避免越界 if(response >=1 && response <=6){ freq[response - 1]++; } } printf("%s\n", questions[i]); for(int z = 0; z < 6; z++){ double percent = (num_respondents > 0) ? (freq[z] * 100.0) / num_respondents : 0.0; printf("%.2f%%: %s\n", percent, (z == 0) ? "fully disagree" : (z == 1) ? "disagree" : (z == 2) ? "partially disagree" : (z == 3) ? "partially agree" : (z == 4) ? "agree" : "fully agree"); } printf("\n"); } } void calculatescores(int num_questions, int num_respondents){ if(num_respondents == 0){ return; } printf("SCORES FOR ALL RESPONDENTS\n"); for (int r = 0; r < num_respondents; r++){ int total_c = 0, total_i = 0, total_g = 0, total_u = 0, total_p = 0; for(int q = 0; q < num_questions; q++){ int score = responses[r][q]; if(score <1 || score >6){ continue; // 跳过无效响应 } if(q_type[q] == REVERSE){ score = 7 - score; } if (q < 8) total_c += score; else if (q < 18) total_i += score; else if (q < 28) total_g += score; else if (q < 34) total_u += score; else total_p += score; } printf("C:%d, I:%d, G:%d, U:%d, P:%d\n", total_c, total_i, total_g, total_u, total_p); } } int main() { int num_questions = 0; int num_respondents = 0; readquestions(); // 统计有效问题数量 for(int i = 0; i < MAXQ; i++){ if(questions[i][0] != '\0'){ num_questions++; }else{ break; // 遇到空问题就停止统计,假设问题是连续的 } } readresponses(&num_respondents); calculatefrequencies(num_questions, num_respondents); calculatescores(num_questions, num_respondents); return 0; }
内容的提问来源于stack exchange,提问作者abgdestroyer
相关产品推荐
相关产品推荐

