Fscanf还是Fgets?逐行读取文件

8

我需要用C语言编写一个程序,读取包含多行文本的文件,每行都包含两个变量:一个数字(%f)和一个字符串:

EX: file.txt
============
24.0 Torino
26.0 Milano
27.2 Milano
26.0 Torino
28.0 Torino
29.4 Milano

这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[])
{
    int r, line = 0, found = 0;
    float temp, t_tot = 0;
    char loc[32];


    FILE *fp;

    fp = fopen(argv[1], "r");

    if (fp == NULL)
    {
        printf ("Error opening the file\n\n'");
        exit(EXIT_FAILURE);
    }

    if (argc == 3)
    {
        r = fscanf(fp, "%f %s\n", &temp, loc);

        while (r != EOF)
        {
            line++;

            if (r == 2)
            {
                if(strcmp(argv[2], loc) == 0)
                {
                    t_tot += temp;
                    found++;
                }
            }
            else
                printf ("Error, line %d in wrong format!\n\n", line);
        }

        printf ("The average temperature in %s is: %.1f\n\n", argv[2], (t_tot/found);
    }

}

该程序需要读取所有行并查找我在argv [2]中写的城市。然后它将告诉我该城市的平均温度,并通知我文件中是否有格式错误的行。
该程序对我来说编译正确,但屏幕上没有任何输出……我该如何解决?在这种情况下使用fscanf正确吗,还是更好使用fgets
我是一名学生,请以“学术”的方式解决它 :)
4个回答

13

有几件事情。

首先,您必须使用fclose()。
其次,您的代码需要fscan()文件中的每一行。不仅要在while()循环之前,而且在每个while循环内部,您都需要进行fscan()以进行下一个迭代。
第三,在计算平均温度时,您并没有计算所有找到的温度的平均值,而是计算了所有找到的温度的总和。通过在最后的printf()中将“t_tot”更改为“(t_tot / found)”,可以解决这个问题。

最后,我不确定为什么您没有得到任何输出。您的输入方式类似于“myprogram file.txt Milano”,对我有效。无论如何,以下是经过编辑的代码:

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

int main (int argc, char *argv[])
{
    int r, line = 0, found = 0;
    float temp, t_tot = 0;
    char loc[32];

    FILE *fp;
    fp = fopen(argv[1], "r");

    if (fp == NULL)
    {
        printf ("Error opening the file\n\n'");
        exit(EXIT_FAILURE);
    } else {

        if (argc == 3)
        {
            r = fscanf(fp, "%f %s\n", &temp, loc);
            while (r != EOF)
            {
                line++;
                if (r == 2)
                {
                    if(strcmp(argv[2], loc) == 0)
                    {
                        t_tot += temp;
                        found++;
                    }
                }
                else
                    printf ("Error, line %d in wrong format!\n\n", line);
                r = fscanf(fp, "%f %s\n", &temp, loc);
            }
            printf ("The average temperature in %s is: %.1f\n\n", argv[2], (t_tot / found));
        }

    fclose(fp);

    }
}

3

您必须在while循环内部放置fscanf行。

    while (1)
    {
        r = fscanf(fp, "%f %s\n", &temp, loc);
        if( r == EOF ) 
           break;
        .........................
    }

最后关闭文件。

如果您正在使用fgets,请按以下方式更改

  char s[256];
  while( fgets( s, 256, fp) != NULL )
  {
     sscanf( s, "%f %s", &temp, loc);
     .............
  }

3

你的代码没有像应该那样在循环中调用fscanf: 只读取了一次,然后如果文件为空,程序就立即退出,或者无限循环。

你应该将fscanf的调用移动到while循环内部。一种常见的编码方式是将赋值放在循环头中,像这样:

while ((r = fscanf(fp, "%f %s\n", &temp, loc)) != EOF) {
    ...
}

谢谢您的回答。我刚刚意识到我的错误!如果我想用fgets而不是fscanf来制作另一个解决方案,我该怎么做? - Lc0rE
1
@l_core 你需要改变一些东西:首先,你需要为 fgets 准备一个缓冲区;然后在循环中将检查 EOF 替换为检查 NULL;最后,你需要手动解析缓冲区,找到第一个空格,将初始部分提供给 atof,并将其余部分复制到 strdup 中。 - Sergey Kalinichenko

1

将代码修改为这样...只需在while语句中再加入一个fscanf即可。

if (argc == 3)
{
 r = fscanf(fp, "%f %s\n", &temp, loc);
  while(r != EOF )

    {
        r = fscanf(fp, "%f %s\n", &temp, loc);  
        line++;

        if (r == 2)
        {
            if(strcmp(argv[2], loc) == 0)
            {
                t_tot += temp;
                found++;
            }
        }
        else
            printf ("Error, line %d in wrong format!\n\n", line);
    }

    printf ("The average temperature in %s is: %.1f\n\n", argv[2], t_tot);
}

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接