Thread: Fseek in structures

  1. #16
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    I've now started using pointers, to point to where i want my data to be inserted but as soon as i input int data it just crashes the debugger, if i comment out that part i can do the strings ,but it still won't save my data

    I swear programming with me I don't know why stuff works, and I don't know why it doesn't

    Guess maybe next year I'm going to be able to get C through my thick skull, i'm guessing this year this is a lost cause for me

    I'm going to redo all of this stuff hopefully something will actually be useful for the rest of my group

    Sorry for the rant, I'm sick of spending hours upon hours with this and even with help i'm majorly lost

  2. #17
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Basic semantics seemed to be what was causing my pointers to crash

    I'm using a lot of ftells around my file to make sure it's pointing to where it's supposed to

    I'm using a while together with an fread and an if for when it meets the condition i'm searching for

    I'm using fseek to point to the current location, and then the pointers to "edit" the data

    Only thing is fwrite is still writing at the end of the file instead of overwriting the pointer located in the memory it's currently sitting at

    Summing up the important parts

    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;
        int location;
        struct studentdata change;
        struct studentdata *edit;
            edit = &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", change.phone_number);
                if (feof(p))
                        break;
                }
    
                printf("Please input the student number you want to edit:");
                scanf("%d",&edit_student);
                fseek(p, 0, SEEK_SET);
                system("cls");
    
    
                while(fread(&change,sizeof(struct studentdata),1,p)){
    
                if ( change.student_number == (edit_student) ){
    
                            location = ftell(p);
    
                        setbuf(stdin, NULL);
                            printf("Current student name: %s\n", change.student_name);
                            printf("\New student name: ");
                            scanf("%s", &edit->student_name);
                            printf("Current Student ID: %d\n", change.student_id);
                            printf("\tNew Student ID: ");
                            scanf("%d", &edit->student_id);
                            printf(" Current Address: %s\n", change.student_address);
                            printf("\tAddress / CP: ");
                            scanf("%s", &edit->student_address);
                            printf("Current Phone Number: %d\n", change.phone_number);
                            printf("\tPhone Number: ");
                            scanf("%d", &edit->phone_number);
    
                                location = ftell(p);
    
                            fwrite(&edit,sizeof(struct studentdata),1,p);
                            fclose(p);
                            break;
                }
                    if (feof(p))
                        break;
                }
        }
    Am I going in the right direction?

    Or am I using the wrong logic?

    Thanks

  3. #18
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    You don't need all those feof() calls if you're using the results of other calls properly.

    main returns an int.

    Keep on top of the indentation. Be wary of mixing spaces and tabs in your IDE (which may deal with it), vs posting the same code online (which will make a mess of it).

    Try this.
    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;
    };
    
    int main()  //!! yes, really!
    {
      FILE *p;
      //struct studentdata insert;
      int edit_student;
      //int location;
      struct studentdata change;
      // struct studentdata *edit;
      // edit = &change;
    
      p = fopen("students.txt", "r+");
      while (fread(&change, sizeof(struct studentdata), 1, p) == 1) {
        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", change.phone_number);
        //if (feof(p))
        //  break;
      }
    
      printf("Please input the student number you want to edit:");
      scanf("%d", &edit_student);
      fseek(p, 0, SEEK_SET);
      system("cls");
    
      while (fread(&change, sizeof(struct studentdata), 1, p) == 1) {
        if (change.student_number == (edit_student)) {
          //location = ftell(p);
          //setbuf(stdin, NULL);
          printf("Current student name: %s\n", change.student_name);
          printf("\nNew student name: ");
          scanf("%s", change.student_name);    // you don't need & on char arrays
          printf("Current Student ID: %d\n", change.student_id);
          printf("\tNew Student ID: ");
          scanf("%d", &change.student_id);
          printf(" Current Address: %s\n", change.student_address);
          printf("\tAddress / CP: ");
          scanf("%s", change.student_address);
          printf("Current Phone Number: %d\n", change.phone_number);
          printf("\tPhone Number: ");
          scanf("%d", &change.phone_number);
    
          // try an fseek here
          // location = ftell(p);
          // go back one record
          fseek(p, -(long)(sizeof(struct studentdata)), SEEK_CUR);
    
          fwrite(&change, sizeof(struct studentdata), 1, p);
          fclose(p);
          break;
        }
        //if (feof(p))
        //  break;
      }
    }
    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. #19
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    I tried the code you suggested on a file with 4 users on which i had selected the 3rd, and although it did replace the data, the fread no longer reads the 4th user (on the file i can see the data on the 3rd has changed and the 4th is there)

    The while with the fread runs 3 times and then jumps out

  5. #20
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > The while with the fread runs 3 times and then jumps out

    Of course it does.
    Code:
          fwrite(&change, sizeof(struct studentdata), 1, p);
          fclose(p);
          break;
    If you want it to carry on searching through the file, then you need to do this.
    Code:
          fwrite(&change, sizeof(struct studentdata), 1, p);
          // you must do this between a fwrite and an fread
          fflush(p);
    > p = fopen("students.txt", "r+");
    I hope you're on a Linux/Unix/Posix system.

    Calling something a .txt file when it doesn't contain purely text is going to lead to surprises for some people at some point.
    Better to call it a .dat file as a generic "it contains non-printable binary data".
    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.

  6. #21
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Quote Originally Posted by Salem View Post
    > The while with the fread runs 3 times and then jumps out

    Of course it does.
    Code:
          fwrite(&change, sizeof(struct studentdata), 1, p);
          fclose(p);
          break;
    If you want it to carry on searching through the file, then you need to do this.
    Code:
          fwrite(&change, sizeof(struct studentdata), 1, p);
          // you must do this between a fwrite and an fread
          fflush(p);
    > p = fopen("students.txt", "r+");
    I hope you're on a Linux/Unix/Posix system.

    Calling something a .txt file when it doesn't contain purely text is going to lead to surprises for some people at some point.
    Better to call it a .dat file as a generic "it contains non-printable binary data".
    Apparently, when I changed the file type to binary, that situation changed, and the data is now read successfully

    Now, I'm going around trying to see how to replace the scanf's and printf's to get rid of the single word problem when reading the inputs

    I'm using fgets for the strings, and scanf's for the int data when reading the user input

    And then writing to the screen with fputs and printf's, but I still need to remember how to get around the buffer overflow that's happening after i use the first fputs (it doesn't print and the results of the printf's are all messed up)

    Is my thinking going anywhere?

  7. #22
    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 using fgets for the strings, and scanf's for the int data when reading the user input
    Yeah, that's going to bite you.

    They don't play nicely with one another.

    It's better to fgets() into a temporary buffer, then use sscanf / strcpy / whatever to take that buffer, validate it in some way and then assign good data to your actual data variables.

    > And then writing to the screen with fputs and printf's, but I still need to remember how to get around the buffer overflow that's happening
    > after i use the first fputs (it doesn't print and the results of the printf's are all messed up)
    You'd have to post your latest code for detailed comments.
    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.

  8. #23
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    Right now the code i'm running is something like this:

    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;
        int location;
        struct studentdata change;
        struct studentdata *edit;
            edit = &change;
    
        p = fopen("students.txt","a");
    
        printf("Insert student\n\n ");
            printf("Student Number: ");
            scanf("%d", &insert.student_number);
            printf("Student Name: ");
    
            setbuf(stdin, NULL);
            fgets(insert.student_name,40,stdin);
    
            //scanf("%s", &insert.student_name);
            printf("Student ID: ");
            scanf("%d", &insert.student_id);
            printf("Address: ");
    
            setbuf(stdin, NULL);
            fgets(insert.student_address,60,stdin);
    
            //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","rb+");
    
                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 Name: \n");
                    fputs(change.student_name,stdout);
                    setbuf(stdin, NULL);
    
                printf("Student ID: %d\n", change.student_id);
                //printf("Address: %s\n", change.student_address);
                printf("Address: \n");
                    fputs(change.student_address,stdout);
                    setbuf(stdin, NULL);
                printf("Phone Number: %d\n", change.phone_number);
                if (feof(p))
                        break;
                }
    
                getch();
    
                printf("Please input the student number you want to edit:");
                scanf("%d",&edit_student);
                fseek(p, 0, SEEK_SET);
                system("cls");
    
    
    
    
                while(fread(&change,sizeof(struct studentdata),1,p)){
    
                if ( change.student_number == (edit_student) ){
    
                            location = ftell(p);
    
                        setbuf(stdin, NULL);
                            printf("Current student name: \n");
                                fputs(change.student_name,stdout);
                                setbuf(stdin, NULL);
    
                            printf("\New student name: ");
                                setbuf(stdin, NULL);
                                fgets(insert.student_name,40,stdin);
    
                            printf("Current Student ID: %d\n", change.student_id);
                            printf("\tNew Student ID: ");
                            scanf("%d", &edit->student_id);
    
                            printf(" Current Address: \n");
                                fputs(change.student_address,stdout);
                                setbuf(stdin, NULL);
    
                            printf("\tAddress / CP: ");
                                fputs(change.student_address,stdout);
                                setbuf(stdin, NULL);
    
                            printf("Current Phone Number: %d\n", change.phone_number);
                            printf("\tPhone Number: ");
                            scanf("%d", &edit->phone_number);
    
                                location = ftell(p);
    
                            fwrite(edit,sizeof(struct studentdata),1,p);
                            fclose(p);
                            break;
                }
                    if (feof(p))
                        break;
                }
        }
    On my first attempt i've input this data:

    Student Number: 1232
    Student Name: Jack Miles
    Student ID: 13546
    Address: Bayside View
    Phone Number: 3216496

    On my second attempt inserting data this is the data I've input:

    Student Number: 3216
    Student Name: Alex Carlson
    Student ID: 87985
    Address: 6th Street
    Phone Number: 132468

    On reading this is what i get:
    Fseek in structures-cprogramming-1-png

    I had a feeling it was suspicious this was starting to finally go well

  9. #24
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    You don't need setbuf for this exercise. Forget you learned about it. You also can't use it the way you are using it:

    Quote Originally Posted by https://en.cppreference.com/w/c/io/setbuf
    This function may only be used after stream has been associated with an open file, but before any other operation (other than a failed call to setbuf/setvbuf).
    Also, main returns int, not void (Salem already pointed that out).

  10. #25
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > fwrite(edit,sizeof(struct studentdata),1,p);
    Did you get a warning with that line?

    A few more thoughts for you to ponder.
    When your main (or any other function) is well past 100 lines long, it's time to start factoring out some code.

    Example.
    Code:
    #include <stdio.h>
    #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;
    };
    
    // print each field to stdout
    void printStudent(const struct studentdata *s) {
        printf("Student Number: %d\n",s->student_number);
        printf("Student Name  : %s\n",s->student_name);
        printf("Student ID    : %d\n",s->student_id);
        printf("Address       : %s\n",s->student_address);
        printf("Phone Number  : %d\n",s->phone_number);
    }
    
    void prompt(const char *p) {
        printf("%s",p);
        fflush(stdout);
    }
    
    // input each field from stdin
    int inputStudent(struct studentdata *s) {
        char buff[100];
        prompt("Student Number: ");
        fgets(buff,sizeof(buff),stdin);
        sscanf(buff,"%d",&s->student_number);
        prompt("Student Name  : ");
        fgets(buff,sizeof(buff),stdin);
        sscanf(buff,"%[^\n]",s->student_name);
        prompt("Student ID    : ");
        fgets(buff,sizeof(buff),stdin);
        sscanf(buff,"%d",&s->student_id);
        prompt("Address       : ");
        fgets(buff,sizeof(buff),stdin);
        sscanf(buff,"%[^\n]",s->student_address);
        prompt("Phone Number  : ");
        fgets(buff,sizeof(buff),stdin);
        sscanf(buff,"%d",&s->phone_number);
    }
    
    int main(){
        const char *filename = "students.dat";
        FILE *p;
        struct studentdata data;
    
        // Create initial file
        p = fopen(filename,"w+b");
    
        printf("Enter 3 student details\n");
        for ( int i = 0 ; i < 3 ; i++ ) {
            inputStudent(&data);
            fwrite(&data, sizeof(struct studentdata), 1, p);
        }
        fclose(p);
    
        // print file contents
        p = fopen(filename,"rb+");
        while ( fread(&data,sizeof(struct studentdata),1,p) == 1 ) {
            printStudent(&data);
        }
    
        int edit_student;
        printf("Please input the student number you want to edit:");
        char buff[100];
        fgets(buff,sizeof(buff),stdin);
        sscanf(buff,"%d",&edit_student);
        fseek(p, 0, SEEK_SET);
    
        while ( fread(&data,sizeof(struct studentdata),1,p) == 1 ) {
            if ( data.student_number == (edit_student) ) {
                inputStudent(&data);
                fseek(p, -((long)sizeof(struct studentdata)), SEEK_CUR);
                fwrite(&data,sizeof(struct studentdata),1,p);
                fflush(p);
            }
        }
        fclose(p);
    }
    
    
    $ ./a.out 
    Enter 3 student details
    Student Number: 1
    Student Name  : Fred Flintstone
    Student ID    : 22
    Address       : 1 Bedrock
    Phone Number  : 5551234
    Student Number: 2
    Student Name  : Wilma Flintstone
    Student ID    : 33
    Address       : 1 Bedrock
    Phone Number  : 5551234
    Student Number: 3
    Student Name  : Barney Rubble
    Student ID    : 44
    Address       : 2 Bedrock
    Phone Number  : 5554321
    Student Number: 1
    Student Name  : Fred Flintstone
    Student ID    : 22
    Address       : 1 Bedrock
    Phone Number  : 5551234
    Student Number: 2
    Student Name  : Wilma Flintstone
    Student ID    : 33
    Address       : 1 Bedrock
    Phone Number  : 5551234
    Student Number: 3
    Student Name  : Barney Rubble
    Student ID    : 44
    Address       : 2 Bedrock
    Phone Number  : 5554321
    Please input the student number you want to edit:2
    Student Number: 2
    Student Name  : Betty Rubble
    Student ID    : 77
    Address       : 2 Bedrock
    Phone Number  : 5554321
    $ hd students.dat 
    00000000  01 00 00 00 46 72 65 64  20 46 6c 69 6e 74 73 74  |....Fred Flintst|
    00000010  6f 6e 65 00 00 00 00 00  00 00 00 00 00 00 00 00  |one.............|
    00000020  00 00 00 00 00 00 00 00  00 00 00 00 16 00 00 00  |................|
    00000030  31 20 42 65 64 72 6f 63  6b 00 00 00 00 00 00 00  |1 Bedrock.......|
    00000040  00 00 00 00 00 00 00 00  e8 6f 2f f3 fe 7f 00 00  |.........o/.....|
    00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000060  00 00 00 00 00 00 00 00  00 00 00 00 82 b4 54 00  |..............T.|
    00000070  02 00 00 00 42 65 74 74  79 20 52 75 62 62 6c 65  |....Betty Rubble|
    00000080  00 6f 6e 65 00 00 00 00  00 00 00 00 00 00 00 00  |.one............|
    00000090  00 00 00 00 00 00 00 00  00 00 00 00 4d 00 00 00  |............M...|
    000000a0  32 20 42 65 64 72 6f 63  6b 00 00 00 00 00 00 00  |2 Bedrock.......|
    000000b0  00 00 00 00 00 00 00 00  e8 6f 2f f3 fe 7f 00 00  |.........o/.....|
    000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    000000d0  00 00 00 00 00 00 00 00  00 00 00 00 91 c0 54 00  |..............T.|
    000000e0  03 00 00 00 42 61 72 6e  65 79 20 52 75 62 62 6c  |....Barney Rubbl|
    000000f0  65 00 6e 65 00 00 00 00  00 00 00 00 00 00 00 00  |e.ne............|
    00000100  00 00 00 00 00 00 00 00  00 00 00 00 2c 00 00 00  |............,...|
    00000110  32 20 42 65 64 72 6f 63  6b 00 00 00 00 00 00 00  |2 Bedrock.......|
    00000120  00 00 00 00 00 00 00 00  e8 6f 2f f3 fe 7f 00 00  |.........o/.....|
    00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000140  00 00 00 00 00 00 00 00  00 00 00 00 91 c0 54 00  |..............T.|
    00000150
    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. #26
    Registered User
    Join Date
    Dec 2022
    Posts
    14
    So, really stupid question, considering I believe we have completely and absolutely messed up

    The only way to sort the structures we have been using in the program above is if we load them into an array (using fread or something) and then run a bubble sort or a qsort, or something right?

    Because we need to sort some of the structs based on a certain criteria, and those are the only options I've been finding on the internet.

    So far the only way it seems we're accessing the structs data is if we fread them sequentially and then print the ones that meet a certain criteria.

  12. #27
    Registered User
    Join Date
    Mar 2022
    Posts
    7
    It looks like you already have a bunch of answers (which I want to read - I didn't know reading data directly into structs like that was even possible) but I thought it might be worth sharing what I usually do: use regular string-reading functions (fgetc, fgets, fread etc.) and then fill out my struct with the results of that. At work I've been doing a lot with TSV (tab-separated values) and strtok, cuz unlike CSV you're a lot less likekly for users to enter your delimiter char (\t vs a comma, lol). I guess the bottom line is, there's always another way. I'm wrestling with a different problem (totally unrelated) and kinda having to consider chaning my approach in a similar way (lol). That's what I love about C - despite its many quirks, you can do just about anything with it.

  13. #28
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > The only way to sort the structures we have been using in the program above is if we load them into an array (using fread or something) and then run a bubble sort or a qsort, or something right?
    The simple answer is yes.

    Apart from the bit about using bubble sort. You'd always use qsort.

    But Merge sort - Wikipedia can be implemented as a file to file sort if your file doesn't fit in memory.
    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.

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