0

I want to count the amount of "items" in binary file using feof and fseek functions. I have a binary file with names of people in chars and their salaries in floats. before each name there is an int that represents the amount of chars in the name. for example my file could look like this (but without spaces and without \0's): 5danny5000.00 4lena2500.50

one item is "4lena2500.50" for example.

in my code, the while loop does not stops. what can I do to repair the problem?

thanks!

int count_items(FILE* file)
{
    int count=0;
    int curr_name_len;
    while (!feof(file))
    {
        fread(&curr_name_len, sizeof(int), 1, file);
        fseek(file, (curr_name_len * sizeof(char)) + sizeof(float), SEEK_CUR);
        count++;
    }
    rewind(file);
    return count;
}
Pentakorr
  • 25
  • 3
  • What have you tried to debug this? A good idea might be too use a debugger and check which integer you read in each iteration. – Marcus Müller Jun 03 '23 at 08:50
  • Also, I assume the 5 in `5danny` is bye with the value 5 and not an ASCII character showing the character `'5'`, right? If that is the case, your example is misleading. If that's not the case, your code is wrong. – Marcus Müller Jun 03 '23 at 08:53
  • the fread(&curr_name_len, sizeof(int), 1, file); works in the first 2 iterations: first iteration is 5, second is 4, and then the while loop should break, but after that is continues to be 4 in every next iteration. the value of 5 in the file is int. I understand that the code is wrong, because of that I wrote the question. Im asking for help to understand what wrong with it and how to fix it. – Pentakorr Jun 03 '23 at 08:55
  • 1
    fseek value is 0 in every iteration – Pentakorr Jun 03 '23 at 09:04

1 Answers1

0

feof doesn't check whether the file is at the EOF, it checks whether the eof-indicator of the file was set on a previous operation. fseek allows to seek to an arbitrary position (if the operating system and the file system supports this) to allow for example to write with holes inside of the file, which is useful if you intend to write things inbetween. Thus the eof-indicator is set after the fread-call, but is cleared after your fseek-call. So this should work:

int count_items(FILE* file)
{
    int count=0;
    int curr_name_len;
    for (fread(&curr_name_len, sizeof(int), 1, file);
         !feof(file);
         fread(&curr_name_len, sizeof(int), 1, file))
    {
        fseek(file, (curr_name_len*sizeof(char))+sizeof(float), SEEK_CUR);
        count++;
    }
    rewind(file);
    return count;
}

or if you don't like that style:

int count_items(FILE* file)
{
    int count=0;
    int curr_name_len;

    fread(&curr_name_len, sizeof(int), 1, file);
    while (!feof(file))
    {
        fseek(file, (curr_name_len*sizeof(char))+sizeof(float), SEEK_CUR);
        count++;
        fread(&curr_name_len, sizeof(int), 1, file);
    }
    rewind(file);
    return count;
}

or less structured, but more clearly:

int count_items(FILE* file)
{
    int count=0;
    int curr_name_len;

    while (true);
    {
        if (sizeof(int) != fread(&curr_name_len, sizeof(int), 1, file)))
        {
            break;
        }

        fseek(file, (curr_name_len*sizeof(char))+sizeof(float), SEEK_CUR);
        count++;
    }

    if (feof(file))
    {
        rewind(file);
        return count;
    }

    if (ferror(file))
    {
        /* error handling */
    }
    else
    {
        /* fatal error handling */
    }
}
caulder
  • 83
  • 8