struct{
int year;
int unit;
int NumberOfSubject;
float gpa;
char semester[5];
char NameOfSubject[60][50];
char grade;
char name[40];
}student;
char CreatAccount(void)
{
int i;
char ans;
database= fopen("database.rtf", "w");
printf("\tThis is registration page\n");
printf("Please enter your name\n");
fgets(student.name,40,stdin);
printf("Is your name %s?, Y/N\n", student.name);
scanf("%c", &ans);
if (ans == 'y' || ans == 'Y')
{
printf("Registration is successfully completed!. Name on your account is %s",student.name);
fopen("database.txt", "w");
for (i=0; student.name[i] != '\n'; i )
{
fputc(student.name[i], database);
}
fclose(database);
int i;
int j;
printf("Please enter year\n");
scanf("%d",&(student.year));
fflush(stdin);
printf("Please enter semester\n");
fgets(student.semester,10,stdin);
printf("Please enter units you have taken\n");
scanf("%d",&(student.unit));
printf("Please enter number of subjects you are taking at this moment\n");
scanf("%d",&(student.NumberOfSubject));
fflush(stdin);
for (i=0; i<student.NumberOfSubject; i )
{
printf("Please enter the name of subjects you are taking\n");
fgets(student.NameOfSubject[i],50,stdin);
printf("Your %dth Subject is %s\n",i 1,student.NameOfSubject[i]);
}
printf("Registration is completed! Here is your information\n\n");
printf("Your year:%d\n",student.year);
printf("Semester:%s\n",student.semester);
printf("Units:%d\n",student.unit);
for (j=0; j<student.NumberOfSubject; j )
{
printf("Name of subjects:%s",student.NameOfSubject[j]);
}
printf("Number of subjects:%d\n",student.NumberOfSubject);
}
I just can't find the cause of this problem. When the output is printed out, there are things that shouldn't be there. I want to spot what the cause is for this matter. Thanks returnFor instance, if I enter following input
2022 -year
fall-semester
12-units
3-number of subjects
math,english,physics
the output will be this,
Your year:2022
Semester:fall
english // shouldn't be printed
//shouldn't be next-line space here
Units:12
Name of subjects:english
Name of subjects:math
Name of subjects:physics
Number of subjects:3
CodePudding user response:
fflush(stdin);
is undefined behavior.
In fgets()
newline character is present at length - 1
position.
Also, never ever mix scanf()
with fgets()
.
size_t len = strlen(str); // str is your string
if(str[len - 1] == '\n')
str[len - 1] = 0;
Edit: better one
str[strcspn(str, "\n")] = '\0'
CodePudding user response:
There are a couple of issues in your code:
- You are mixing
scanf
withfget
. They don't work the same way, so you shouldn't use them altogether (unless you are very careful). fflush(stdin)
is undefined behaviour. The only way to flushstdin
is by reading what's in it.scanf
can be a dangerous function if you misuse it (and you clearly are). You need to check its return value and, in case it fails, perform some actions.fgets
reads also the newline (the character when you press Enter). You have to replace it with a null-terminator.
I just can't find the cause of this problem.
The last point above explains why.
scanf
does not read user input. It parses it. That's what its name says: scan formatted. And scanning may fail, and when it does, it leaves the input buffer intact. So it's up to you to "flush" (i.e. clear, or read-and-discard everything in) it.
void fflush_stdin(void)
{
scanf("%*[^\n]");
}
Addressing scanf
failure is done by checking its return value. From cppreference:
Return value
Number of receiving arguments successfully assigned (which may be zero in case a matching failure occurred before the first receiving argument was assigned), or EOF if input failure occurs before the first receiving argument was assigned.
bool read_char(const char *msg, char *c)
{
do {
printf("%s", msg);
int ret = scanf(" %c", c); // Note the extra space before %c. It means match all space characters before a given character is met.
switch (ret) {
case EOF: return false;
case 1: return true;
default:
flush_stdin();
printf("Input error.\n");
break;
}
} while (true);
return true; // This won't run.
}
The same thing goes for int
s, float
s, etc. For scanning strings, you have to provide the length of the char
buffer:
char buffer[100];
scanf("