2

I am writing a code which reads a binary file, read each struct fields seperatly, prints out the results, then stop when the file reading reaches the end.

FYI - The binary file contains multiple records with same struct fields

I could figure out how to do it using feof. but, I would like to run this code using only fread() function(No feof). I was told to find fread return value to detect the end of the file but I am struggling how to do it.

If there are alternate ways to do it Please help me out. below is the code

#define MAX_CT 11
#include<stdio.h>
#include<stdlib.h>

//struct variables
struct test
{
    short int a;
    double b;
    short int c;
    int d;
    float e;
    unsigned short f;
    unsigned char g;
    double h;
    unsigned long i;
    short int j;
    char k;
    int l;
    int m;
    int n;
    char o[MAX_CT];
    char p;
    double q;
};

int main(int argc, char **argv)
{
    struct test a1;
    
    FILE *fp;
    
        //Input Checking Error
        if (argc < 2) {
                fprintf(stderr, "Usage: %s input_file\n", argv[0]);
                exit(1);
        }
    
        //binary file to open for reading
        fp = fopen(argv[1], "rb");
    
        //File Checking Error
        if (fp == NULL){fprintf(stderr, "Cannot open the file %s\n", 
                        argv[1]);
                        exit(1);
        }
    
    //Print the field names
    printf("a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q \n");
    
    //Allocate values into struct using fread
    
    while(1) 
    {
        fread(&a1.a, sizeof(a1.a), 1, fp);
        fread(&a1.b, sizeof(a1.b), 1, fp);
        fread(&a1.c, sizeof(a1.c), 1, fp);
        fread(&a1.d, sizeof(a1.d), 1, fp);
        fread(&a1.e, sizeof(a1.e), 1, fp);
        fread(&a1.f, sizeof(a1.f), 1, fp);
        fread(&a1.g, sizeof(a1.g), 1, fp);
        fread(&a1.h, sizeof(a1.h), 1, fp);
        fread(&a1.i, sizeof(a1.i), 1, fp);
        fread(&a1.j, sizeof(a1.j), 1, fp);
        fread(&a1.k, sizeof(a1.k), 1, fp);
        fread(&a1.l, sizeof(a1.l), 1, fp);
        fread(&a1.m, sizeof(a1.m), 1, fp);
        fread(&a1.n, sizeof(a1.n), 1, fp);
        fread(&a1.o, sizeof(a1.o), 1, fp);
        fread(&a1.p, sizeof(a1.p), 1, fp);
        fread(&a1.q, sizeof(a1.q), 1, fp); 
        
        //if file reading reaches the end, stop the loop 
        //(without feof, is there any other way to finish the loop using fread()????

        if(feof(fp)){
            break;
        }
        
    //Print results
    printf("%d, %f, %i, %d, %f, %d, %d, %f, %lu, %i, %i, %i, %i, %x, %s, %c, %f\n", a1.a, a1.b, 
           a1.c, a1.d, a1.e, a1.f, a1.g, a1.h, a1.i, a1.j, a1.k, a1.l, a1.m, a1.n, a1.o, a1.p, 
           a1.q);
    
    }
    
    //close the file
    fclose(fp);
        
    return 0;
}

1 Answers1

-5

i prefer

int c = fgetc(filehandle);

so, I can check:

int c = fgetc(filehandle);
if (c == EOF) {
  fclose(filehandle);
  exit(0);
}

note: for EOF, you can alternatively use '\0'. don't use exit(0); in modern programs. Try to design a program logic, that only need "return ERROR;" or "return SUCCESS;" Because you ran into some trouble if "exit" is nested, and you don't know the position in source. So, good idea is, to "strace", and debug, before you deploy your work.

Jens
  • 57
  • 8
  • 2
    _"for EOF, you can alternatively use '\0'."_: huh(!?) – Jabberwocky Sep 09 '21 at 05:43
  • yes, \0 (not ***NULL*** or ***nullptr***) has different things - e.g. mark a char array (char *) in C, and C++ as null-terminated string, mark the (E)nd(O)f(F)ile - EOF. during execution of a binary application, it is used to start counters - computers begin starting to count at 0, not 1. so the numbers have +1 if you calculate with them. \0 can mark a empty database record, and so on, and so forth, ... since '0' is other char as '\0' - caution on the back-slash !!! – Jens Sep 09 '21 at 06:29
  • 3
    @Jens `EOF` is definitely different from `'\0'`. `'\0'` does definitely not mark the end of file. The statement _"for EOF, you can alternatively use '\0'"_ is wrong. Read this: https://stackoverflow.com/a/4705984/898348. – Jabberwocky Sep 09 '21 at 06:52
  • 4
    The C standard tells us: 7.21.1#3: "The macros are .... `EOF` which expands to an integer constant expression, with **type int and a negative value**, that is returned by several functions to indicate end-of-file, that is, no more input from a stream;" Your suggestion to use `0` is clearly wrong as 0 is not a negative value and cannot be separated from possible `char` values returned by various functions like `fgetc` you use in your answer – Gerhardh Sep 09 '21 at 07:05