簡體   English   中英

從文件中讀取 192/200 行文本后,第二個 fgets 返回分段錯誤

[英]2nd fgets returns segmentation fault after reading 192/200 lines of text from file

我正在嘗試從文本文件中讀取 200 行文本,並將每行的值存儲到一個結構中。 這只是不工作部分的一小部分。 在整個代碼中,我詢問用戶是否希望讀取不同的文本文件。 它第一次完美運行,但是當用戶說是讀取不同的文件時,它只讀取並存儲文本文件的 200 行中的前 192 行,然后返回一個段錯誤。

我嘗試在整個代碼的各個部分打印出隨機字母,以確定哪一行返回了段錯誤,並且(根據我發現的內容),這是進入內部的 while 條件,我無法弄清楚為什么它會給出段錯誤。

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

int main(int argc, char *argv[]) {
    FILE *f1;
    int i = 0;
    struct pNames popNames;
    char fileName[20];
    char maleSNumber[20];
    char femaleSNumber[20];
    char string[200];

    fileName[0] = '\0';
    sprintf(fileName, "%d", popNames.year);
    strcat(fileName, "Names.txt");

    if ((f1 = fopen(fileName, "r")) != NULL) {
        while (fgets(string, 200, f1) != NULL) {
            sscanf(string, "%d %s %s %s %s",
                   &popNames.rank[i], 
                   popNames.maleName[i], maleSNumber,
                   popNames.femaleName[i], femaleSNumber);
            printf("%d %s %s %s %s\n", 
                   popNames.rank[i],
                   popNames.maleName[i], maleSNumber,
                   popNames.femaleName[i], femaleSNumber);
            removeCommas(maleSNumber);
            removeCommas(femaleSNumber);
            popNames.maleNumber[i] = atoi(maleSNumber);
            popNames.femaleNumber[i] = atoi(femaleSNumber);
            i++;
        }
    } else {
        printf("Cannot open %s\n", fileName);
        return (-1);
    }
}

結構定義:

#define MAXLENGTH 20
#define ROWS 200

/* Struct definitions */
struct pNames {
    int  year;
    int  rank[ROWS];
    char maleName[ROWS][MAXLENGTH];
    int  maleNumber[ROWS];
    char femaleName[ROWS][MAXLENGTH];
    int  femaleNumber[ROWS];
};

removeCommas()的定義:

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

int removeCommas(char *num) {
    int i;
    int newNum = 0;
    char *pointer;

    pointer = strchr(num, ',');
    while (pointer != NULL) {
        i = (int)(pointer - num);
        strcpy(&num[i], &num[i + 1]);
        newNum += 1;
        pointer = strchr(num, ',');
    }
    return (newNum);
}

它應該讀取、存儲每行的部分內容並打印出文本文件的所有 200 行,但它僅適用於前 192 行(第二次使用它時,當用戶要求更改文本文件時)。 1個文本行的格式應該是:

[rank][maleName][numMaleNameOccurences][femaleName][numFemaleNameOccurences]

(例如1 John 89,950 Mary 91,668

我了解您只發布了代碼片段,但這里有一些明顯的問題:

  • 您應該采取一切預防措施來避免緩沖區溢出:使用snprintf而不是sprintfstrcat
  • 計算文件名時popNames.year未初始化
  • 將正確的大小傳遞給fgets
  • 檢查sscanf()的返回值
  • 傳遞sscanf()%s字段的最大字符數。
  • 在將文件內容解析到 arrays 的第i個條目之前測試i的值,如果文件異常大,您將獲得未定義的行為

您的removeCommas()具有未定義的行為,因為您使用重疊字符串調用strcpy 這不太可能是您的段錯誤的原因,但這里有一個簡化和更正的版本:

int removeCommas(char *num) {
    int newNum = 0;
    char *p = num;

    while ((*num = *p++) != '\0') {
        if (*num != ',')
            num++;
        else
            newNum++;
    }
    return newNum;
}

這是main() function 的修改版本:

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *f1;
    int i;
    struct pNames popNames;
    char fileName[20];
    char maleSNumber[20];
    char femaleSNumber[20];
    char string[200];

    snprintf(fileName, sizeof fileName, "%dNames.txt", popNames.year);

    if ((f1 = fopen(fileName, "r")) == NULL) {
        printf("Cannot open %s\n", fileName);
        return -1;
    }
    i = 0;
    while (i < 200 && fgets(string, sizeof string, f1) != NULL) {
        if (sscanf(string, "%d %19s %19s %19s %19s",
                   &popNames.rank[i], 
                   popNames.maleName[i], maleSNumber,
                   popNames.femaleName[i], femaleSNumber) != 5) {
            printf("invalid input: %s", string);
            continue;
        }
        printf("%d %s %s %s %s\n",
               popNames.rank[i],
               popNames.maleName[i], maleSNumber,
               popNames.femaleName[i], femaleSNumber);
        removeCommas(maleSNumber);
        removeCommas(femaleSNumber);
        popNames.maleNumber[i] = atoi(maleSNumber);
        popNames.femaleNumber[i] = atoi(femaleSNumber);
        i++;
    }
    fclose(f1);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM