Struct in C++ – incorrect reading from file
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.
Related videos on Youtube
northbridge
Updated on December 02, 2022Comments
-
northbridge 6 months
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:
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 almost 6 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 almost 6 yearsIt'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 almost 6 yearsYour 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 increate
- you only use the first element of it. -
n. m. almost 6 yearsYou 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 almost 6 yearsthank 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 almost 6 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 almost 6 years@YuliyaChakhovich if your teacher use some funtion C++, so you can use some other features from C++ ;), I add function for readFromFile().
-
northbridge almost 6 yearsthanks, this fix works for new line moving, though starting from the second loop name of the student is getting lost somewhere :(
-
northbridge almost 6 yearsalso would appreciate if you have time to give a piece of advice on how this code could be improved and done differently