我的代码中有以下行:
char y[] = "a";
scanf("Letter: %s", y);
printf("%s\n", y);
第二行根本不会影响第三行的输出。我已经包含<stdio.h>
,我想不出有什么问题......
答案 0 :(得分:8)
其中一个最大的错误是在scanf
函数中包含除格式规范之外的引号之间的任何字符串(例如%s
或{{1}代码应该是%d
。如果你采取任何其他角色,那么你将不得不挠头寻找问题。
(即使您包含任何字符,您也必须输入该字符,例如 - 如果您编写scanf("%s",y)
然后输入,则必须写入scanf("letter: %s",y);
“字母,您将输入该字母“)这显然不是一个明智的想法。而C:\>letter:
函数不是打印出来的东西,只是为了从终端读取输入。要打印出来,你应该使用scanf
就是这样。
假设您必须使用一个printf("letter");
从两个int变量中获取输入,那么您将使用类似scanf()
,因为您可以看到除了引号中的格式规范之外什么都没有。
答案 1 :(得分:2)
我假设你想要一个提示,而不是一个格式字符串:
printf("Letter: ");
fflush(stdout);
scanf("%s", y);
请注意,你的字符串只能容纳一个字符。如果输入更长的字符串,则会出现缓冲区溢出。
您还应养成测试scanf
的返回值的习惯。它返回成功读取的项目数。因此,在您的示例中,如果它读取字符串,则应返回1
。因为你没有对它进行测试,所以你花了很多时间试图弄清楚什么是错的,而实际上它会告诉你没有读过任何物品。
答案 2 :(得分:1)
其他答案已正确诊断scanf()
未输出任何数据(特别是不会生成任何提示),而问题似乎预计scanf("Letter: %s", y)
将输出提示{{ 1}}然后阅读回复。如果输入了多个字符,还有一些问题,例如没有检查Letter:
的返回值和缓冲区溢出。
其中一个答案表明格式字符串中不应包含转换规范以外的字符。这个答案主要是一个反例,展示了其他角色如何至关重要。您可以使用此示例代码并对其进行修改,以提高您对scanf()
函数族如何工作的理解。请注意,它不是一个交互式程序;它使用scanf()
转换数据,几乎就像数据已被sscanf()
读取一样。 练习:为什么它只是'几乎就像'而不仅仅是'好像'?
考虑您正在处理使用以下行格式化的文件:
fgets()
假设您想要阅读这四个数字,您的格式字符串很可能是以下变体:
centre (23, 41) size (19, 42)
这几乎是合理的。但是,没有办法用这种格式来发现缺少第二个右括号。为了确保存在最后的括号,您需要一个格式字符串,如:
"centre (%d,%d) size (%d,%d)"
其中空格允许输入间距的许多变化,而扫描集("centre (%d ,%d ) size (%d ,%d %1[)]"
)需要一个紧密的括号。您将测试%1[)]
返回的5个字段。请注意,如果使用扫描集(scanf()
)抑制了赋值,则如果缺少括号,则不会出现错误指示。这是一个判断调用,关于你希望在你接受的有效输入中有多灵活。
%*1[)]
#include <stdio.h>
int main(void)
{
int x1, y1, x2, y2;
char str[10];
const char *data[] =
{
"centre ( 19, 43 ) size ( 21, 37 )",
"centre (19, 43) size (21, 37)",
"centre (19, 43) size (21, 37",
"centre(19,43) size(21,37)",
"centre(19,43) size(21,37",
"centre ( 19 , 43 ) size ( 21 , 37 )",
};
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
const char *format5[] =
{
"centre (%d ,%d ) size (%d ,%d %[)]",
"centre (%d,%d) size (%d,%d%[)]",
};
enum { NUM_FORMAT5 = sizeof(format5) / sizeof(format5[0]) };
const char *format4[] =
{
"centre (%d ,%d ) size (%d ,%d )",
"centre (%d,%d) size (%d,%d)",
};
enum { NUM_FORMAT4 = sizeof(format4) / sizeof(format4[0]) };
printf("Format 5\n");
for (int i = 0; i < NUM_FORMAT5; i++)
{
printf("Format: <<%s>>\n", format5[i]);
for (int j = 0; j < NUM_DATA; j++)
{
int rc;
printf(" Data: <<%s>>\n", data[j]);
if ((rc = sscanf(data[j], format5[i], &x1, &y1, &x2, &y2, str)) != 5)
printf("!! Failed: scanf() returned %d\n", rc);
else
printf("== Passed: centre(%d,%d) size(%d,%d)\n", x1, y1, x2, y2);
}
}
printf("\nFormat 4\n");
for (int i = 0; i < NUM_FORMAT4; i++)
{
printf("Format: <<%s>>\n", format4[i]);
for (int j = 0; j < NUM_DATA; j++)
{
int rc;
printf(" Data: <<%s>>\n", data[j]);
if ((rc = sscanf(data[j], format4[i], &x1, &y1, &x2, &y2)) != 4)
printf("!! Failed: scanf() returned %d\n", rc);
else
printf("== Passed: centre(%d,%d) size(%d,%d)\n", x1, y1, x2, y2);
}
}
return 0;
}
请注意,当缺少第二个右括号时,“格式4”下的格式字符串如何接受数据。即使缺少该字符,也满足4个转换规范。 '格式5'格式拒绝这些数据行。
示例代码和数据没有演示它,但代码也很乐意读取多个紧密括号(因为它使用Format 5
Format: <<centre (%d ,%d ) size (%d ,%d %[)]>>
Data: <<centre ( 19, 43 ) size ( 21, 37 )>>
== Passed: centre(19,43) size(21,37)
Data: <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre (19, 43) size (21, 37>>
!! Failed: scanf() returned 4
Data: <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre(19,43) size(21,37>>
!! Failed: scanf() returned 4
Data: <<centre ( 19 , 43 ) size ( 21 , 37 )>>
== Passed: centre(19,43) size(21,37)
Format: <<centre (%d,%d) size (%d,%d%[)]>>
Data: <<centre ( 19, 43 ) size ( 21, 37 )>>
!! Failed: scanf() returned 2
Data: <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre (19, 43) size (21, 37>>
!! Failed: scanf() returned 4
Data: <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre(19,43) size(21,37>>
!! Failed: scanf() returned 4
Data: <<centre ( 19 , 43 ) size ( 21 , 37 )>>
!! Failed: scanf() returned 1
Format 4
Format: <<centre (%d ,%d ) size (%d ,%d )>>
Data: <<centre ( 19, 43 ) size ( 21, 37 )>>
== Passed: centre(19,43) size(21,37)
Data: <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre (19, 43) size (21, 37>>
== Passed: centre(19,43) size(21,37)
Data: <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre(19,43) size(21,37>>
== Passed: centre(19,43) size(21,37)
Data: <<centre ( 19 , 43 ) size ( 21 , 37 )>>
== Passed: centre(19,43) size(21,37)
Format: <<centre (%d,%d) size (%d,%d)>>
Data: <<centre ( 19, 43 ) size ( 21, 37 )>>
!! Failed: scanf() returned 2
Data: <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre (19, 43) size (21, 37>>
== Passed: centre(19,43) size(21,37)
Data: <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
Data: <<centre(19,43) size(21,37>>
== Passed: centre(19,43) size(21,37)
Data: <<centre ( 19 , 43 ) size ( 21 , 37 )>>
!! Failed: scanf() returned 1
)。通过使用%[)]
来规定最后只有一个紧密括号,可以避免这种情况。您还可以使用%1[)]
转换规范和第六个参数(另一个%n
)来获取处理的字符数。这将允许您检测扫描停止的位置,从而检测所需输入后是否有未处理的字符。请注意,int *
转换规范不计入%n
等的返回值。该片段可以粘贴在代码中的scanf()
函数的末尾:
main()
它生成输出:
printf("\nFormat 6\n");
int len, rc;
const char data6[] = "centre ( 19 , 43 ) size ( 21 , 37 )))";
const char format6[] = "centre (%d ,%d ) size (%d ,%d %1[)]%n";
printf("Format: <<%s>>\n", format6);
printf(" Data: <<%s>>\n", data[5]);
if (sscanf(data6, format6, &x1, &y1, &x2, &y2, str, &len) != 5)
printf("!! Failed: scanf() returned %d\n", rc);
else
printf("== Passed: centre(%d,%d) size(%d,%d) len=%d <<%s>>\n",
x1, y1, x2, y2, len, &data6[len]);
如果你理解为什么会得到每个结果,你就会对Format 6
Format: <<centre (%d ,%d ) size (%d ,%d %1[)]%n>>
Data: <<centre ( 19 , 43 ) size ( 21 , 37 )))>>
== Passed: centre(19,43) size(21,37) len=35 <<))>>
有一个很好的理解。如果您不确定原因,请尝试并阅读规范(例如POSIX sscanf()
),直到您确定理解它为止。
答案 3 :(得分:0)
在你的案例中
char y[] = "a";
scanf("Letter: %s", y);
printf("%s\n", y);
您应该提供这样的输入。
信:abcd
它会正常工作
例如,如果scanf是这样写的
int y;
scanf("y=%d", &y);
然后你应该给出像
这样的输入<强> Y = 10 强>
不 10
我想你得到了你想要的...... :)现在享受