【问题标题】:Why isn't my loop reaching the end of the file?为什么我的循环没有到达文件末尾?
【发布时间】:2014-10-27 18:48:17
【问题描述】:

我正在 Windows 8.1 上的 Visual Studio 2012 中构建一个应用程序,该应用程序使用线性回归来计算/预测特定年份的世界人口。正在从文本文件中读取数据,程序使用该数据计算线性回归。

文本文件内容:

0.001 0.200
1.000 0.310
1.500 0.450
1.650 0.500
1.750 0.791
1.800 0.978
1.850 1.262
1.900 1.650
1.927 2.000
1.950 2.519
1.955 2.756
1.960 2.982
1.965 3.335
1.970 3.692
1.975 4.068
1.980 4.435
1.985 4.831
1.990 5.263
1.995 5.674
2.000 6.070
2.005 6.454
2.008 6.707
2.009 6.800

我遇到的问题是,当我遍历文件以将数据存储在结构数组中时,在完全读取文件之前出现异常。

这是我遇到问题的功能:

int ReadFile(char* filename) {
    char line[20];
    int i = 0;
    int recordCount = 0;
    FILE* file = NULL;
    Population* wp[] = {0};

    file = fopen(filename, "r"); /* open text file for reading */
    if (file != NULL) {
        printf("FILE OPENED FOR READING\n");
        while (fgets(line, 20, file) != NULL) {
            fscanf(file, "%s", line);
            recordCount++;
        }
        fclose(file);
        printf("There are %d records.\n\n", recordCount);
        //*wp = (Population*)malloc(sizeof(Population) * recordCount);
        file = fopen(filename, "r");
        for (i = 0; i < recordCount; i++) {
            wp[i] = (Population*)malloc(sizeof(Population));
            fscanf(file, "%5f", &wp[i]->year);
            printf("%f ", wp[i]->year);
            fscanf(file, "%5f", &wp[i]->population);
            printf("%f\n", wp[i]->population);
        }
    }
    fclose(file);
    return 1;
}

最后一个 for 循环(我为结构分配空间的那个)是使我的程序崩溃的循环。在第 4 次崩溃之前,我可以获得大约 3 次迭代。

抛出异常:

First-chance exception at 0x7741D7E0 (ntdll.dll) in worldpopulation.exe: 0xC0000005: Access violation reading location 0x871EADD7.
Unhandled exception at 0x7741D7E0 (ntdll.dll) in worldpopulation.exe: 0xC0000005: Access violation reading location 0x871EADD7.

该异常似乎是由文件指针损坏引起的,但我不知道为什么。谁能帮我弄清楚为什么最后一个循环会导致崩溃?谢谢!

【问题讨论】:

  • 为什么第一个malloc被注释掉了?
  • 您永远不会为实际数组分配。试试这个:Population* wp[2000]; 看看你是否仍然得到错误。
  • @Hogan 这确实是问题所在,但我使用双指针让它工作。初始大小应该是recordCount,但因为它是一个变量,所以我不能将它用作大小。但是 +1 帮助我隔离了问题。
  • 在 C 中,x *var[];x **var; 之间没有区别,除了 C 允许您使用的语法。
  • 关于这些行:while (fgets(line, 20, file) != NULL) { fscanf(file, "%s", line);第一行是读取文件的第一行,第二行是读取文件的第二行。因此代码仅适用于每隔一行,但是,作为旁注, fscanf() 的格式参数需要有一个前导 ' ',因此可以跳过空格。否则会被行尾的 '\n' 阻塞。从那里开始,事情会变得非常糟糕。建议从代码中删除 fscanf() 行。

标签: c loops visual-studio-2012 file-io struct


【解决方案1】:
while (fgets(line, 20, file) != NULL) {
    fscanf(file, "%s", line);
    recordCount++;

您正在阅读两次并数一次。首先使用fgets,然后使用fscanf。我猜你想摆脱fscanf

另外一个问题是:

Population* wp[] = {0};
[...]
wp[i] = (Population*)malloc(sizeof(Population));

访问wp[0] 以外的任何内容都是非法的。同样,我猜你想分配类似的东西:

Population** wp = malloc(recordCount * sizeof *wp);

您两次读取文件的方式效率不高。您应该第一次使用fscanfs,并根据需要使用realloc 扩展wp

【讨论】:

  • @cricutar -- realloc 很慢。特别是。因为代码计算了行数。
  • @Hogan 你确定摊销realloc(每次加倍大小)比执行额外的系统调用(额外的打开、读取和关闭)和额外的解析要慢吗?
  • 我明白你的意思——你说不要先计算行数,删除那部分并在需要时使用 realloc 。我同意这一点。
  • @cnicutar 在修复双指针和删除数组声明之后,我得到了我想要的输出。非常感激! +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-25
  • 2020-09-09
相关资源
最近更新 更多