Thread: Fseek in structures

  1. #1
    Registered User
    Join Date
    Dec 2022
    Posts
    14

    Fseek in structures

    Hi everyone,

    I'm currently doing a group assignment on C, and i'm kind of stuck in my part of the work.

    So, one of my colleagues is receiving user input, and then saving it in a file, and my part consists of asking the user for input on which part of the data he wants to edit, edit it, and save into a file again.

    But i'm stuck on the part of searching the file for the part I need to edit.

    I'm using fread to read the file content into the screen (struct with 3 ints and 2 char arrays).
    Code:
    struct studentdata{
            int student_number;        
            char student name[40];  
            int student_id;                   
            char student_address[60];           
            int phone_number;                          
        };
    The objective is to keep the student_number, but change the other parts, but for the life of me, I can't understand how to get fseek to where i want it to be.
    Code:
    printf("Please input the student number you want to edit:");
                scanf("%d",&edit_student);
    But when i use fseek, Which in my ingenuity should change the pointer location, it doesn't seem to do anything.
    Code:
    fseek(p,(edit_student)*sizeof(struct studentdata),SEEK_SET);
    
    or for example:
    
    fseek(p,sizeof(struct studentdata)*(edit_student-1),SEEK_SET);
    Or a few other attempts i've tried, but have already removed from the file.

    And then try to edit the data, it still edits the last data it printed in the screen (the one that's still in the buffer).

    Am i using the right logic at least?

    Sorry, It's my second time having C classes, and just like 12 years ago, i still can't get the hang of it

    Thanks for the help

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Please show the file contents you are trying to "seek" through.

    Did your colleague use binary methods to write the file (like fwrite())?

    Trying to seek in a text file is very problematic. Text files are usually not suitable for "random searching".

    I'd start by reading the file provided by you colleague one record at time, storing the record in an array in memory. Then once you have read the entire file step through the array to find the desired record. Edit the record, then re-write the file with the modified data. Trying to "replace" content in the middle of a file will usually not work properly ( even you you use the proper file open mode).

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Both are correct, depending on whether edit_student starts at 0 or 1 (think arrays).

    The other things to remember are
    1. Open the file in binary mode.

    2. The read-modify-write operation on the file goes as
    Code:
    fseek(fp, (edit_student)*sizeof(struct studentdata),SEEK_SET);  // assuming 0-based
    fread(&buff, sizeof(buff), 1, fp);
    
    // do stuff with buff
    
    fseek(fp, (edit_student)*sizeof(struct studentdata),SEEK_SET);  // assuming 0-based
    fwrite(&buff, sizeof(buff), 1, fp);
    fflush(fp);  // needed between fwrite and another fread.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Quote Originally Posted by jimblumberg View Post
    Please show the file contents you are trying to "seek" through.

    Did your colleague use binary methods to write the file (like fwrite())?

    Trying to seek in a text file is very problematic. Text files are usually not suitable for "random searching".

    I'd start by reading the file provided by you colleague one record at time, storing the record in an array in memory. Then once you have read the entire file step through the array to find the desired record. Edit the record, then re-write the file with the modified data. Trying to "replace" content in the middle of a file will usually not work properly ( even you you use the proper file open mode).
    Here's a version i've simplified for my testing:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    struct studentdata{
            int student_number;
            char student_name[40];
            int student_id;
            char student_address[60];
            int phone_number;
    };
    
    void main(){
        FILE *p;
        struct studentdata insert;
        int edit_student;
        struct studentdata change;
    
        p = fopen("students.txt","a");
    
        printf("Insert student\n\n ");
            printf("Student Number: ");
            scanf("%d", &insert.student_number);
            printf("Student Name: ");
            scanf("%s", &insert.student_name);
            printf("Student ID: ");
            scanf("%d", &insert.student_id);
            printf("Address: ");
            scanf("%s", &insert.student_address);
            printf("Phone Number: ");
            scanf("%d", &insert.phone_number);
            printf("\tData saved sucessfully.\n");
    
                fwrite(&insert, sizeof(struct studentdata), 1, p);
        fclose(p);
    
    
                p = fopen("students.txt","r+");
    
                while(fread(&change,sizeof(struct studentdata),1,p)){
                printf("Student Number: %d\n", change.student_number);
                printf("Student Name: %s\n", change.student_name);
                printf("Student ID: %d\n", change.student_id);
                printf("Address: %s\n", change.student_address);
                printf("Phone Number: %d\n\n\n", change.phone_number);
                }
    
                printf("Please input the student number you want to edit:");
                scanf("%d",&edit_student);
    
                void rewind(p);
                fseek(p,sizeof(struct fornecedor)*(id_fornecedor-1),SEEK_SET);
    
    scanf("%s", &edit.student_name);
            printf("Student ID: ");
            scanf("%d", &edit.student_id);
            printf("Address: ");
            scanf("%s", &edit.student_address);
            printf("Phone Number: ");
            scanf("%d", &edit.phone_number);
    
    
    
    }
    I know it still needs a lot of tweaking, but if i'm not even getting the "simple" part working, the other part is the next step
    Last edited by M3ss3r92; 12-03-2022 at 10:02 AM.

  5. #5
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Quote Originally Posted by Salem View Post
    Both are correct, depending on whether edit_student starts at 0 or 1 (think arrays).

    The other things to remember are
    1. Open the file in binary mode.

    2. The read-modify-write operation on the file goes as
    Code:
    fseek(fp, (edit_student)*sizeof(struct studentdata),SEEK_SET);  // assuming 0-based
    fread(&buff, sizeof(buff), 1, fp);
    
    // do stuff with buff
    
    fseek(fp, (edit_student)*sizeof(struct studentdata),SEEK_SET);  // assuming 0-based
    fwrite(&buff, sizeof(buff), 1, fp);
    fflush(fp);  // needed between fwrite and another fread.
    I'm not understanding what you mean by your first sentence, as &edit_student is supposed to be the input from the user to select the structure to edit

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    >I'm not understanding what you mean by your first sentence, as &edit_student is supposed to be the input from the user to select the structure to edit
    If you want to edit the first record, do you type in 0 or 1?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    I'm trying to use edit_student to point to the structure containing that student number

    So if I have the data of 7 students

    Student Number 1984
    Student Number 9571
    Student Number 142
    Student Number 95
    Student Number 264
    Student Number 11
    Student Number 195


    If i input 95 i'm trying to get fseek to point to the structure containing that student number, instead of the struct that's the 1st, 2nd, 3rd, etc

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > If i input 95 i'm trying to get fseek to point to the structure containing that student number, instead of the struct that's the 1st, 2nd, 3rd, etc
    Then you have to read each record in turn, and then decide whether it's the one you're looking for.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    So, instead of finding it directly, i need to jump to the start of the file, and then do a loop, and compare if the struct i'm pointing at at that time meets the condition i'm looking for?

    Sorry, if i'm sounding a bit dumb, it's just that with my lack of knowledge and the time i've been going around this in the last few days and not going anywhere even though it seems ultra simple, it's kind of taking its toll

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Forget it's a file, what would you do if you had
    Code:
    struct studentdata students[7] = {
    };
    initialised with the 7 student numbers you showed us.

    You'd probably end up with
    Code:
    for ( i = 0 ; i < 7 ; i++ ) {
      if ( students[i].student_number == 95 ) {
        // do something
      }
    }
    With all the records in a file, and only a sense of "the current record", it becomes:
    Code:
    for ( i = 0 ; i < 7 ; i++ ) {
      struct studentdata current;
      fread(&current, sizeof(current), 1, fp);
      if ( current.student_number == 95 ) {
        // do something
      }
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    For some reason I can't the IF to actually do what it's supposed to

    It just runs the FOR until the specified number of times, and then jumps out

    I'll see what's wrong with it tomorrow

    Hopefully a good night's sleep will help

    Thanks for all the help so far

  12. #12
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    I tried compiling the longer example that was provided, and got numerous errors:

    Code:
    gcc -o a a.c -Wall -pedantic -O3
    a.c:14:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
       14 | void main(){
          |      ^~~~
    a.c: In function ‘main’:
    a.c:26:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[40]’ [-Wformat=]
       26 |         scanf("%s", &insert.student_name);
          |                ~^   ~~~~~~~~~~~~~~~~~~~~
          |                 |   |
          |                 |   char (*)[40]
          |                 char *
    a.c:30:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[60]’ [-Wformat=]
       30 |         scanf("%s", &insert.student_address);
          |                ~^   ~~~~~~~~~~~~~~~~~~~~~~~
          |                 |   |
          |                 |   char (*)[60]
          |                 char *
    a.c:52:13: warning: parameter names (without types) in function declaration
       52 |             void rewind(p);
          |             ^~~~
    a.c:53:28: error: invalid application of ‘sizeof’ to incomplete type ‘struct fornecedor’
       53 |             fseek(p,sizeof(struct fornecedor)*(id_fornecedor-1),SEEK_SET);
          |                            ^~~~~~
    a.c:53:48: error: ‘id_fornecedor’ undeclared (first use in this function); did you mean ‘fornecedor’?
       53 |             fseek(p,sizeof(struct fornecedor)*(id_fornecedor-1),SEEK_SET);
          |                                                ^~~~~~~~~~~~~
          |                                                fornecedor
    a.c:53:48: note: each undeclared identifier is reported only once for each function it appears in
    a.c:55:14: error: ‘edit’ undeclared (first use in this function); did you mean ‘exit’?
       55 | scanf("%s", &edit.student_name);
          |              ^~~~
    If this is your code, you are most likely running an old compiled version.

  13. #13
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    I'm sure that the OP aware that the way that fseek() is used will move the file pointer to the 'n'th structure in the the file:

    Code:
                fseek(p,sizeof(struct fornecedor)*id_fornecedor,SEEK_SET);
    However it will not position you at the structure for student with the id of 'id_fornecedo', unless student IDs were all written in order of student ids, with no gaps between student ids

  14. #14
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Quote Originally Posted by hamster_nz View Post
    I tried compiling the longer example that was provided, and got numerous errors:

    Code:
    gcc -o a a.c -Wall -pedantic -O3
    a.c:14:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
       14 | void main(){
          |      ^~~~
    a.c: In function ‘main’:
    a.c:26:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[40]’ [-Wformat=]
       26 |         scanf("%s", &insert.student_name);
          |                ~^   ~~~~~~~~~~~~~~~~~~~~
          |                 |   |
          |                 |   char (*)[40]
          |                 char *
    a.c:30:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[60]’ [-Wformat=]
       30 |         scanf("%s", &insert.student_address);
          |                ~^   ~~~~~~~~~~~~~~~~~~~~~~~
          |                 |   |
          |                 |   char (*)[60]
          |                 char *
    a.c:52:13: warning: parameter names (without types) in function declaration
       52 |             void rewind(p);
          |             ^~~~
    a.c:53:28: error: invalid application of ‘sizeof’ to incomplete type ‘struct fornecedor’
       53 |             fseek(p,sizeof(struct fornecedor)*(id_fornecedor-1),SEEK_SET);
          |                            ^~~~~~
    a.c:53:48: error: ‘id_fornecedor’ undeclared (first use in this function); did you mean ‘fornecedor’?
       53 |             fseek(p,sizeof(struct fornecedor)*(id_fornecedor-1),SEEK_SET);
          |                                                ^~~~~~~~~~~~~
          |                                                fornecedor
    a.c:53:48: note: each undeclared identifier is reported only once for each function it appears in
    a.c:55:14: error: ‘edit’ undeclared (first use in this function); did you mean ‘exit’?
       55 | scanf("%s", &edit.student_name);
          |              ^~~~
    If this is your code, you are most likely running an old compiled version.
    I've got so many different versions of files that some actually have stuff from other files i'm trying to follow the logic of

    I'll see if i correct the one I've posted to the correct one

  15. #15
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Quote Originally Posted by hamster_nz View Post
    I'm sure that the OP aware that the way that fseek() is used will move the file pointer to the 'n'th structure in the the file:

    Code:
                fseek(p,sizeof(struct fornecedor)*id_fornecedor,SEEK_SET);
    However it will not position you at the structure for student with the id of 'id_fornecedo', unless student IDs were all written in order of student ids, with no gaps between student ids
    Oh...

    Well, when you barely know the basics and start wanting to use more complicated stuff, this happens

    Guess I'm just going to have to use some of the other options that have been posted around here, thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. New to 'C' using fseek(), please help
    By leopardforest@g in forum C Programming
    Replies: 9
    Last Post: 05-09-2007, 04:53 PM
  2. Reg. fseek
    By pokks in forum C Programming
    Replies: 1
    Last Post: 01-16-2006, 01:28 PM
  3. Help With fseek();
    By Explicit in forum C Programming
    Replies: 3
    Last Post: 05-26-2004, 08:40 PM
  4. fseek
    By Max in forum C Programming
    Replies: 5
    Last Post: 12-15-2003, 03:21 PM
  5. fseek ???
    By davie_scotland in forum C Programming
    Replies: 2
    Last Post: 02-19-2002, 06:13 PM

Tags for this Thread