scanf不打印或读取任何内容
我的代码中有以下行:
char y[] = "a"; scanf("Letter: %s", y); printf("%s\n", y);
第二行根本不影响第三行的输出。 我已经包含了 ,我想不出有什么问题……
其中一个最大的错误就是在scanf
函数中包含除格式规范之外的引号之间的任何字符串(如%s
或%d
)。代码应该是scanf("%s",y)
。如果你采取的话任何其他角色,那么你将不得不挠头寻找问题。
(即使你包含任何字符,你也必须输入该字符,例如 – 如果你写scanf("letter: %s",y);
那么在输入时你必须像C:\>letter:
一样写C:\>letter:
“你的字母将输入“ )这显然不是一个明智的想法。而且scanf
函数不存在打印出来的东西,它只是从终端读取输入。打印输出你应该使用printf("letter");
而已。
假设您必须使用一个scanf()
从两个int变量中获取输入,然后您将使用类似scanf("%d%d",&a,&b);
正如你所看到的,除了引号中的格式规范之外我什么都没有。
我假设你想要一个提示,而不是一个格式字符串:
printf("Letter: "); fflush(stdout); scanf("%s", y);
请注意,您的字符串只能容纳一个字符。 如果输入更长的字符串,则会出现缓冲区溢出。
你也应该养成测试scanf
返回值的习惯。 它返回成功读取的项目数。 因此,在您的示例中,如果它读取字符串,则应返回1
。 因为你没有对它进行测试,所以你花了很多时间试图弄清楚什么是错的,而事实上它会告诉你没有读过任何物品。
其他答案已经正确诊断出scanf()
不输出任何数据(特别是,不会产生任何提示),而问题似乎是期望scanf("Letter: %s", y)
将输出提示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[)]
)需要一个紧密的括号。 您将测试scanf()
返回5个字段。 请注意,如果使用扫描集( %*1[)]
抑制了赋值,则如果缺少括号,则不会出现错误指示。 这是一个判断调用,关于你希望在你接受的有效输入中有多灵活。
码
#include 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; }
产量
Format 5 Format: <> Data: < > == Passed: centre(19,43) size(21,37) Data: < > == Passed: centre(19,43) size(21,37) Data: < > !! Failed: scanf() returned 4 Data: <> == Passed: centre(19,43) size(21,37) Data: <> !! Failed: scanf() returned 4 Data: < > == Passed: centre(19,43) size(21,37) Format: < > Data: < > !! Failed: scanf() returned 2 Data: < > == Passed: centre(19,43) size(21,37) Data: < > !! Failed: scanf() returned 4 Data: <> == Passed: centre(19,43) size(21,37) Data: <> !! Failed: scanf() returned 4 Data: < > !! Failed: scanf() returned 1 Format 4 Format: < > Data: < > == Passed: centre(19,43) size(21,37) Data: < > == Passed: centre(19,43) size(21,37) Data: < > == Passed: centre(19,43) size(21,37) Data: <> == Passed: centre(19,43) size(21,37) Data: <> == Passed: centre(19,43) size(21,37) Data: < > == Passed: centre(19,43) size(21,37) Format: < > Data: < > !! Failed: scanf() returned 2 Data: < > == Passed: centre(19,43) size(21,37) Data: < > == Passed: centre(19,43) size(21,37) Data: <> == Passed: centre(19,43) size(21,37) Data: <> == Passed: centre(19,43) size(21,37) Data: < > !! Failed: scanf() returned 1
请注意当缺少第二个右括号时,“格式4”下的格式字符串如何接受数据。 即使缺少该字符,也满足4个转换规范。 ‘格式5’格式拒绝这些数据行。
示例代码和数据没有演示它,但代码也很乐意读取多个紧密的括号(因为它使用%[)]
)。 这可以通过使用%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: <> Data: < > == Passed: centre(19,43) size(21,37) len=35 <<))>>
摘要
如果你理解为什么获得每个结果,你就可以理解scanf()
。 如果您不确定原因,请尝试并阅读规范(例如POSIX sscanf()
),直到您确定理解为止。
在你的情况下
char y[] = "a"; scanf("Letter: %s", y); printf("%s\n", y);
你应该给这样的输入。
信:abcd
它会正常工作
例如,如果scanf是这样写的
int y; scanf("y=%d", &y);
那么你应该给像输入
Y = 10
不是10
我想你得到了你想要的…… :)现在享受