scanf()的行为

scanf()的行为,c,scanf,C,Scanf,为什么程序没有在第4行停止以获取输入 int main(int argc, char *argv[]) { int a, b; char c1, c2; printf("Enter something: "); scanf("%d",&a); // line 1 printf("Enter other something: "); scanf("%d", &b); // line 2 printf("Enter a char: "); scan

为什么程序没有在第4行停止以获取输入

int main(int argc, char *argv[])
{
  int a, b;
  char c1, c2;
  printf("Enter something: ");
  scanf("%d",&a); // line 1
  printf("Enter other something: ");
  scanf("%d", &b); // line 2

  printf("Enter a char: "); 
  scanf("%d",&c1); // line 3
  printf("Enter other char: ");
  scanf("%d", &c2); // line 4

  printf("Done"); // line 5

  system("PAUSE");  

  return 0;
}
我从一本书中读到这个问题,在上面的第4行中,scanf没有执行,但为什么?

%d希望从输入中读取一组数字,这样它可以形成一个整数,并将结果存储到您传递的指针中,在本例中,这是无效的,因为您提供了指向char的指针,但无论如何,这与此无关

问题是,如果您输入一个字符,scanf会注意到输入中没有有效的数字。它将读取此字符,将其推回输入,然后过早返回。这发生在第3行。由于该字符被推回,第4行将再次从输入中检索相同的字符,并查看输入中没有有效的整数,因此再次推回相同的字符

这里要记住的关键一点是,scanf过早返回无效输入,使输入流保持不变

例如,如果stdin包含字符a,则第3行的scanf将从输入中检索a。它发现这不是一个有效的数字,所以a返回stdin,scanf返回。在第4行,scanf调用将做同样的事情:它从输入中选择下一项,即相同的a,然后过早返回。在使用此字符之前,扫描整数将无法工作。例如,如果在第3行之后调用getchar,则使用了有问题的字符,第4行上的scanf将等待输入。

%d希望从输入中读取一组数字,以便它可以形成一个整数,并将结果存储到您传递的指针中,该指针在本例中无效,因为您提供了指向char的指针,但无论如何,这在这里无关紧要

问题是,如果您输入一个字符,scanf会注意到输入中没有有效的数字。它将读取此字符,将其推回输入,然后过早返回。这发生在第3行。由于该字符被推回,第4行将再次从输入中检索相同的字符,并查看输入中没有有效的整数,因此再次推回相同的字符

这里要记住的关键一点是,scanf过早返回无效输入,使输入流保持不变

例如,如果stdin包含字符a,则第3行的scanf将从输入中检索a。它发现这不是一个有效的数字,所以a返回stdin,scanf返回。在第4行,scanf调用将做同样的事情:它从输入中选择下一项,即相同的a,然后过早返回。在使用此字符之前,扫描整数将无法工作。例如,如果在第3行之后调用getchar,则使用了有问题的字符,第4行的scanf将等待输入。

scanf对换行有问题。解决此问题的一种快速而肮脏的方法是,在%c之前添加一个空格或\n以绕过该

  printf("Enter a char: "); 
  scanf(" %c",&c1); // line 3
  printf("Enter other char: ");
  scanf(" %c", &c2); // line 4
scanf对新线有问题。解决此问题的一种快速而肮脏的方法是,在%c之前添加一个空格或\n以绕过该

  printf("Enter a char: "); 
  scanf(" %c",&c1); // line 3
  printf("Enter other char: ");
  scanf(" %c", &c2); // line 4
将%d和%c从十进制更改为字符


将%d和%c从十进制更改为字符

使用fgets而不是scanf。格式“%d”要求参数类型为“int*”,但参数2的类型为“char*”。如果您想在输入数据时也输入空格,也可以尝试此操作:-scanf%[^\n]c,&c2;这将允许您继续输入数据,直到有足够的空间分配给变量或直到没有遇到新行为止。使用%d将代码读取到第scanf%d行的字符中,&c1;//第3行肯定会出现编译器警告。这里的主要问题不是代码混乱,而是编译器警告没有启用或遵守。启用编译器警告。使用fgets而不是scanf。格式“%d”要求参数类型为“int*”,但参数2的类型为“char*”。如果您想在输入数据时也输入空格,也可以尝试此操作:-scanf%[^\n]c,&c2;这将允许您继续输入数据,直到有足够的空间分配给变量或直到没有遇到新行为止。使用%d将代码读取到第scanf%d行的字符中,&c1;//第3行肯定会出现编译器警告。这里的主要问题不是代码混乱,而是编译器警告没有启用或遵守。打开编译器警告。这个空格会做什么?它会使scan使用换行符。Scanf读取一个换行符,该换行符由上一次调用保留在输入缓冲区中。Scanf并不健壮。FreeBSD手册页scanf3:c匹配一系列宽度计数字符,默认值为1;下一个指针必须是指向char的指针,并且必须有足够的空间容纳所有字符,不添加终止NUL。通常前导空白的跳过被抑制。若要首先跳过空白,请在格式中使用显式空格。此空格将起什么作用?它使扫描使用换行符。Scanf读取换行符
racter,它由上一次调用保留在输入缓冲区中。Scanf并不健壮。FreeBSD手册页scanf3:c匹配一系列宽度计数字符,默认值为1;下一个指针必须是指向char的指针,并且必须有足够的空间容纳所有字符,不添加终止NUL。通常前导空白的跳过被抑制。若要首先跳过空白,请在格式中使用明确的空格。请详细说明用粗体书写的单词。谢谢@巴彦特·辛格只要您在输入中有非数字的内容时,继续给scanf%d,scanf就会过早返回。scanf只使用它应该使用的stdin中的字符。如果您告诉它获取一个整数,并且输入中没有数字,它将永远不会使用任何输入。所以角色就躺在那里。在再次尝试匹配整数之前,您必须使用具有正确格式的getchar或scanf来使用它。Goncalves但是当我将最后两条语句的%d更改为%c时,输出是Enter a char:Enter other char:在这里它停止在第四个scanf而不是第三个,为什么?@Bayant_singh,因为%c接受普通字符。因此,它将使用输入流中的任何字符,包括空格和换行符。因此,第三行的scanf很可能使用了前一个输入的换行符或空格%d不使用尾随空格。@Filipe_Goncalves好的,先生…thanxx很多。STD是输入缓冲区吗?请详细说明您用粗体写的字。谢谢@巴彦特·辛格只要您在输入中有非数字的内容时,继续给scanf%d,scanf就会过早返回。scanf只使用它应该使用的stdin中的字符。如果您告诉它获取一个整数,并且输入中没有数字,它将永远不会使用任何输入。所以角色就躺在那里。在再次尝试匹配整数之前,您必须使用具有正确格式的getchar或scanf来使用它。Goncalves但是当我将最后两条语句的%d更改为%c时,输出是Enter a char:Enter other char:在这里它停止在第四个scanf而不是第三个,为什么?@Bayant_singh,因为%c接受普通字符。因此,它将使用输入流中的任何字符,包括空格和换行符。因此,第3行上的scanf很可能使用了前一个输入%d中的换行符或空格,但没有使用尾随空格。@Filipe\u Goncalves ok先生…thanxx很多。stdin是输入缓冲区吗?c1可能会使用前一个scanf%d中的“\n”值,&b;//第2行%c当然更符合OP的需要。c1可能会采用上一次扫描%d留下的'\n'值,&b;//第2行%c当然更符合OP的需要。