c 新增的分段错误(核心转储)

问题描述 投票:0回答:1

正如标题所示,我得到了分段错误(核心转储)输出。我已经使用了调试器,但我不知道它为什么这样做。我对 C 有点陌生,所以我们将不胜感激。

该程序应该:

读取问题:它从输入中读取一组调查问题并将其分类为“直接”或“反向”。 读取响应:它处理调查响应(例如,“完全不同意”、“同意”等),将其转换为数值,并为每个受访者存储它们。 计算频率:它计算并打印每个问题的回答频率。如果问题被标记为“反向”,则答案会相应调整(例如,反向评分)。 计算分数:它根据每个受访者对调查的回答计算并打印不同类别(例如,信心、兴趣、性别、有用性、专业性)的分数。

`#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXR 100
#define MAXQ 50

//define constants for the questions
#define DIRECT 0
#define REVERSE 1

//the arrays to hold the questions
char questions[MAXQ][256];
int q_type[MAXQ]; //0 for direct 1 for reverse
int responses[MAXR][MAXQ]; //array to hold the responses

//function to read the questions
void readquestions(){
    
    char buffer[4096];

 //reading questiosn from input
    if(fgets(buffer, sizeof(buffer), stdin) != NULL){
        char *token = strtok(buffer, ";");
        int i = 0;

        while (token != NULL && i < MAXQ){
            strcpy(questions[i], token);
            token = strtok(NULL, ";");
            i++;
        }
    }

    //reads question type
    if(fgets(buffer, sizeof(buffer), stdin) != NULL){
        char *token = strtok(buffer, ";");
        int i = 0;  

        while(token != NULL && i < MAXQ){
            if(strcmp(token, "Reverse") == 0){
                q_type[i] = REVERSE;
            }else{
                q_type[i] = DIRECT;
            }
            token = strtok(NULL, ";");
            i++;
        }
    }
    /*//for loop that counts how many questions are read
    for(int i = 0; i < MAXQ; i++){
        q_type[i] = 0; // initialize as not REVERSE
        snprintf(questions[i], 256, "Questions %d", i + 1);
    }*/
}

//function to read responses
void readresponses(int *num_respondents){
    char buffer[4096]; //holds each line of responses
    *num_respondents = 0;

    //for loop to process responses
    while(fgets(buffer, sizeof(buffer), stdin) != NULL){
        if(buffer[0] == '#') continue; //skip comment lines

        char *token = strtok(buffer, ",");

        //skip demographic fields
        for(int i = 0; i < 3; i++){
            if(token == NULL) break;
            token = strtok(NULL, ",");
        }

        if(token == NULL){
            continue;
        } //skips if there are no responses

        //parse respones
        for(int i = 0; i < MAXQ; i++){
            if(token == NULL) break;

            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, ","); //move to next response
        }
        (*num_respondents)++;
    }
}

//this function calculates the frequencies
void calculatefrequencies(int num_questions, int num_respondents){
    //simple if statement to return function if theres no 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}; // freq. for the 6 likert levels

        //for loop to count the freq .of each response
        for(int j = 0; j < num_respondents; j++){
            int response = responses[j][i];
            if(q_type[i] == REVERSE){//if reverse-scored
                response = 7 - response;
            }//this reverses the score if its a reverse question
        freq[response - 1]++;
        }

    //to print relative frequencies
    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");
    }
}

//function to calculate and print scores for each respondent
void calculatescores(int num_questions, int num_respondents){
    if(num_respondents == 0){
    return;
    }

    printf("SCORES FOR ALL THE RESPONDENT\n");

    //looping through each respondent and to compute scores
    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(q_type[q] == REVERSE){
                score = 7 - score; //reverse the score if needed
            }

    //categorization
        if (q < 8) total_c += score;      // Confidence
                else if (q < 18) total_i += score; // Interest
            else if (q < 28) total_g += score; // Gender
                else if (q < 34) total_u += score; // Usefulness
                else total_p += score;             // Professionalism
        }
        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(); //read question from input

    //for loop to count how many questions are read
    for(int i = 0; i < MAXQ; i++){
        if(questions[i][0] != '\0'){
        num_questions++;
        }
    }
    readresponses(&num_respondents); //read responses from input
    calculatefrequencies(num_questions, num_respondents); //calculate frequencies
    calculatescores(num_questions, num_respondents); //calculate  scores

    //checks for debugging
    //printf("Number of questions: %d\n", num_questions);
    //printf("Number of respondents: %d\n", num_respondents);

 return 0;
}
`
c
1个回答
0
投票

代码至少存在这些问题:

fgets()
保存
'\n'

if(strcmp(token,...
树都会失败,因为
token
可能有
'\n'
。 请参阅从 fgets() 输入中删除尾随换行符
如果没有匹配,代码应该抱怨。 也许不匹配条件也会导致 OP 的 UB?

潜在的缓冲区溢出

strcpy(questions[i], token);
有溢出的风险
questions[i]

简单的替代方案:

sprintf(questions[i], sizeof questions[i], token, "%s", token);

还存在其他更优雅的方法 - 但往往超过 1 行。
IAC,代码还应该检测过长的字符串并抱怨。

也许还有其他问题

© www.soinside.com 2019 - 2024. All rights reserved.