0

I have following problem:

void edit(FILE *f, int cnt)
{
    int i = 0;
    int offset = 0;
    rewind(f);

    schedule todo;
    schedule *p = &todo;

    fprintf(stdout, "\n%s\n", "------------------------------------------------");
    fread(&todo, sizeof(schedule), 1, f);
    while (!feof(f)) {
        fprintf(stdout, "%6d%18s\n",                                
            ++i, todo.title);
        fread(&todo, sizeof(schedule), 1, f);
    }
    fprintf(stdout, "%s\n\n", "-------------------------------------------------");
    fprintf(stdout, "%s\n\n", "Number: ");

    scanf("%d", &i);
    getchar();

    rewind(f);
    offset = (long) sizeof(schedule);
    fseek(f, (i - 1)*offset, SEEK_CUR);

    fread(&todo, sizeof(schedule), 1, f);
    printf("Edit: %s\n", todo.title);
    fprintf(stdout, "%6d%18s%8s%10s%8d\n",                              
        todo.number, todo.title, todo.where, todo.details, todo.importance);

    scanf("%s", todo.title);

    fwrite(&todo, (long)sizeof(todo.title), 1, f);

}

It's part of editing data codes. This is what I expected.

If a user put a number(i in the code), the program will find the location (in binary file). Then, the user put todo.title by (scanf("%s", todo.title);) and the program will edit it by using fwrite(&todo, (long)sizeof(todo.title), 1, f);

I got a warning like

Expression: ("Flush between consecutive read and write.", !stream.has_any_of(_IOREAD))

I think there's problems with buffer, but I can't fix this.

Hunter
  • 19
  • 7
  • 1
    What is `todo.title`? How do you open the file? Please try to show us a [mcve]. And if the "edit" of it makes it a different length then the write could write past the end of the old text in the file. Modifying variable-length texts in a file can't be by a simple read and rewrite. – Some programmer dude Dec 18 '19 at 15:47
  • As for the warning, please read about the [`fflush`](https://en.cppreference.com/w/c/io/fflush) function. – Some programmer dude Dec 18 '19 at 15:47
  • 1
    By the way, the code as you show it have another problem: After you have read the `todo` structure from the file, the file-pointer will be placed *after* that structure, so you will write the string in the wrong place. You need to reseek and rewrite the full structure. – Some programmer dude Dec 18 '19 at 15:49
  • 2
    Note that [`while (!feof(file))` is always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). You should also inspect the value returned by `fread()` to make sure you got what you expected. – Jonathan Leffler Dec 18 '19 at 16:00

1 Answers1

2

If you have a file open for update (read and write) then the C11 standard requires:

§7.21.5.3 The fopen function

¶7 When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations.

The quote comes from the C11 specification, but the wording is essentially unchanged in all versions of the standard.

Note that you must do a seek operation, even if it is just fseek(f, 0, SEEK_CUR), between a read and a write operation, and between a write and a read operation.

Your code has an fread() followed by an fwrite() with no intervening fseek(). That's probably an oversight since you change the record and overwrite the next record in the file with the updated information. You probably need an fseek(f, -(long)sizeof(schedule), SEEK_CUR) or thereabouts to move back and overwrite the record just read and changed.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278