Daycopo
Daycopo

Reputation: 188

fgets where the number of char read is bigger than the size of the storage

I'm looking at a code to learn things and I saw something like this :

void funRead(){
     char str[80];
     FILE *fi;
     fi = fopen("file","r");
     while(!feof(fi)){
        fgets(str, 200, fi);
        // do things
     }
     fclose(fi);
}

And it works! (It's quite a big code) I didn't understand why it was working so I tried to reproduce it (just this part, pretty much just the code above) and my program crashes (I'm doing it on Eclipse). It only works when I write

fgets(str, 80, fi);

Or another number < 80, otherwise it won't work.

Did I miss something?

EDIT : Screen capture of the part of the program I'm talking about https://gyazo.com/c8847ccc36bbbe7a406a3260db8dd358 Lines 4 & 26

Upvotes: 0

Views: 839

Answers (2)

jat
jat

Reputation: 106

In your code you are defining a character array with size of 80 characters

char str[80];


fgets(str, 200, fi);

Above statement means that it is reading 200 characters from file "fi" in the character array "str" of size 80. You cannot copy 200 characters in an array of size 80.

Either make character array bigger or read 80 or less characters at a time from the file.

EDIT: The reason program crashes is because it is accessing illegal memory locations. This does not mean it will necessary crash if you index a location which is greater than size of array, It just means it can crash if it is not allowed to access that memory location. So that is the reason, the code you mentioned is probably working(purely on chance), although that 200 part is wrong. If it ran then run it multiple times it will probably crash atleast once.

Upvotes: 2

Pablo
Pablo

Reputation: 13570

fgets(str, 200, fi); is indeed wrong, because it is telling fgets to read up to 199 characters when in reality str can store up to 79 characters (not including the '\0'-terminating byte), that's why it "works"1 with fgets(str, 80, fi);.

In general it's a good idea to use sizeof like this2:

char str[80];
fgets(str, sizeof str, fi);

With sizeof you will get the correct size, even if you later decide to change the size of str.

One thing that is really wrong is:

while(!feof(fi))
{
    ...
}

What the code should do is:

while(fgets(str, sizeof str, fi))
{
    // do things
}

that's the proper way to read the whole file.


Fotenotes

1I put works in quotes because the way the code checks when to stop reading is incorrect. However fgets(str, 80, fi) is the correct call.

2Note that sizeof will give the correct size only if str is an array. If it is a pointer and you allocated memory for it, then you cannot use sizeof, for example:

size_t len = 80;
char *str = malloc(len);
if(str == NULL)
{
    // error handling
}

fgets(str, len, fi); // <-- do not use sizeof here, but the variable

Upvotes: 3

Related Questions