从文件读取到struct到终端,分段错误

时间:2015-02-10 22:15:03

标签: c

我正在尝试从具有类似线条的文本文件中读取(其中大约200个,其中有一些空行)。 我知道某些东西可能是未初始化的,但我对它是什么一无所知。我现在要做的就是从文件中读取并将其打印到终端窗口。

我真的希望你能帮助我! 谢谢。

几行文本文件的示例:

Fre     19/07 18.30     AGF - FCM      0 - 2     9.364   
Lor     20/07 17.00     VFF - RFC      2 - 2     4.771   
Son     21/07 14.00     OB - SDR       1 - 1     7.114   

我的结构看起来像这样:

struct match {
    char weekday[MAX_NAME_LEN];
    int day;
    int month;
    int hours;
    int minutes;
    char home_team[MAX_NAME_LEN];
    char away_team[MAX_NAME_LEN];
    int home_team_goals;
    int away_team_goals;
    int spectators_thds;
    int spectators_hdrs;
};

我的read_file函数如下所示:

void read_file(struct match *match) {
    FILE *fp;
    int i;
    fp = fopen("superliga-2013-2014", "r"); 
    while (!fp) {
        error("Cannot open file.");
    }

    struct match *matches = (struct match *) malloc(sizeof(match) * MAX_MATCHES);
    while(!feof(fp)) {
        fscanf(fp, " %s %i/%i %i.%i %s - %s %i - %i %i.%i \n", 
               matches[i].weekday, &matches[i].day, &matches[i].month, &matches[i].hours,
               &matches[i].minutes, matches[i].home_team, matches[i].away_team,
               &matches[i].home_team_goals, &matches[i].away_team_goals,
               &matches[i].spectators_thds, &matches[i].spectators_hdrs);
    }
    fclose(fp);
    free(fp);
}

我的main函数看起来像这样:

int main(int argc, char *argv[]) {
    int i;
    struct match *matches;
    void read_file(struct match *matches);
    for (i = 0; i < MAX_MATCHES; ++i) {
        printf(" %s %i/%i %i.%i %s - %s %i - %i %i.%i ",
               matches[i].weekday, matches[i].day, matches[i].month, matches[i].hours,
               matches[i].minutes, matches[i].home_team, matches[i].away_team,
               matches[i].home_team_goals, matches[i].away_team_goals,
               matches[i].spectators_thds, matches[i].spectators_hdrs);
    }

    return 0;
}

它编译时没有问题,但是当我尝试运行它时,我得到Segmentation fault。然后我使用Valgrind,它给了我这个信息:

==12799== Use of uninitialised value of size 8
==12799==    at 0x4007B8: main (in /home/dradee/Dropbox/UNI/Programmering/C/readfile)
==12799== 
==12799== Invalid read of size 4
==12799==    at 0x4007B8: main (in /home/dradee/Dropbox/UNI/Programmering/C/readfile)
==12799==  Address 0x34 is not stack'd, malloc'd or (recently) free'd
==12799== 
==12799== 
==12799== Process terminating with default action of signal 11 (SIGSEGV)
==12799==  Access not within mapped region at address 0x34
==12799==    at 0x4007B8: main (in /home/dradee/Dropbox/UNI/Programmering/C/readfile)

1 个答案:

答案 0 :(得分:3)

  1. Don't施放malloc()

    struct match *matches = (struct match *) malloc(sizeof(match) * MAX_MATCHES);
    

    更好

    struct match *matches = malloc(sizeof(struct match) * MAX_MATCHES);
    
  2. 检查malloc()的结果,失败时返回NULL

  3. 不要检查!feof(),因为它是always wrong,所以请更改此

    while(!feof(fp))
    

    while (fscanf(fp, " %s %i/%i %i.%i %s - %s %i - %i %i.%i \n", 
           matches[i].weekday, &matches[i].day, &matches[i].month, &matches[i].hours,
           &matches[i].minutes, matches[i].home_team, matches[i].away_team,
           &matches[i].home_team_goals, &matches[i].away_team_goals,
           &matches[i].spectators_thds, &matches[i].spectators_hdrs) == 11)
    
  4. 这是重要:您在MAX_MATCHES循环中迭代到printf(),当您不一定阅读MAX_MATCHES时。因此,您需要保留成功读取项目的计数,并在第二个for循环中使用它。

    例如,您可以将读取项目的数量从read_file返回到main,并使用它。

    您已在read_file()中设置了一个计数器,但请阅读下一点。

  5. 您永远不会在i的{​​{1}}循环中增加while

  6. 这是非常受欢迎的

    read_file()
    你是说

    吗?
    void read_file(struct match *matches);
    
  7. 这是不正确的

    read_file(matches);
    

    你已经free(fp); 这是发布fclose(fp)资源的正确方法,FILE *会导致未定义的行为,可能是分段错误,或任何事情否则,因为它未定义。

  8. 这没有任何意义

    free()

    你的意思

    while (!fp) { ... }
    
  9. 您的if (!fp) { ... } 函数只有localy会分配read_file(),然后您无法从structs访问它们,您可以做的就是这个

    main()

    然后是您的int read_file(struct match **matches) { FILE *fp; int i; struct match *match; if (matches == NULL) return 0; *matches = NULL; fp = fopen("superliga-2013-2014", "r"); if (!fp) { error("Cannot open file."); return 0; } match = malloc(sizeof(struct match) * MAX_MATCHES); if (match == NULL) return 0; while ((fscanf(fp, " %s %i/%i %i.%i %s - %s %i - %i %i.%i \n", match[i].weekday, &match[i].day, &match[i].month, &match[i].hours, &match[i].minutes, match[i].home_team, match[i].away_team, &match[i].home_team_goals, &match[i].away_team_goals, &match[i].spectators_thds, &match[i].spectators_hdrs) == 11) && (i < MAX_MATCHES)) { i++; } fclose(fp); *matches = match; return i; }

    main()