C语言 `scanf("%*[^\n]%*c")` 是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30065675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:55:03  来源:igfitidea点击:

What does `scanf("%*[^\n]%*c")` mean?

cuser-inputscanfformat-specifiers

提问by Gustavo Alejandro Castellanos

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.

我想在 C 中创建一个循环,当程序要求输入一个整数并且用户键入一个非数字字符时,程序再次要求输入一个整数。

I just found the below code. but I don't understand what this means scanf("%*[^\n]%*c"). What does ^\nmean? What does the *before ^\nand cmean?

我刚刚找到了下面的代码。但我不明白这是什么意思scanf("%*[^\n]%*c")。什么^\n意思?是什么在*之前^\nc意味着什么?

/*

 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;
}

回答by Spikatrix

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

细分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.
  • %*cscans a single character, which will be the \nleft over by %*[^\n]in this case. The asterisk instructs scanfto discard the scanned character.
  • %*[^\n]扫描所有内容直到 a \n,但不扫描\n. 星号( *) 告诉它丢弃扫描的任何内容。
  • %*c扫描单个字符,在这种情况下将是\n剩余的%*[^\n]。星号指示scanf丢弃扫描的字符。

Both %[and %care 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.

这两个%[%c格式说明。你可以在这里看到他们做什么。两个说明符中的星号告诉scanf, 不存储这些格式说明符读取的数据。

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.

正如@chux 在下面评论的那样,它将清除stdin(标准输入流)的一行,直到并包括换行符。在您的情况下,输入无效的行会从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 \ncharacter and the rest of the format string of the scanfwill be skipped which means that the %*cwill not function and thus, the \nfrom the input will still be in the input stream. In this case, this will not happen as even when the first scanffails, the second one will execute as they are separate scanfstatements.

清除stdin. 这是因为,在前一种情况下(单个scanf),%*[^\n]当要扫描的第一个字符是\n字符时将失败,并且scanf将跳过的其余格式字符串,这意味着%*c将不起作用,因此,\n来自输入仍将在输入流中。在这种情况下,这不会发生,因为即使第一个scanf失败,第二个也会执行,因为它们是单独的scanf语句。

回答by Tanishka Singhal

You can take a string as input in C using scanf(“%s”, s). But, it accepts string only until it finds the first space.

您可以使用字符串作为 C 中的输入scanf(“%s”, s)。但是,它只接受字符串,直到找到第一个空格。

In order to take a line as input, you can use scanf("%[^\n]%*c", s);where is defined as char s[MAX_LEN]where MAX_LENis the maximum size of s . Here, []is the scanset character.

为了将一行作为输入,您可以使用scanf("%[^\n]%*c", s);where 定义为char s[MAX_LEN]whereMAX_LEN是 s 的最大大小。这里,[]是扫描集字符。

  1. ^\nstands for taking input until a newline isn't encountered.

  2. Then, with this %*c, it reads the newline character and here, the used *indicates that this newline character is discarded.

  1. ^\n代表接受输入直到没有遇到换行符。

  2. 然后,用 this %*c,它读取换行符,这里, used*表示这个换行符被丢弃。

Also note that: After inputting the character and the string, inputting the sentence by the above mentioned statement won't work. This is because, at the end of each line, a new line character \nis present. So, the statement: scanf("%[^\n]%*c", s);will not work because the last statement will read a newline character from the previous line. This can be handled in a variety of ways and one of them being: scanf("\n");before the last statement.

还要注意的是:输入字符和字符串后,按上述语句输入语句将不起作用。这是因为,在每一行的末尾,存在一个换行符\n。因此,语句:scanf("%[^\n]%*c", s);将不起作用,因为最后一条语句将从前一行读取换行符。这可以通过多种方式处理,其中之一是:scanf("\n");在最后一条语句之前。

回答by Gagan Agarwal

You can take a string as input in C using scanf(“%s”, s). But, it accepts string only until it finds the first space.

您可以使用字符串作为 C 中的输入scanf(“%s”, s)。但是,它只接受字符串,直到找到第一个空格。

In order to take a line as input, you can use scanf("%[^\n]%*c", s);where sis defined as char s[MAX_LEN]where MAX_LENis the maximum size of s. Here, []is the scanset character. ^\nstands for taking input until a newline isn't encountered. Then, with this %*c, it reads the newline character and here, the used *indicates that this newline character is discarded.

为了将一行作为输入,您可以使用scanf("%[^\n]%*c", s);wheres定义为char s[MAX_LEN]whereMAX_LEN是 的最大大小s。这里,[]是扫描集字符。^\n代表接受输入直到没有遇到换行符。然后,用 this %*c,它读取换行符,这里, used*表示这个换行符被丢弃。

回答by Debanshu Datta

Suppose char sen[max_length] where maximum length is maximum size of sen[].

假设 char sen[max_length] 其中最大长度是 sen[] 的最大大小。

this scanf(“%[^\n]%*c”,&sen[]);will help you to get a entire sentence until the next line isn't encountered “\n”or enter is pressed which is done with the help of “%[^\n]”here [ ]is the scan set character . the ”%*c”will read the newline character , asterisk ” * ”is used to indicate that the next line character is discarded.

这个scanf(“%[^\n]%*c”,&sen[]); 将帮助您获得整个句子,直到没有遇到下一行“\n”或按下回车键,这是在“%[^\n]”的帮助下完成的,这里[]是扫描集字符。的“%* C”将读取换行符,星号” *”被用于指示下一行字符被丢弃。

回答by Pranit Patil

%[^\n]%*c

%[^\n]%*c

Which will read everything up to the newline into the string you pass in, then will consume a single character (the newline) without assigning it to anything (that '*' is 'assignment suppression').

这会将换行符之前的所有内容读入您传入的字符串中,然后将使用单个字符(换行符)而不将其分配给任何内容(“*”是“赋值抑制”)。

Otherwise,the newline is left in the input stream waiting to immediately terminate the the subsequent %[^\n]format directives.

否则,换行符会留在输入流中,等待立即终止后续的%[^\n]格式指令。

The problem with adding a space character to the format directive (%[^\n]) is that the space will match any white space. So, it will eat the newline from the end of the previous input, but it will also eat any other whitespace (including multiple newlines).

向格式指令 ( %[^\n])添加空格字符的问题在于空格将匹配任何空格。因此,它会吃掉前一个输入末尾的换行符,但也会吃掉任何其他空格(包括多个换行符)。