我想输入一个带空格的字符串,并在同一行上用另一个字符串打印该字符串。
int i = 4;
double d = 4.0;
char s[] = "Apple ";
int x;
double y;
char z[105];
scanf("%d",&x);
scanf("%lf",&y);
scanf("%[^105\n]s",z);
printf("%d\n",i+x);
printf("%0.1lf\n",d+y);
printf("%s %s",s,z);
return 0;
答案 0 :(得分:2)
您scanf
格式说明符 "%[^105]s"
使用字符类 [...]
本身是一个独立的说明符并且最后不需要's'
。通过在末尾放置's'
,您将迫使scanf
在不限数量的不包含's'
的字符之后寻找文字1, 0, 5
。
您似乎打算使用数字来保护数组边界-很好,但是在这种情况下,正确的格式是"%104[^\n]"
,它将最多读取104
个字符不包含'\n'
(保留 nul-character 的空间)。
例如:
if (scanf("%104[^\n]",z) == 1)
printf("%s %s\n",s,z);
(注意:总是通过至少检查返回值来验证所有用户输入)
也请注意:不阅读上面的'\n'
,它就留在您的输入缓冲区(stdin
)中未读,并且如果您下一次尝试输入的是{{1 }}或"%c"
,您将把"%[...]"
作为输入的一部分,因为下面的'\n'
或`“%[...]”会消耗前导空格。
在示例中将其放在一起即可:
"%c"
(注意:推荐使用#include <stdio.h>
int main (void) {
char s[] = "Apple";
char z[105];
printf ("enter z: ");
if (scanf("%104[^\n]",z) == 1)
printf("%s %s\n",s,z);
else
fputs ("error: stream error or user canceled.\n", stderr);
return 0;
}
而不是scanf
,然后只需修剪填充缓冲区中包含的fgets()
)
使用/输出示例
'\n'
改为使用$ ./bin/oneline
enter z: is a fruit
Apple is a fruit
使用fgets()
之类的面向 line _ 的输入功能,而不是使用scanf
进行行输入,这会消耗整行(包括行尾)。确保您的输入缓冲区保持一致状态,而不依赖于先前的格式说明用户,例如
fgets()
按评论编辑每个问题
您的新代码存在的问题 {> ...
#include <string.h>
...
printf ("enter z: ");
if (fgets (z, sizeof z, stdin) != NULL) {
z[strcspn (z, "\n")] = 0; /* trim '\n' from end of z */
printf("%s %s\n",s,z);
}
将scanf("%lf",&y);
留在'\n'
中未读,然后尝试读取{ {1}}不会读取什么,因为您已经排除了在倒字符类中读取stdin
的情况,然后读取了scanf("%[^105\n]",z);
作为输入,其中< strong>第一个字符是'\n'
。 stdin
的意思是:读取无限数量的字符,并且仅在遇到'\n'
或"%[^105\n]"
字符(或1, 0, 5
)时停止读取。
与'\n'
进行混合输入充满了陷阱,这是由于EOF
所剩内容以及如何领导< em>空白的处理方式取决于所使用的格式说明符。这就是为什么建议将scanf
(或POSIX stdin
)用于用户输入,然后使用fgets()
从填充的缓冲区中解析所需信息的原因。使用面向行的输入功能,每行输入都会完全消耗行(给定足够的缓冲区大小,请不要跳过),从而消除了getline()
的问题。
要使当前代码正常工作,您可以执行以下操作:
sscanf
(验证每个对scanf
的呼叫-留给您)
如果您还有其他问题,请告诉我。
答案 1 :(得分:0)
我通过在scanf(“%lf \ n ”,&y);中使用\ n解决了该问题;