c - fscanf != eof Clang 编译器,异常行为

标签 c file clang

我有一个我无法理解的加重问题,

void file_count(FILE* stream,int* const num)
{
    int temp;
    while((fscanf(stream,"%d",&temp))!=EOF)
    {
        (*num)++;
    }
}

通过这段程序,我从一个文件中读取了其中的所有数字,每次我取一个数字时,计数器都会增加,这样我就可以计算出文件中有多少元素。

在此文件中有 6 个数字,但如果我运行此代码,计数器会飙升至 32777... 如果我用 gcc 编译它,没有问题,计数器如预期的那样是 6。这是clang的错误吗?这是我不知道的功能吗?

文件包含:

22 30 30 21 25 29

完整代码:

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

typedef char* string;
typedef struct student
{
    int flag;
    char name[25];
    char surname[25];
    char dorm[25];
    int* grades;
}
Student;

void check_input(const int argc,const string* const argv);
void check_file(FILE* stream);
void file_count(FILE* stream,int* const num);
void update_student(const string* const infos,Student* const student,const int grades,FILE* stream);
void print_student(FILE* stream,Student const student,const int grades);

int main(int argc, string argv[])
{
    check_input(argc,argv);
    FILE* one,* two;
    string info[]={"David","Malan","Mather"};
    Student student;
    int grades;
    one=fopen(argv[1],"r");
    check_file(one);
    file_count(one,&grades);
    update_student(info,&student,grades,one);
    fclose(one);
    two=fopen(argv[2],"w");
    check_file(two);
    print_student(two,student,grades);
    fclose(two);
    free(student.grades);
    system("cat out");
    return 0;
}

void check_input(const int argc,const string* const argv)
{
    if(argc!=3)
    {
        printf("\x1B[31mError: %s takes two arguments!\x1B[0m\n",argv[0]);
        exit(EXIT_FAILURE);
    }
}

void check_file(FILE* stream)
{
    if(stream==NULL)
    {
        printf("\x1B[31mError:invalid file.\x1B[0m\n");
        exit(EXIT_FAILURE);
    }
}

void file_count(FILE* stream,int* const num)
{
    int temp;
    printf("reading file...\n");
    while((fscanf(stream,"%i",&temp))!=EOF)
    {
        (*num)++;
    }
    printf("\x1B[33mthe value read were %i\x1B[0m\n",*num);
}

void update_student(const string* const infos,Student* const student,const int grades,FILE* stream)
{
    rewind(stream);
    student->grades=malloc(grades*sizeof(int));
    strcpy(student->name,infos[0]);
    strcpy(student->surname,infos[1]);
    strcpy(student->dorm,infos[2]);
    student->flag=0;
    for(int i=0;i<grades;i++)
    {
        fscanf(stream,"%i",&student->grades[i]);
    }
}

void print_student(FILE* stream,Student const student,const int grades)
{
    printf("Writing to file..\n");
    fprintf(stream,"%i %s %s %s ",student.flag,student.name,student.surname,student.dorm);
    for(int i=0;i<grades;i++)
    {
        fprintf(stream,"%i ",student.grades[i]);
    }
    printf("\x1B[32mFile successfully written..\x1B[0m\n");
}

最佳答案

您的代码很危险,因为不正确的文件会将其发送到无限循环中。

一旦带有 %dfscanf 发现无法解释为 int 的输入,该函数将返回零,而不会在消费上取得任何进展输入。因此,循环永远不会到达 EOF

只要输入被消耗,您就可以通过循环来解决这个问题:

while(fscanf(stream,"%d",&temp) == 1) {
    ...
}

现在您需要一种方法来告知调用者计数是否正确。如果达到 EOF,您可以返回 1,否则返回 0:

int file_count(FILE* stream,int* const num) {
    int temp, last;
    while((last = fscanf(stream,"%d",&temp)) == 1) {
        (*num)++;
    }
    return last == EOF;
}

I tried with fscaf==1 it still reaches 32777

发生这种情况是因为您没有在调用方中初始化 grades。您应该将其定义为int grades = 0,或者在file_count中进入循环之前添加*num = 0

关于c - fscanf != eof Clang 编译器,异常行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47838678/

相关文章:

linux - 如何在目录中查找二进制文件?

c - 大数组不会导致堆栈溢出

c++ - 具有 int 类型的枚举类的 printf 不适用于 clang

c - 无法理解 C 基础知识

c++ - 请问 `alignof(N) == sizeof(N)` 其中 N 是整型吗?

c - 图邻接 vector - 文件

c - 如何防止 gcc 预处理器删除行继续符?

java - nio.file 中默认的 StandardOpenOptions 是什么?

c# - Windows 上的时间戳类似于 Unix 时间戳和文件操作

c++ - 使用模索引自动矢量化?