我正在尝试从文件中读取成对的非特定数量的整数。我还想跳过以#开头的行。我的问题是没有打印任何东西。当我尝试打印 fgets 返回的值时,它打印了 null。我真的很感激一点帮助,因为我对 C 不是很有经验,如果您不关注 feof,我将不胜感激,因为我已经阅读了为什么 feof 不好。
该文件如下所示:
#This must
#be
#skipped
1233 14432
4943928 944949
11233 345432
代码是:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
int start;
int end;
}path;
int main()
{
path* array;
array=malloc(5*sizeof(path));
if(array==NULL){
printf("Error allocating memoryn");
abort();
}
FILE* fd=fopen("File.txt","r");
if(fd==NULL){
printf("Error opening filen");
abort();
}
char buff[200];
int counter=0;
if(fopen==NULL){
printf("Error opening filen");
abort();
}
char c;
while(!feof(fd)||counter==6){
fgets(buff,200,fd);
c=buff[0];
if(strcmp(buff[0],"#")){
continue;
}
sscanf(&buff,"%d %d",array[counter].start,array[counter].end);
printf("%dt%dn",array[counter].start,array[counter].end);
counter++;
}
fclose(fd);
free(array);
return 0;
}
首先,回答问题的标题:fgets()
在文件末尾返回NULL
,而不是在文件为空时返回。
无论如何,您在while
循环中的测试是不正确的:
-
只有当您已经尝试读取并且已经到达文件末尾且读取失败时,
feof()
才会给出真实的结果。read
试图给你尽可能多的字节......或者根本没有,如果文件结束,则完全没有,获得文件结束条件的唯一方法是在您无法读取某些内容之后。最好检查fgets()
结果,因为它返回NULL
现在无法读取任何内容。(而不是在最后一次阅读中(所以while(fgets(buff, sizeof buff, fd) != NULL)
或者只是
while(fgets(buff, sizeof buff, fd))
会好得多。 另外,请参阅我如何使用
sizeof
运算符来使用所用缓冲区的大小,而不是在两个位置重复(并且容易出错(实际字节数。 如果您决定更改缓冲区的大小,则还需要更改要在fgets()
调用中读取的实际字节数,从而使忘记其中一个缓冲区的可能性成为遇到麻烦的机会。 -
您命令仅在
!feof()
或counter == 6
时保持循环(首先,这将使控件在计数器等于 6 时进入循环,无论您是否已达到 EOF,这都不是正确的(认为只有当两个条件都为 false 时才退出循环(这意味着feof()
返回 true并且也返回counter != 6
(, 你最好写:while(fgets(buff, sizeof buff, fd) && counter < max_number_of_iterations)
-
测试内容
if(strcmp(buff[0],"#"))
也是不正确的,因为
buff[0]
是一个字符(实际上,它是缓冲区中读取的第一个字符,"#"
是字符串文字(不是字符(可能您至少从编译器那里得到了警告,您没有说任何单词。 您最好测试两个字符的相等性,例如if (buff[0] == '#') /* this time '#' is a character literal, not a string literal */
-
在行中
if (fopen == NULL)
fopen
本身就是一个指向库函数的指针,fopen(3)
它不是你想要的(fopen
总是!= NULL
(,但是if (fd == NULL){
(你之前做过,所以你最好消除这个代码(
-
你定义一个
char c;
,然后将其初始化为buff
的第一个字符,然后你根本不使用它。 这对你的代码没有影响,但它的风格很糟糕,将来会让维护者感到困惑。 -
在行
sscanf(&buff, "%d %d", ....
中,您不需要传递&buff
,而buff
已经是一个字符指针。 最好将其传递buff
.n 但是,您需要将指针传递给您正在读取的变量,因此您需要将其更正为:sscanf(buff, "%d%d", &array[counter].start, &array[counter].end);
不这样做会产生难以追求的未定义行为,因为使用未初始化的变量(以及更多关于变量的指针(将使代码一开始可能会工作,但在投入生产一段时间后会失败......这是一个非常严重的错误。
更正所有这些错误后,您的代码应如下所示:
普鲁克
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N (5) /* I have defined this constant so you can
* change its value without having to go all
* the code for occurrences of it and
* changing those */
typedef struct{
int start;
int end;
} path;
int main()
{
path* array = malloc(N*sizeof(path)); /* better declare and init */
if(array==NULL){
printf("Error allocating memoryn");
abort(); /* have you tried exit(EXIT_FAILURE); ?? */
}
FILE* fd=fopen("File.txt","r");
if(fd==NULL){
printf("Error opening filen");
abort();
}
char buff[200];
int counter=0;
while(fgets(buff, sizeof buff, fd) && counter < N){
if(buff[0] == '#'){
continue;
}
sscanf(buff, "%d %d", &array[counter].start, &array[counter].end);
printf("%dt%dn", array[counter].start, array[counter].end);
counter++;
}
fclose(fd);
free(array);
return 0;
}
运行代码显示:
$ pru
1233 14432
4943928 944949
11233 345432
使用您发布的File.txt
。
最后,提示一下:
尽管你只想知道循环下降的原因,而不是为什么feof()
在这里没有用(以及许多其他你只是不要求和代码中错误的东西(,但如果确实是这种情况,你最好发布一个示例,仅显示页面建议的失败行为如何创建一个最小值, 您应该阅读的完整且可验证的示例,我建议您这样做。
您不应该在while
条件下检查feof()
。请参阅为什么"while ( !feof (file(("总是错误的?。
循环应为:
while (fcounter < 5 && fgets(buff, 200, fd))