Reputation: 87
I'm trying to store information of the name of a lesson and the day(s) I have that lesson using structures in C. Storing the name hasn't been an issue. The problem occurs when I try and store multiple days (weekdays as integers, ie. Monday = 1) in an array.
This is what I have:
#include<stdio.h>
#include<string.h>
struct lessons{
char name[20];
int day[3];
};
changelessons(){
int i, k;
struct lessons give[1], receive[1];
FILE *fptr;
fptr = fopen("lessons","wb");
fflush(stdin);
printf("\n\t ~ Change lessons ~");
printf("\n\nWhat's the lesson called?: ");
gets(give[0].name);
printf("\nHow many days do you have it?\n");
scanf("%d", &k);
for(i = 0; i < k; i++); { // Asks the weekday number for each day you have the lesson
printf("What day is lesson %d?: ", i);
scanf("%d", &give[0].day[i]);
}
fwrite(give, sizeof(give), 1, fptr);
fclose(fptr);
fptr = fopen("lessons", "rb");
fread(receive, sizeof(receive), 1, fptr);
printf("\n\t ~ Updated information: ~\n\nLesson name: %s\nDay: %d", receive[0].name, receive[0].day[1]);
for(i = 1; i < k; i++); { // Prints the extra weekdays if there are any
printf(", day: %d", receive[0].day[i]);
}
printf("\n\n");
fclose(fptr);
}
showlessons(){
struct lessons give[1], receive[1];
FILE *fptr;
fptr = fopen("lessons", "rb");
fread(receive, sizeof(receive), 1, fptr);
printf("\t ~ Current information: ~ \n\nLesson name: %s\nDay: %d\n\n", receive[0].name, receive[0].day[0]);
}
int main(){
showlessons();
changelessons();
return 0;
}
Also, in the first for loop it only ever loops once regardless of what k equals.
Thanks in advance for any help!
Upvotes: 1
Views: 49
Reputation: 13580
nicomp pointed out the most obvious error.
But I would also like to point out a few issues I have with your code:
fflush(stdin);
This is wrong, undefined behaviour. fflush
is used to
flusg output streams, stdin
is an input stream. See Using
fflush(stdin)
.
I know that in Windows fflush(stdin)
clears the input buffer, but I strongly
recommend not to use it, because you lose portability when relaying on features
available only in one OS. If you don't care about portability, then use it. If
you use that because scanf
left stuff in the input buffer, use this instead:
int c;
while((c = getchar()) != '\n' && c != EOF);
This is portable.
Never ever use gets
in 2018. gets
is an unsafe, dangerous functions that
has been deprecated in C99 and for good reasons: it doesn't take the size of the
buffer into consideration and if the text entered is longer than the buffer can
store, it will overflow the buffer. This is an accident waiting to happen. So,
never ever use gets
again. Use fgets
instead and if you don't want to have
a newline, you can remove it:
fgets(give[0].name, sizeof give[0].name, stdin);
give[0].name[sizeof(give[0].name) - 1] = 0; // remove possible newline
Why do you declare an array of struct lessons
with dimension 1? What's the
point? You don't need an array for this. You could write it like this:
struct lessons give, receive;
...
printf("\n\nWhat's the lesson called?: ");
fgets(give.name, sizeof give.name, stdin);
give.name[strcspn(give.name, "\n")] = 0;
...
fwrite(&give, sizeof give, 1, fptr);
fclose(fptr);
...
fptr = fopen("lessons", "rb");
fread(&receive, sizeof receive, 1, fptr);
Also don't forget to check the return values of fwrite
and fread
.
Check the return value of fopen
, if it returns NULL
, you cannot use
fread
or fwrite
. Print an error value and return/exit.
stdout
is buffered and when you write to it with printf
, it won't
necessarily print the characters on screen right away. An exception is when
stdout
is connected to a terminal and a newline is written with printf
. For
user interaction this is great, because the user would see the output
immediately. That's why most people print a newline along the text.
If you don't do that but you still want that the user immediately sees the
output, then this time you should use fflush
:
printf("What day is lesson %d?: ", i);
fflush(stdout);
scanf("%d", &give[0].day[i]);
I don't know if there's a guarantee that scanf
flushes stdout
when it's
connected to a terminal, regardless it is good practice to use fflush(stdout)
when you don't print a newline at the end.
Upvotes: 1
Reputation: 4647
for(i = 0; i < k; i++);
should be
for(i = 0; i < k; i++)
The extra semi colon is a problem. Your loop code is not part of a loop. The semi colon terminates the loop.
Upvotes: 2