0

I have used the following code. 's' is a variable of the structure. Can someone show me the currect usage of fseek as this code doesnt replaces but adds the edited portion in the file.

the file name 'g' is of the mode r+

HA

In the output section whenever the roll no matches it shows me 2 lines at a time and doesnt waits for the input.

Do you want to change the name? (y/n) Do you want to change the class? (y/n)

void edit()
{
int x;
char ch,c;
printf("\nEnter roll no. \n");
scanf("%d", &x);
rewind(g);
while(!feof(g))
{
    fscanf(g, "%d %s %d %s %s", &s.roll, s.name, &s.standard, s.sub, s.address);
    if(s.roll==x)
    {
        printf("\nDo you want to change the name? (y/n)\n");
        scanf("%c",&ch);
        if(ch=='y')
        {
            printf("\nEnter new name\n");
            scanf("%s", s.name);
        }
        printf("\nDo you want to change the class? (y/n)\n");
        scanf("%c",&ch);
        if(ch=='y')
        {
            printf("\nEnter new class\n");
            scanf("%d",&s.standard);
        }
        printf("\nDo you want to change the subject? (y/n)\n");
        scanf("%c", &ch);
        if(ch=='y')
        {
            printf("\nEnter new subject\n");
            scanf("%s", s.sub);
        }
        printf("\nDo you want to change the address? (y/n)\n");
        scanf("%c", &ch);
        if(ch=='y')
        {
            printf("\nEnter new address\n");
            scanf("%s", s.address);
        }
        fseek(g,sizeof(struct student) ,SEEK_SET);
        fprintf(g,"%d %s %d %s %s",s.roll, s.name, s.standard, s.sub, s.address);
    }
}
fclose(g);

}

  • 1
    Where do you open the file? Why are you rewinding the file if you seek in it to an absolute position anyway? What does the structure look like? What does the file look like (if it's a text file)? – Some programmer dude Dec 10 '15 at 05:25
  • 1
    You need to read [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). I *assume* you actually meant to use `while (!feof(g))` instead of `while (feof(g))` (notice the lack of logical not operator `!` in your code)? – Some programmer dude Dec 10 '15 at 05:26
  • 1
    Also, if the file is a text file with variable-length texts separated by a newline (where's the newline?) then you can't seek to a specific position in the file as each records position will be depending on the previous data. – Some programmer dude Dec 10 '15 at 05:28
  • i opened the file in main function and then called this function. i read that article you mentioned. Can you suggest alternative use according to my program. this is how the structure looks like: – Pranava Sureka Dec 10 '15 at 05:30
  • @joachimstruct student { char name[30]; int standard; char sub[20]; char address[100]; int roll; } s; – Pranava Sureka Dec 10 '15 at 05:30
  • @joachim yes its a text file. So what do you suggest? I am new at programming – Pranava Sureka Dec 10 '15 at 05:32
  • Using this `sizeof(struct student)` in the `fseek` is unlikely to be what you want. You are writing strings to the file which is not the same as the binary form of the struct. For example, `s.roll` may be an `int` type of 4 bytes. But when converted to a string it may be more than 4 bytes (for any integer value with more than 4 digits) or less than 4 bytes (for integers with 3 digits or less). – kaylum Dec 10 '15 at 05:32
  • So what should i do @kaylum – Pranava Sureka Dec 10 '15 at 05:37

1 Answers1

1

As I see it you have two choices: One is to open the file in binary mode and read/write the structures as-is. The other is to keep using text-files with variable-length records. The solution depends very much on how you continue after this selection. I'll provide sample code for both.


First the binary solution where you read and write the whole structures.

For this you can do something like this:

// Open the file for reading and writing, in binary mode
// Initial position is at the beginning of the file
g = fopen("some path to the file", "r+b");

...

// While we can read one structure
while (fread(&s, sizeof(s), 1, g) == 1)
{
    // Your code to update the structure...

    // Seek backwards in the file from the current position
    // So when we write we will overwrite the structure we just read
    fseek(g, -sizeof(s), SEEK_CUR);

    // Write out the structure again, overwriting the previous data
    fwrite(&s, sizeof(s), 1, g);
}

The code to handle variable-length records in a text file is much harder, because then you can't actually replace the contents in the file "in place", you have to write to a temporary file which you rename to the original file when you are done.

// Open the input file in read-only text mode
g = fopen("some path to the file", "r");
t = fopen("some path to the file.tmp", "w");
...

// Buffer where we read each line of the input file into
char line[256];

// Loop while we can read a line
while (fgets(line, sizeof(line), g) != NULL)
{
    sscanf(line, "%d %29[^1234567890] %d %19[^1234567890] %99[^\n]%*c",
           &s.roll, s.name, &s.standard, s.sub, s.address);

    // Your existing code to update the structure...

    // Write to the temporary file
    fprintf(t, "%d %s %d %s %s\n",
            s.roll, s.name, s.standard, s.sub, s.address);
}

// Close the files
fclose(t);
fclose(g);

// Rename the files, overwriting the old original file
// with the temporary file
rename("some path to the file.tmp", "some path to the file");

Both of these solutions have pros and cons. For the first solution the pro is that it's obviously much easier and simpler. The con is that it's not really readable by a text editor, and that you can't simply copy the file to a platform with a different endianness.

The pros of using the text file is that you can read and edit the file in just about any program, like a simple text editor. The con is that it's much harder and needs more code on your side.


When you read input from the user using scanf, you read a single character. When you give that single character input you write the character, and then you press the Enter key, right? Both the character and the Enter key will be put in the input buffer. The scanf call reads the input but leaves the Enter key, so the next time you try to read input scanf will see the newline added by the Enter key.

You solve this problem by adding a single space in the format, like e.g.

scanf(" %c",&ch);
//    ^
//    |
// Note space here

That extra leading space will tell scanf to read and discard any white-space.

It's not needed for the numeric and string formats, they automatically skip leading space, it's only needed for the "%c" and "%[" formats.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621