Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

user input - What does `scanf("%*[^ ]%*c")` mean?

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("%*[^ ]%*c"). What does ^ mean? What does the * before ^ 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("
Welcome to the program 
 Tell me if Im clever enough! 
 Designed for humans 


");
  printf("Enter your 4 notes between 0 and 100 to calculate your course grade

");

  // 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!='
')){
      i-=1;
      scanf("%*[^
]%*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("%*[^
]%*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 

" , meanValue, grade);

  return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Breakdown of scanf("%*[^ ]%*c"):

  • %*[^ ] scans everything until a , but doesn't scan in the . The asterisk(*) tells it to discard whatever was scanned.
  • %*c scans a single character, which will be the left over by %*[^ ] 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("%*[^
]");
scanf("%*c");

to clear the stdin. This is because, in the former case (single scanf), %*[^ ] will fail when the first character to be scanned is the 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 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...