I want to make a loop in C that, when the program asks for an integer and the user types a non-digit character, the program asks again for an integer.
I just found the below code. but I don't understand what this means scanf("%*[^\n]%*c")
. What does ^\n
mean? What does the *
before ^\n
and c
mean?
/*
This program calculate the mean score of an user 4 individual scores,
and outputs the mean and a final grade
Input: score1, score2,score2, score3
Output: Mean, FinalGrade
*/
#include <stdio.h>
//#include <stdlib.h>
int main(void){
int userScore = 0; //Stores the scores that the user inputs
float meanValue = 0.0f; //Stores the user mean of all the notes
char testChar = 'f'; //Used to avoid that the code crashes
char grade = 'E'; //Stores the final
int i = 0; //Auxiliar used in the for statement
printf("\nWelcome to the program \n Tell me if Im clever enough! \n Designed for humans \n\n\n");
printf("Enter your 4 notes between 0 and 100 to calculate your course grade\n\n");
// Asks the 4 notes.
for ( ; i<=3 ; i++ ){
printf("Please, enter your score number %d: ", i+1);
//If the note is not valid, ask for it again
//This is tests if the user input is a valid integer.
if ( ( scanf("%d%c", &userScore, &testChar)!=2 || testChar!='\n')){
i-=1;
scanf("%*[^\n]%*c");
}else{ //Enter here if the user input is an integer
if ( userScore>=0 && userScore<=100 ){
//Add the value to the mean
meanValue += userScore;
}else{ //Enter here if the user input a non valid integer
i-=1;
//scanf("%*[^\n]%*c");
}
}
}
//Calculates the mean value of the 4 scores
meanValue = meanValue/4;
// Select your final grade according to the final mean
if (meanValue>= 90 && meanValue <=100){
grade = 'A';
} else if(meanValue>= 80 && meanValue <90){
grade = 'B';
} else if (meanValue>= 70 && meanValue <80){
grade = 'C';
} else if(meanValue>= 60 && meanValue <70){
grade = 'D';
}
printf("Your final score is: %2.2f --> %c \n\n" , meanValue, grade);
return 0;
}
Breakdown of scanf("%*[^\n]%*c")
:
%*[^\n]
scans everything until a \n
, but doesn't scan in the \n
. The asterisk(*
) tells it to discard whatever was scanned.%*c
scans a single character, which will be the \n
left over by %*[^\n]
in this case. The asterisk instructs scanf
to discard the scanned character.Both %[
and %c
are format specifiers. You can see what they do here. The asterisks in both the specifiers tell scanf
, not to store the data read by these format specifiers.
As @chux commented below, it will clear a single line of the stdin
(Standard Input Stream) up to and including the newline character. In your case, the line with invalid input gets cleared from the stdin
.
It is better to use
scanf("%*[^\n]");
scanf("%*c");
to clear the stdin
. This is because, in the former case (single scanf
), %*[^\n]
will fail when the first character to be scanned is the \n
character and the rest of the format string of the scanf
will be skipped which means that the %*c
will not function and thus, the \n
from the input will still be in the input stream. In this case, this will not happen as even when the first scanf
fails, the second one will execute as they are separate scanf
statements.