I am writing a super simple command line based program in C. It’s just a small test and the code is very simple. So what it is meant to do is to ask the user for their name, maths grade, english grade, computing grade. Then it figures out their average grade and also tells them the name they entered. Yes I know this is an extremely simple program, but I’m still doing something wrong.
The problem is, one part of my code will run first telling the user to enter their name and then once they do this and press enter the rest of my code will run all at once and then stop working. It’s weird I just don’t understand what is wrong.
#include <stdio.h>
int main(int argc, const char * argv[])
{
char chr;
char firstname;
int mathsmark, englishmark, computingmark, averagemark;
printf("What is your name?\n");
scanf("%c", &firstname);
printf("\n");
printf("What is your maths mark?\n");
scanf("%d", &mathsmark);
printf("\n");
printf("What is your english mark?\n");
scanf("%d", &englishmark);
printf("\n");
printf("What is your computing mark?\n");
scanf("%d", &computingmark);
printf("\n");
printf("Your name is: %c", firstname);
printf("\n");
averagemark = (mathsmark + englishmark + computingmark) / 3;
printf("%d", averagemark);
printf("\n");
chr = '\0';
while (chr != '\n') {
chr = getchar ();
}
return 0;
}
One major problem is that you’ve declared
firstnameto be a single character long, and when you try to read the name from the console, you’re using the%cconversion specifier, which reads the next single character from the input stream and stores it tofirstname. The remainder of the name is left in the input stream to foul up the remainingscanfcalls.For example, if you type “Jacob” as a first name, then the first
scanfcall assignsJtofirstname, leaving"acob\n"in the input stream.The next
scanfcall attempts to convert"acob\n"to an integer value and save it tomathsmark, which fails ("acob\n"is not a valid integer string). Same thing happens for the next twoscanfcalls.The last loop
finally consumes the rest of
"acob\n", which contains the newline character (because you hit Enter after typing the name), causing the loop and program to exit.How do you fix this?
First, you need to declare
firstnameas an array ofchar:where
SOME_SIZEis large enough to handle all your cases. The you need to changescanfcall toThis tells
scanfto read characters from the input stream up to the next whitespace character and store the results to thefirstnamearray. Note that you don’t need to use the&operator here; under most circumstances, an expression of array type will be converted (“decay”) to an expression of pointer type, and the value of the expression will be the address of the first element in the array.Note that
scanfis not very safe, and it’s not very robust. If you enter more characters than your buffer is sized to hold,scanfwill happily store those extra characters to memory following the array, potentially clobbering something important. You can guard against this by using an explicit field width in the conversion specifier, likebut in general it’s a pain.
scanfis also not very good at detecting bad input. If you enter “12er” as one of your marks,scanfwill convert and assign the"12", leaving the"er"in the stream to foul up the next read.scanfreturns the number of successful assignments, so one way to guard against bad input is to check the return value, like so:Unfortunately,
scanfwon’t remove bad characters from the stream; you’ll have to do that yourself usinggetcharor similar.