使用scanf()从键盘读取时读取前一输入的换行符

时间:2015-04-27 20:08:25

标签: c string char

这应该很简单,但是我无法从键盘读取连续输入。

以下是代码:

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

int main()
{
    char string[200];
    char character;
    printf ("write something: ");
    scanf ("%s", string);
    printf ("%s", string);
    printf ("\nwrite a character: ");
    scanf ("%c", &character);
    printf ("\nCharacter %c  Correspondent number: %d\n", character, character);

    return 0;
}

发生了什么

当我输入一个字符串(例如:计算机)时,程序会读取换行符('\n')并将其放入character。以下是显示的外观:

 write something: computer
 computer
 Character:
    Correspondent number: 10

此外,该程序不适用于包含多个单词的字符串。 我怎么能克服这些问题?

6 个答案:

答案 0 :(得分:9)

首先scanf读取输入的字符串并在输入缓冲区中留下\n。下次致电scanf,请阅读\n并将其存储到character 试试这个

scanf (" %c", &characte);   
     // ^A space before %c in scanf can skip any number of white space characters. 

程序不适用于多个字符串的字符串,因为scanf一旦找到空格字符就会停止读取。您可以使用fgets代替

 fgets(string, 200, stdin);

答案 1 :(得分:5)

OP的第一个问题通常是通过在格式前加一个空格来解决的。这将占用空白区域,包括前一行的'\n'

// scanf("%c", &character);
scanf(" %c", &character);
  

此外,该程序不适用于包含多个单词的字符串。我怎么能克服这些问题?

对于第二个问题,让我们更准确地理解“字符串”和"%s"的作用。

  

string 是由第一个空字符终止并包含第一个空字符的连续字符序列。 7.1.1 1

即使报告“我输入一个字符串(例如:计算机)”,OP也没有输入字符串。 OP正在输入一行文字。 8个字符“computer”后跟 Enter 。这里没有“空字符”。取而代之的是9 char "computer\n"

"%s"中的{p> scanf("%s", string);做了三件事:

1)扫描,但不保存任何前导空格。

2)扫描并保存到string任意数量的非空白区域。

3)到达空白区域或EOF时停止扫描。那个char只能回到stdin'\0'附加string,使char数组成为C 字符串

要阅读包含空格的行,请不要使用scanf("%s",...。考虑fgets()

fgets(string, sizeof string, stdin);
// remove potential trailing \r\n as needed
string[strcspn(string, "\n")] = 0;

混合scanf()fgets()是一个问题,因为scanf("%s", string); fgets(...)之类的调用会让'\n' stdin中的fgets()作为一行读取仅由"\n"组成。建议使用fgets()(或* nix系统上的getline())读取所有用户输入。 然后解析读取的行。

fgets(string, sizeof string, stdin);
scanf(string, "%c", &character);

如果代码必须用户scanf()来读取包含空格的用户输入:

scanf("%*[\n]"); // read any number of \n and not save.
// Read up to 199 `char`, none of which are \n
if (scanf("%199[^\n]", string) != 1) Handle_EOF();

最后,代码应该使用错误检查和输入宽度限制。测试所有输入函数的返回值。

答案 2 :(得分:3)

您所看到的是您所调用的功能的正确行为:

  • scanf将从输入中读取一个字,并在输入的字后立即保留输入指针。如果您键入computer<RETURN>,则要读取的下一个字符是换行符。

  • 要阅读整行,包括最终换行符,请使用fgets。仔细阅读文档:fgets返回一个字符串,其中包含它读取的最终换行符。 (gets,由于多种原因无论如何都不应该使用,会读取并丢弃最终换行符。)

我应该补充一点,scanf有其用途,交互式使用它会导致非常混淆行为,正如我认为你发现的那样。即使在您想要逐字阅读的情况下,如果预期用途是交互式的,也可以使用其他方法。

答案 3 :(得分:0)

您可以使用%*c

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

int main()
{
    char string[200];
    char character;
    printf ("write something: ");
    scanf ("%s%*c", string);
    printf ("%s", string);
    printf ("\nwrite a character: ");
    scanf ("%c%*c", &character);
    printf ("\nCharacter %c  Correspondent number: %d\n", character, character);

    return 0;
}

%*c将接受并忽略换行符或任何空格

答案 4 :(得分:0)

您也将getchar()放在scanf行之后。它将完成这项工作:)

答案 5 :(得分:-1)

需要刷新流。执行连续输入时,标准输入流stdin缓冲键盘上的每次按键。所以,当你输入&#34;计算机&#34;并按下回车键,输入流也吸收了换行,即使只有字符串&#34;计算机&#34;被分配到string。因此,当您稍后扫描某个字符时,已加载的新行字符是扫描并分配给character的字符。

还需要刷新stdout流。考虑一下:

...
printf("foo");
while(1)
{}
...

如果尝试执行类似这样的操作,则控制台上不会显示任何内容。系统缓冲了stdout流,标准输出流,不知道接下来会遇到无限循环的事实,一旦发生这种情况,它就永远不会有机会将流卸载到控制台。

显然,只要scanf阻塞程序并等待stdin(标准输入流),它就会以类似的方式影响其他缓冲流。无论如何,无论如何,如果事情开始笨拙,最好能够正确地冲洗流。

以下对代码的修改似乎产生了所需的输出

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

int main()
{
char string[200];
char character;

printf ("write something: ");

fflush(stdout);

scanf ("%s", string);

fflush(stdin);

printf ("%s", string);
printf ("\nwrite a character: ");

fflush(stdout);

scanf ("%c", &character);
printf ("\nCharacter %c  Correspondent number: %d\n", character, character);

return 0;
} 

输出
写点东西:电脑
计算机
写一个字符:a

字符对应号码:97