【发布时间】: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<366 ; k++) 内的行 fread(&t,sizeof(t),1,fin) 中工作的。显而易见,这里 fread() 的参数不依赖于循环变量k,因此它应该为每个k 读取相同的数据到矩阵t[31][31]。但是,我检查过,令人惊讶的是,该程序提取的数据对于 if(k == 105) 行中的 k 的不同值是不同的,例如,为 k == 105 和 k == 32 提取的数据是不同的。
如果有人能解释上述内容,我将不胜感激。
【问题讨论】:
-
FILE *
fin跟踪其在文件中的位置。从文件中读取的所有文件操作都将从当前位置开始读取,并将位置推进读取的字节数。 -
@WilliamPursell,非常感谢您的回复!你能再解释一下吗?在上面的程序中,文件指针
fin的值首先设置在fin = fopen("C:\\New folder\\Mintemp_MinT_1980.GRD","rb");行中。你的意思是fin的值被fread(&t,sizeof(t),1,fin);行中的函数fread() 修改了吗?那么,是不是意味着fread(&t,sizeof(t),1,fin);同时修改了矩阵t和指针fin的值? -
一些不相关的编码建议...如果可以避免,请不要在打开文件时使用绝对路径——如果从数据所在的目录运行代码,则可以使用没有路径的文件名。使用 fread 时,检查其返回值以确保实际读取了数据。然后,如果 fread 失败,要么在 fread 之后终止循环(使用 break、return 或 exit),要么在循环条件下包含返回值。这样,如果文件比您预期的短,您就不会得到一团糟的错误输出或无限循环。
-
当
fread被调用时,fin的值没有改变,但是fin所指向的对象被修改了。 FILE * 的常见实现是一种数据结构,其中包含(除其他外)文件描述符、缓冲区和有关缓冲区的一些元数据。当您第一次调用fread时,数据被读取并存储在缓冲区中。如果您进行少量读取,那么缓冲区很可能包含比您的freadrequested 更多的数据。元数据已更新,因此下一个fread仅返回先前从缓冲区读取的数据。 -
@WilliamPursell 非常感谢您的回复!它帮助我比以前更好地理解了这个问题。
标签: c loops for-loop fread weather