【问题标题】:Why my fscanf does not read the first string but reads the last line into the first string instead?为什么我的 fscanf 不读取第一个字符串,而是将最后一行读入第一个字符串?
【发布时间】:2022-11-30 20:59:59
【问题描述】:

我是包括代码在内的文件的初学者,所以请有人帮助我。这就是我的代码的样子。

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

#define first_ten_hours 7.99;
#define after_ten_hours 1.99;

double charges_all(int hour);
double charges_avg(int money, int hour_use);
double round_money(double sum);

int main()
{
    FILE *f_read, *f_write;

    f_read = fopen("usage.txt", "r");
    f_write = fopen("charges.txt", "w");

    if(f_read == NULL)
    {
        printf("Error to open the file.\n");
        return 1;
    }

    char date[2][10];
    char studenid[10][100];
    double using_hour[10];
    int current_line = 1;

    for(int i = 0; i < 11; i++)
    {
        if(current_line == 1)
        {
            fscanf(f_read, "%s %s", date[0], date[1]);
            current_line++;
        }
        else
        {
            fscanf(f_read, "%s %lf", studenid[i], &using_hour[i]);
            current_line++;
        }
    }

    current_line = 1;

    for(int i = 0; i < 11; i++)
    {
        if(current_line == 1)
        {
            printf("%s %s\n", date[0], date[1]);
            current_line++;
        }
        else
        {
            printf("%s %lf\n", studenid[i], using_hour[i]);
            current_line++;
        }
    }

    fclose(f_read);
    fclose(f_write);

    return 1;   
}

current_line = 1; 之后,我打印以查看问题所在。

这是我的文本文件。

12 2022
18010 4.5
92052 3.2
01051 7.4
11052 6.3
13052 5.5
01081 2.2
65052 1.3
94052 2.8
32052 3.7
41051 4.9

这是 printf 循环的输出:

41051 2022
18010 4.500000
92052 3.200000
01051 7.400000
11052 6.300000
13052 5.500000
01081 2.200000
65052 1.300000
94052 2.800000
32052 3.700000
41051 4.900000

但我想要的是第一行的第一个字符串是 12。

【问题讨论】:

  • 如果你想填充 0 到 9 等,请阅读 studenid[i-1]。

标签: c file scanf


【解决方案1】:

由于您编写 for 循环的方式,您正在访问 studenidusing_hour 数组的元素,这些元素在这些循环的最后一次迭代中越界(即当 i是 10——[10] 处的一个元素超过了用 10 个元素声明的数组的末尾)。这种“不良访问”导致未定义的行为,这可能(如您的情况所示)包括覆盖您之前读入 date 数组元素的值。

“快速修复”是将 [i] 索引(全部)更改为 [i - 1]。然而,更好的方法是将第一行的读取放在循环之外,然后为接下来的 10 行运行这些循环:

int main()
{
    FILE* f_read, * f_write;

    f_read = fopen("usage.txt", "r");
    f_write = fopen("charges.txt", "w");

    if (f_read == NULL)
    {
        printf("Error to open the file.
");
        return 1;
    }

    char date[2][10];
    char studenid[10][100];
    double using_hour[10];

    fscanf(f_read, "%9s %9s", date[0], date[1]); // Read first line differently
    for (int i = 0; i < 10; i++) // Run the loop ONLY 10 times ...
    {
        fscanf(f_read, "%99s %lf", studenid[i], &using_hour[i]);
    }

    printf("%s %s
", date[0], date[1]);
    for (int i = 0; i < 10; i++)
    {
        printf("%s %lf
", studenid[i], using_hour[i]);
    }

    fclose(f_read);
    fclose(f_write);

    return 1;
}

【讨论】:

  • 谢谢你的解释。我真的没有注意到并看那部分。
  • fscanf(f_read, "%s %s", date[0], date[1]); 没有宽度是不好的做法。更好的fscanf(f_read, "%9s %9s", date[0], date[1]);
  • @chux 公平评论 - 已编辑。
猜你喜欢
  • 1970-01-01
  • 2013-08-23
  • 1970-01-01
  • 2016-01-18
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 2013-03-31
相关资源
最近更新 更多