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
的智慧和安全是另一种方式。缺少错误检查和溢出保护肯定是个问题..
所以此代码的要求之一是它从同一行扫描乐谱和姓名,因此我将它们放在同一个 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
的智慧和安全是另一种方式。缺少错误检查和溢出保护肯定是个问题..