scanf - 程序等待另一个程序类似于什么?

5
在下面的程序中,我期望在输入一个单词并按下回车键后立即看到打印出来的信息。然而,直到我输入其他随机单词之后才会发生这种情况。为什么会这样?
#include <cstdio>
#include <cstdlib>

using namespace std;

char tictac[17];

int main() 
{
    scanf("%s\n", tictac);


    printf("%s\n", tictac);
    return 0;
}

1
在 C 中,你不使用 using namespace std;。即使在 C++ 中也不应该使用它。 - sobol6803
1
@sobol6803 这只是一个快速演示,用C++编写的,并不是真正的代码 :) - Novellizator
3个回答

4
tl;dr: 使用 scanf("%s\n", tictac); 时,你是要求读取一个字符串,忽略其后的所有空格字符,然后读取一个新行。问题在于,由于第一个空格字符之后的所有空格都被忽略了,因此第一个 Enter 和第二个 Enter 之间必须至少有一个非空格字符(因此在接受第二个 Enter 之前需要一些垃圾的 非空格 输入)。
这里是使用 \n 和 scanf 的一个示例用法。
char x, y;
scanf("%c", &x); 
scanf("%c", &y);
printf("%c %c", x,y); 

使用这个代码,您会发现输入一个字符并按下Enter键将直接跳转到printf语句。这是因为第二个scanf读入了回车(本身就是一个字符)到y中。
scanf("\n%c", &y);  // This is recommended to do if you have a sequence of scanfs (but not on the first one).

这里使用 \n 来匹配或忽略多余的换行符,正确的字符将被读入到变量 y 中。


现在我们来看你的代码

scanf("%s\n", tictac);
%s命令scanf读取直到找到空格字符空格,制表符或换行符),然后在遇到非空格字符之前忽略所有空格字符。 因此,scanf将忽略您输入字符串时按下的Enter键。以及其后的任何空格字符尝试在第二行输入空格并按回车键。

这意味着这将正常工作(不像char版本)

scanf("%s", tictac);
scanf("%s", tictac2);

实际上,在Windows中,因为"%s"会导致库读取输入字符串直到找到一些空格,所以等价的格式说明符是"%[^\0x20\t\n]",它指示库读取字符串直到遇到空格字符(\0x20)、制表符(\t)或换行符(\n)。

但是,由于您已明确要求scanf匹配\n

scanf("%s\n", tictac);
         ^^

它会等待直到获取到另一个\n(在非空字符后),因为第一个已被%s使用。


你能否请进一步解释一下scanf函数?如果我理解正确的话,scanf("%s\n",var)首先将字符串(直到遇到空格)读入变量var,并忽略紧随字符串后的空格(包括回车键)。然后它会等待新的一行"\n"吗?附注:我使用cstdio库以提高性能和降低内存消耗。 - Novellizator
@Novellizator 这里的意思并不是新行,而是等待每个输入后的 回车(键盘上的回车)。尝试使用 scanf("%d %d %d", &x,&y,&z);scanf("%d\n%d\n%d", &x,&y,&z);,你会看到它们之间的区别。 - user995502
尝试了上面的例子 - 我看不出任何区别...在两种情况下,我都尝试将所有数字写在一行中,并按下回车键输入每个值。但在这两种情况下都没有任何区别。 - Novellizator
@Novellizator 请看我的编辑,我认为这样更详细地解释了。 - user995502
"%s告诉scanf函数读取直到找到一个空白字符...然后忽略所有的空格直到遇到一个非空格字符。"这种说法是错误的。%s首先扫描空白字符,但不存储它们。然后它扫描非空白字符,并将其存储起来。它存储一个NUL字符,然后停止。接下来的\n才会扫描空白字符,但不存储任何内容。这个过程会一直持续,直到遇到一个非空白字符为止。注意:空白字符不仅限于' '、\t和\n。 - chux - Reinstate Monica

3
从您的scanf调用中删除\n

1

这里有一个关于scanf的好解释在这里。在你的情况下,你应该从scanf函数中删除\n。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接