cfilebinaryfilesfseekfeof

I have a trouble in counting amount of "items" in binary file. C


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;
}

Solution

  • 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 */
        }
    }