0

i wrote following code for writing data to a file

#include<stdio.h>
struct bank{
    int accn;
    char last[10];
    char first[15];
    double bal;
};
int main()
{
    FILE *ptr;
    int i;
    struct bank cl={0," "," ",0.00};
    printf("%d %d %d\n",sizeof(struct bank),sizeof(int),sizeof(double));
    if ((ptr=fopen("banking_r.dat","wb"))==NULL)
        printf("file can't be opened");
    else
        {
            printf("enter account number,last name,first name and balance\n");
            fprintf(ptr,"%s%10s%10s %s\n","account no","last name","first name","balance");
            for (i=1;i<=2;i++)
            {
                fscanf(stdin,"%d%10s%10s%lf",&cl.accn,cl.last,cl.first,&cl.bal);
                fseek(ptr,(cl.accn-1)*sizeof(struct bank),SEEK_SET);
                printf("%d\n",sizeof(struct bank));
                fwrite(&cl,sizeof(struct bank ),1,ptr);
                fprintf(ptr,"\n");}
                fclose(ptr);
            }
            return 0;
        }

after it i entered data as

1 parker peter 23.89
2 parker arnold 23.45

then, i wrote following code to read the file

#include<stdio.h>
struct bank{
    int accn;
    char last[10];
    char first[15];
    double bal;
};
int main()
{
    FILE *ptr;
    struct bank cl;
    if ((ptr=fopen("banking_r.dat","rb"))==NULL)
        printf("file can not be opened");
    else {
        while(!feof(ptr)) {
            fread(&cl,sizeof(struct bank),1,ptr);
            //if (cl.accn!=0)
            printf("%-4d %-10s %-10s %-4.2f\n",cl.accn,cl.last,cl.first,cl.bal) ;
        }
    }
        return 0;
}

and the output i get is

1  parker peter 23.89
2  parker arnold 23.45
10 parker arnold 23.45

why did the last line get printed in output?

sujin
  • 2,813
  • 2
  • 21
  • 33
Amit Bisht
  • 131
  • 3
  • 1
    Please format your code correctly so it is readable. – Jabberwocky Jan 06 '14 at 09:42
  • After completing of write operation, please open the written file and cross verify your contents. Was it purely read error or write error? Could you post the written file contents obtained before doing read operation. – UserM Jan 06 '14 at 09:47
  • Why are you writing `\n` to the file? It's a binary file, not a text file, you don't need newlines between the structures. – Barmar Jan 06 '14 at 09:49
  • if i open the written file with notepad should it appear in the form in which i have entered data above .i merely thought that \n will try to arrange data in the file in new line. – Amit Bisht Jan 06 '14 at 09:59
  • i know there are a number of modes of opening a file .but as i am new to c language i want to know when should we use "rb","wb","ab" and when should we use "r","w","a". – Amit Bisht Jan 06 '14 at 10:07

3 Answers3

2

After the 2nd iteration of the while loop,

1  parker peter 23.89
2  parker arnold 23.45

the fread() statement has executed twice
i.e. now file position in moved ahead by sizeof(struct bank) twice

At this point you are expecting the while loop to terminate, however it executes one more time.

The third time it reads the remaining one byte i.e. the \n line-feed character (0x0a). Hence the 3rd row printed is simply the 2nd row with the first value set to 10 - the decimal representation of 0x0a, due to %-4d used in printf().

10 parker arnold 23.45

Refer to the answers to this question to see why feof() should NOT be used as done in your example to read-in the entire contents of a file.

Alternate approach :

  1. Start and loop as long as fread() returns non-zero (number of characters read-in).

  2. When fread() returns 0, use feof() to determine if its the end of the file of a read error.

Sample code snippet:

while( fread(&cl, sizeof(struct bank), 1, ptr) != 1 ) {
    // Another complete line read-in to 1 instance of struct bank, print it.
    printf("%-4d %-10s %-10s %-4.2f\n",cl.accn,cl.last,cl.first,cl.bal);
}

if(!feof(ptr)) {
    // flow comes here ONLY if while loop was terminated due to an fread() error
}
Community
  • 1
  • 1
TheCodeArtist
  • 21,479
  • 4
  • 69
  • 130
  • if after two iteration ptr will be at the last character of the file.then should it not encounter the end of file character in next iteration i am not getting why is it looping third time. – Amit Bisht Jan 06 '14 at 10:31
  • [feof(stream)](http://pubs.opengroup.org/onlinepubs/009695399/functions/feof.html) returns whether the **End of File** marker is set for the given stream which happens when a read of seek operation attempts to read in more characters past EOF. In other words, an earlier `fread()` of `fseek()` past the end of a file enables a subsequent call to `feof()` to return `TRUE`. The call to `feof()` itself does **NOT** perform any read/seek on the file to detect EOF. – TheCodeArtist Jan 06 '14 at 10:40
  • when ptr is at last character, read of the seek operation still try to search and read more characters even after encountering eof. this causes feof() to return true when it is expected to return false.this is waht i understand .is it correct? – Amit Bisht Jan 06 '14 at 11:01
  • To help understand, think of it in 2 steps. Step1 - When read and seek operations on a stream (`ptr` returned by `fopen()`) encounter the end of the file, they set an internal `EOF` flag. Step2 - Calling `feof()` simply checks this internal flag and returns if the end of file was reached or not; it does NOT try to actually read the file to check. – TheCodeArtist Jan 06 '14 at 11:12
  • Now i got it totally ..thanks alot @TheCodeArtist – Amit Bisht Jan 06 '14 at 15:39
0

using feof to find end of the file is wrong.. also using fgets and sscanf you can read the file. many other ways also available.

This code will work

#include<stdio.h>
#include <stdlib.h>
struct bank{
    int accn;
    char last[10];
    char first[15];
    double bal;
};
int main()
{
FILE *ptr;
char buf[128];
struct bank *cl = malloc(sizeof(struct bank));
if ((ptr=fopen("banking_r.dat","rb"))==NULL)
    printf("file can not be opened");

else {

    while(fgets(buf, sizeof(buf), ptr)) 
    {
        sscanf(buf, "%d %s %s %lf", &cl->accn,cl->last,cl->first, &cl->bal);
        printf("%-4d %-10s %-10s %-4.2f\n",cl->accn,cl->last,cl->first,cl->bal) ;
    }
}
free(cl);
return 0;
}
Community
  • 1
  • 1
sujin
  • 2,813
  • 2
  • 21
  • 33
0

@TheCodeArtist point out correctly. Just to add, you can make following changes to your code

#include<stdio.h>
struct bank{
    int accn;
    char last[10];
    char first[15];
    double bal;
};
int main()
{
    FILE *ptr;
    struct bank cl;
    if ((ptr=fopen("banking_r.dat","rb"))==NULL)
        printf("file can not be opened");
    else {
            fread(&cl,sizeof(struct bank),1,ptr); //Add before the while loop once

        while(!feof(ptr)) {
            //if (cl.accn!=0)
            printf("%-4d %-10s %-10s %-4.2f\n",cl.accn,cl.last,cl.first,cl.bal) ;

            fread(&cl,sizeof(struct bank),1,ptr); //And again to read more data. If EOF is encountered, this will cause it to break the loop
        }
    }
        return 0;
}
Kamran Khan
  • 1,367
  • 1
  • 15
  • 19