【问题标题】:How does fread() in C work inside a for loop?C 中的 fread() 如何在 for 循环中工作?
【发布时间】:2021-06-06 15:41:31
【问题描述】:

我是 C 编程新手,但我需要它来读取我在下面描述的一些二进制文件。

印度气象局 (IMD) 在其website 中提供了 .GRD 文件中的历史天气数据。他们还提供了示例 C 代码来读取这些文件。从他们的示例 C 代码中,我编写了以下代码,该代码提取了 1980 年 4 月 15 日在印度 31x31 网格上记录的每日最低气温。

/* This program reads binary data for 365/366 days and writes in ascii file. */ 
#include <stdio.h>
int main() {
float t[31][31]; 
int i,j ,k; 
FILE *fin,*fout; 
fin = fopen("C:\\New folder\\Mintemp_MinT_1980.GRD","rb"); // Input file 
fout = fopen("C:\\New folder\\MINT15APR1980.TXT","w"); // Output file 
fprintf(fout,"Daily Minimum Tempereture for 15 April 1980\n");
if(fin == NULL) {
    printf("Can't open file");
    return 0;
}
if(fout == NULL) {
    printf("Can't open file");
    return 0; 
} 
for(k=0 ; k<366 ; k++) {
    fread(&t,sizeof(t),1,fin); 
    if(k == 105) {
        for(i=0 ; i < 31 ; i++) {
            fprintf(fout,"\n") ;
            for(j=0 ; j < 31 ; j++) 
                fprintf(fout,"%6.2f",t[i][j]);
        } 
    } 
} 
fclose(fin);
fclose(fout);
return 0; 
}
/* end of main */ 

可以从IMD website 下载文件Mintemp_MinT_1980.GRD,方法是选择1980 年作为最低温度。

我不明白的是,fread() 函数实际上是如何在循环 for(k=0 ; k&lt;366 ; k++) 内的行 fread(&amp;t,sizeof(t),1,fin) 中工作的。显而易见,这里 fread() 的参数不依赖于循环变量k,因此它应该为每个k 读取相同的数据到矩阵t[31][31]。但是,我检查过,令人惊讶的是,该程序提取的数据对于 if(k == 105) 行中的 k 的不同值是不同的,例如,为 k == 105k == 32 提取的数据是不同的。

如果有人能解释上述内容,我将不胜感激。

【问题讨论】:

  • FILE * fin 跟踪其在文件中的位置。从文件中读取的所有文件操作都将从当前位置开始读取,并将位置推进读取的字节数。
  • @WilliamPursell,非常感谢您的回复!你能再解释一下吗?在上面的程序中,文件指针fin 的值首先设置在fin = fopen("C:\\New folder\\Mintemp_MinT_1980.GRD","rb"); 行中。你的意思是fin 的值被fread(&amp;t,sizeof(t),1,fin); 行中的函数fread() 修改了吗?那么,是不是意味着fread(&amp;t,sizeof(t),1,fin);同时修改了矩阵t和指针fin的值?
  • 一些不相关的编码建议...如果可以避免,请不要在打开文件时使用绝对路径——如果从数据所在的目录运行代码,则可以使用没有路径的文件名。使用 fread 时,检查其返回值以确保实际读取了数据。然后,如果 fread 失败,要么在 fread 之后终止循环(使用 break、return 或 exit),要么在循环条件下包含返回值。这样,如果文件比您预期的短,您就不会得到一团糟的错误输出或无限循环。
  • fread被调用时,fin的值没有改变,但是fin所指向的对象修改了。 FILE * 的常见实现是一种数据结构,其中包含(除其他外)文件描述符、缓冲区和有关缓冲区的一些元数据。当您第一次调用fread 时,数据被读取并存储在缓冲区中。如果您进行少量读取,那么缓冲区很可能包含比您的fread requested 更多的数据。元数据已更新,因此下一个 fread 仅返回先前从缓冲区读取的数据。
  • @WilliamPursell 非常感谢您的回复!它帮助我比以前更好地理解了这个问题。

标签: c loops for-loop fread weather


【解决方案1】:

文件包含顺序数据。所有文件操作符都基于这样一个前提,即无论您对文件执行什么操作,通常都是按顺序执行的。

因此,当您读取数据,然后读取更多数据时,您将获得文件的连续块。 FILE 数据类型和操作系统本身都会为您做很多事情,包括跟踪您在文件中的当前位置以及在内存中进行块缓冲以提高性能。

如果您想重新读取相同的数据,或在文件中跳转,您需要在下次读取之前使用 fseek() 更改文件中的位置。

【讨论】:

  • 非常感谢您的回复!现在我很清楚了。
  • 用投票和接受答案表示感谢。 :)
猜你喜欢
  • 2016-01-01
  • 2017-05-13
  • 2016-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
相关资源
最近更新 更多