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

我想你得到了你想要的…… :)现在享受