André Hincu
André Hincu

Reputation: 427

bug when reading integers from a text file in C

I am a little bit desperate as I wasted my last 4 hours looking for a solution for a simple/stupid thing. I have a project in school in which I must read integers from a text file and then calculate the maximum of them. The thing is that these numbers are not necessarily separated by spaces, but also tabs ( \t ) or newlines (\n). I use the fscanf function to read my integers, but the problem is that after the last number I have a space in my file, so it reads 2 times the last number(I do not know why). Normally one would say "Just delete that space", but my teacher is going to test the program in several manners, and he warned us that the program must be robust (we have to be able to manage the spaces, \t, \n so we can read correctly the numbers, so this is why he left on purpose a space after the last number). Here is my code with the sample text:

FILE* file = NULL;
int *t = NULL, *new_size = NULL;
int temp, count;

file = fopen(argv[1],"r");
do
{
    fscanf(file,"%d",&temp);
    count++;

    new_size = (int*) realloc (t, count * sizeof(int));

    if (new_size != NULL)
    {
        t = new_size;
        t[count-1] = temp;
    }
    else
    {
        free(t);
        puts("Erreur d\'allocation memoire!\n");
        exit(1);
    }
} while(!feof(file));

fclose(file);

printf ("Numbers read\n:");
for(i = 0; i < count; i++)
{
    printf ("%d ", t[i]);
}

And my argument is a file named data.txt which contains: 3 1 7 0 4 9 6 150 and a \n at the end. So basically, my program reads the first 8 integers, and after that, since it is not EndOfFile, it still reads the last one (150) again. So my output is : Numbers read: 3 1 7 0 4 9 6 150 150

Could anyone tell me what I should do in order to make my program more robust? I need to manage the same type os error if there is a space at the end, or even a tab (\t). Any help would be appreciated!

Upvotes: 3

Views: 546

Answers (3)

Ramy Al Zuhouri
Ramy Al Zuhouri

Reputation: 21966

If the numbers are separated by a space, then you can read a space with fscanf and then an integer.To make the program robust, always see if fscanf fails.If it fails then stop reading integers, else continue.

bool good=true;
while(good)
{
    char separator;
    if(fscanf(file,"%c",&separator)==1)
    {
        if(separator!=' ' && separator!='\t' && separator!='\n')
        {
            fprintf(stderr,"Illegal character found in file");
            // You can choose if break the loop setting good to false, or
            // if to continue, this depends on your assignment
        }
        if(fscanf(file,"%d",&temp)==1)
        {
            < Push temp to your list/array >
        }
        else
        {
            good=false;
        }
    }
    else
    {
        good=false;
    }
}

Upvotes: 0

hmjd
hmjd

Reputation: 121971

Use the result of fscanf(), which returns the number of assignments made, as the terminating condition of the loop. After the loop check that EOF was reached and the loop did not terminate due to some other failure.

Upvotes: 2

Daniel Fischer
Daniel Fischer

Reputation: 183878

Check the return value of fscanf

if (fscanf(file,"%d",&temp) != 1) break;

and break out of the loop if it doesn't find a number anymore. fscanf returns the number of successful conversions, and that should be used for error checking and handling.

Upvotes: 2

Related Questions