Scanf 在循环中为标准输入取两个值,但只需要取一个值就可以结束循环

Scanf takes two values in loop for standard input but needs to take only one to end loop

所以此代码的要求之一是它从同一行扫描乐谱和姓名,因此我将它们放在同一个 scanf 中,输入 q 将打破循环并停止输入。问题是当不带数字输入 Q 时,它将在停止循环之前接受另一个输入。 我可以做任何修复来使这项工作正常进行吗?

     while(entered_name[0] != 'Q' && entered_name[1] != 0)
     {
        
        scanf(" %s %d", entered_name, &new_score);
        if(entered_name[0] == 'q')
        {
            entered_name[0] = toupper(entered_name[0]);
        }
     }

你应该消费带有fgets()的输入行,因为一旦实际输入与预期的不匹配,scanf()就会卡住格式化字符串。

然后在第二次,你可以用sscanf()分析得到的行。

结果给出成功提取的%个数(从左边开始),这样可以区分在这一行给出一个或两个信息的情况。

/**
  gcc -std=c99 -o prog_c prog_c.c \
      -pedantic -Wall -Wextra -Wconversion \
      -Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <stdio.h>
#include <string.h>

int
main(void)
{
  char entered_name[100]="";
  int new_score=-1;
  while((strcmp(entered_name, "Q")!=0)&&
        (strcmp(entered_name, "q")!=0))
  {
    char line[100];
    if(fgets(line, sizeof(line), stdin)==NULL)
    {
      break; // cannot read standard input any more
    }
    int r=sscanf(line, "%s %d", entered_name, &new_score);
    switch(r) // number of % extracted
    {
      case 1:
      {
        printf("entered name only: %s\n", entered_name);
        break;
      }
      case 2:
      {
        printf("entered name and score: %s %d\n", entered_name, new_score);
        break;
      }
      default:
      {
        printf("sorry, I didn't understand.\n");
      }
    }
  }
  return 0;
}

无需在一次调用中从流中提取名称和分数。当您读取 entered_name 时,分数条目(如果提供)将保持缓冲状态并由下一次调用读取:

例如:

    for(;;)
    {
        scanf(" %s", entered_name);
        if( tolower(entered_name[0]) == 'q' && entered_name[1] == '[=10=]' )
        {
            break ;
        }
        scanf(" %d", &new_score);
        
        printf( "> %s : %d\n", entered_name, new_score ) ;
    }

    printf( "End\n" ) ;

在我的测试输出中:

hjsdhsj 34                                                                                                                                                                         
> hjsdhsj : 34                                                                                                                                                                       
jkdfslkdflksdfj 99                                                                                                                                                                 
> jkdfslkdflksdfj : 99                                                                                                                                                               
q                                                                                                                                                                                  
End                                                                                                                                                                                

以这种方式使用 scanf 的智慧和安全是另一种方式。缺少错误检查和溢出保护肯定是个问题..