Struct in C++ – incorrect reading from file

78

std::fgets retains the newline following the string input (assuming the buffer space was adequate to reach it). As a result, your test members and name member contain their respective strings with those newlines on their tails.

That explains your output precisely. The most immediate fix is to simply remove the newline in those strings if present, and the most opportune time to do that is after reading them. The syntax is similar to this:

char *p = strrchr(str, '\n');
if (p)
    *p = 0;

This will find the newline (which must be the last character read if space allowed) and overwrite it with a terminating nulchar.

The second problem, losing name, is because the trim code you have at the top of the loop (while (getchar() != '\n');) shouldn't be inside the loop. That is there to trim the newline after your menu selection. It belongs there (after the menu selection read); not in this loop.

All of that said, there are plenty of things worth doing differently in this code, which has many assumptions on the success of IO operations, and leaks memory like a sieve leaks rain. Embracing the standard C++ library and utilizing its many features will help with most of those, and I encourage you to do so.

Regardless, the above should fix your issue about odd output.

Share:
78

Related videos on Youtube

northbridge
Author by

northbridge

Updated on December 02, 2022

Comments

  • northbridge
    northbridge over 1 year

    My task is to create a program that does some stuff with the structures. My structure is about student's record (exam grades).

    The function in the first case in my switch creates the structure and writes it into the file. The second – reads it from the file. here's my code:

    #include <stdio.h>
    #include <stdlib.h>
    
    
    struct session {
        char name[50];
        int group;
        int exam1;
        int exam2;
        int exam3;
        int exam4;
        char test1[50];
        char test2[50];
    
    };
    
    void create(int);
    void show(int);
    
    
    
    int main() {
    
        int i, n;
    
        int loop = 2, num;
    
        while(loop > 1) {
    
            printf("\nChoose menu item(1-4):");
            scanf("%d", &num);
    
            switch (num) {
                case 1:
                    printf("The number of students:\n");
                    scanf("%d", &n);
    
                    create(n);
                    break;
                case 2:
    
                    show(n);
                    break;
                case 3:
                    break;
                case 4:
                    break;
                default:
                    loop = 0;
                    break;
            }
        };
    
        return 0;
    }
    
    void create(int n) {
    
        FILE *fp;
        session *year2017 = new session[n];
    
        fp = fopen("lab8.txt", "w");
    
        if(fp == NULL) {
            printf("File can't be opened\n");exit(1);
        }
            for (int i = 0; i < n; i++) {
    
                printf("Student #%d\n", i + 1);
                printf("Student's family name: ");
                while (getchar() != '\n');
    
                fgets(year2017 -> name, 50, stdin);
                printf("Group number: ");
                scanf("%d", &year2017->group);
                printf("1st exam grade: ");
                scanf("%d", &year2017->exam1);
                printf("2d exam grade: ");
                scanf("%d", &year2017->exam2);
                printf("3d exam grade: ");
                scanf("%d", &year2017->exam3);
                printf("4th exam grade: ");
                scanf("%d", &year2017->exam4);
                printf("First test (passed or not): ");
    
                while (getchar() != '\n');
    
                fgets(year2017 -> test1, 50, stdin);
                printf("Second test (passed or not): ");
                fgets(year2017 -> test2, 50, stdin);
                fwrite(year2017, sizeof(session), 1, fp);
    
    
            }
    
         fclose(fp);
    
    }
    
    void show(int n){
    
        FILE *fp;
        session *year2017 = new session[n];
    
        fp = fopen("lab8.txt", "r");
    
        while(fread(year2017,sizeof(session), 1, fp) != NULL) {
            printf("%s %d %d %d %d %d %s %s", year2017->name, year2017 -> 
    group, year2017 -> exam1, year2017 -> exam2, year2017 -> exam3, 
    year2017 -> exam4, year2017 -> test1, year2017 -> test2);
        }
    
     fclose(fp);
    
     }
    

    when I compile the code the input is the following:

    http://take.ms/yoo5U

    so it eats't the name of the student in the second loop and also moves to the new line the grades and the second test.

    I use Clion and Mac OS.

    • northbridge
      northbridge almost 7 years
      @21koizyd guys here commented that it is not C and asked to rename it to C++ (as I use some structures that came with C++)
    • Lightness Races in Orbit
      Lightness Races in Orbit almost 7 years
      It's C++, but written in a C style using C library features. If you're writing C++ you should commit fully and switch to C++ idiom.
    • K. Kirsz
      K. Kirsz almost 7 years
      Your link doesn't work. Also you should delete the sessions you allocate with new. Right now your program leaks memory. There is also no need to allocate the array of sessions in create - you only use the first element of it.
    • n. m.
      n. m. almost 7 years
      You need to decide which language you are using first. No one can decide for you. If you want to use C, you need to remove C++ constructs because C doesn't support them. If you want C++, you want to get rid of C idioms because better alternatives exist in C++.
  • northbridge
    northbridge almost 7 years
    thank you, but C++ syntax is mostly unknown to me (as during the classes we study C), but our teacher uses some structures from C++ (or correctly, it cpp file in a C style), that's why I would like to fix the construction I use
  • WhozCraig
    WhozCraig almost 7 years
    @YuliyaChakhovich Your teacher isn't doing you any favors. For decades vendors pimped the idea of "moving to C++ from C at your own pace", and all it resulted in was a bunch of terrible C++ engineers that continually ran to their C homeroom. The C++ language and it's standard library are things you should embrace hook, line and sinker.
  • 21koizyd
    21koizyd almost 7 years
    @YuliyaChakhovich if your teacher use some funtion C++, so you can use some other features from C++ ;), I add function for readFromFile().
  • northbridge
    northbridge almost 7 years
    thanks, this fix works for new line moving, though starting from the second loop name of the student is getting lost somewhere :(
  • northbridge
    northbridge almost 7 years
    also would appreciate if you have time to give a piece of advice on how this code could be improved and done differently