这应该是非常简单的,但是我无法从键盘读取连续的输入。
这是代码:
#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
此外,该程序不适用于包含多个单词的字符串。
我怎么能克服这些问题?
第一 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);
OP的第一个问题通常是通过在格式前加一个空格来解决。这将占用包括前一行的空白空间 '\n'
。
// scanf("%c", &character);
scanf(" %c", &character);
此外,该程序不适用于包含多个单词的字符串。我怎么能克服这些问题?
对于第二个问题,让我们更准确地理解“字符串”和什么 "%s"
确实。
一个 串 是由第一个空字符终止并包括第一个空字符的连续字符序列。 7.1.1 1
即使报告“我输入一个字符串(例如:计算机)”,OP也没有输入字符串。 OP正在输入一行文字。 8个字符“计算机”后跟 输入。这里没有“空字符”。相反9 char
"computer\n"
。
"%s"
在 scanf("%s", string);
做3件事:
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()
(要么 getline()
在* nix系统上)。 然后 解析读取的行。
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();
最后,代码应该使用错误检查和输入宽度限制。测试所有输入函数的返回值。
您所看到的是您调用的函数的正确行为:
我应该补充一点 scanf
有它的用途,使用它交互式导致 非常 令人困惑的行为,我认为你发现了。即使在您想要逐字阅读的情况下,如果预期用途是交互式的,也可以使用其他方法。
你可以利用 %*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
将接受并忽略换行符或任何空格
你也放了 getchar()
之后 scanf
线。它会做的工作:)
流需要刷新。执行连续输入时,标准输入流stdin缓冲键盘上的每次按键。因此,当您键入“计算机”并按下回车键时,输入流也会吸收换行,即使只将字符串“computer”分配给 string
。因此,当您稍后扫描某个字符时,已加载的新行字符是扫描并分配给该字符的字符 character
。
还需要刷新stdout流。考虑一下:
...
printf("foo");
while(1)
{}
...
如果尝试执行类似这样的操作,则控制台上不会显示任何内容。系统缓冲了 stdout
stream,标准输出流,不知道接下来会遇到无限循环的事实,一旦发生这种情况,它永远不会有机会将流卸载到控制台。
显然,每当有类似的方式 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