有人可以就扫描提供建议吗? "消息"是一个由 4 行 x 16 列组成的数组。 用户输入数字(所有 1 位整数)后,点击"Enter"时会出现错误消息。如前所述 - 可能是扫描有关的东西。
for (int i = 0; i < M; i++) {
for (int j = 0; j < columns; j++) {
scanf("%d", message[i][j]);
}
}
scanf
似乎是一种很好,简单,容易,方便的读取输入的方法。 在某些方面确实如此,但事实证明,正确使用它可能会非常困难,而且充满了陷阱。
一开始,你可能不会想了解scanf
的所有错综复杂之处。 因此,就目前而言,这里有一些安全使用scanf
功能子集的准则。 (由于我不明白的原因,每个人都告诉初学者使用scanf
,但没有人教过这样的规则。
- 请记住始终在您尝试读取的变量前面使用
&
。 (这是一项特殊规则,仅供scanf
使用。 例如,不要尝试在传递给printf
的变量上使用该&
。 - 规则 1 的例外情况:读取带有
%s
的字符串时,请勿使用该&
。 - 如果使用
%s
读取字符串,请确保读取的变量要么是足以容纳用户可能键入的内容的字符数组,要么是指向足够大的内存malloc
指针,该内存对于用户可能键入的内容足够大。 (另请参阅下面有关避免溢出的说明。 - 请注意,
%s
读取不包含空格字符的字符串。 不能使用%s
读取可能包含空格的字符串(如全名)。 (现在,请不要担心如何读取可能包含空格的字符串。 另请参阅规则 14。 - 不要尝试在同一程序中同时使用
scanf
和fgets
(或过时的gets
)。 - 不要尝试在同一程序中同时使用
scanf
和getchar
。 - 尽量将自己限制为仅使用格式说明符
%d
、%s
、%f
和%lf
,以分别读入类型分别为int
、字符串(参见规则3)、float
和double
的变量。 - 如果你想将一个字符读入
char
类型的变量中,你可以使用" %c"
,但是那里神秘的额外显式空格字符是至关重要的。 - 在格式字符串中仅使用一个
%
符号来读取一个变量。 不要尝试在一次scanf
调用中读取两个或多个变量。 -
始终检查
scanf
的返回值。 如果它返回 0,或者负值EOF
,则表示它没有成功读取任何内容。 如果它返回 1,则表示它已成功读取一个值。 (如果您违反规则 9,并尝试读取多个值,它将返回它成功读取的值数,介于 0 和您请求的数字之间。 - 如果
scanf
返回 0 或EOF
,表示用户未键入有效值,只需打印错误消息并退出即可。 不要尝试编写要求用户重试的代码,因为用户的错误输入仍然位于输入流上,并且没有好的、简单的方法来摆脱它。(如果您真的想编写用户友好的代码,以便在出现错误时重新提示,scanf
不是适合这项工作的工具。 - 切勿在格式字符串后放置空格。 这包括换行符
n
。 (也就是说,使用"%d"
,而不是"%d "
或"%dn"
。 - 不要尝试使用
%[…]
说明符。 - 如果您违反了规则 13(可能是因为有人告诉您
%[…]
可能是读取包含空格或整行的字符串的一种方式),请不要在它后面加上s
。格式是%[…]
,而不是%[…]s
。
这些规则可能看起来很严格,但如果您遵循这些规则,您应该能够简单、轻松、可靠地将简单的输入输入到您的简单程序中,这就是这里的目标。scanf
在其他方面非常难以使用,经验表明,有大约 17 个不同的可怕令人沮丧的问题往往会出现,试图解决它们是完全不必要的分散你通过编写简单的 C 程序来学习 C 的目标。
当您读取带有%s
或%[…]
的字符串时,存在一个危险:无论您读取的数组或malloc
缓冲区有多大,用户都可能键入更多内容。 为了避免溢出,您可以使用%19s
等格式来显式告知scanf
允许读取多少个字符。(并记得减去 1,为终止' '
留出空间。 也就是说,您将使用%19s
来读取char str[20];
或char *p = malloc(20);
。
这些规则有些多。有关一组更简单的规则,请参阅此答案。 将规则 7、8、9、12 和 13 放在一起,实际上只有五个完整的格式字符串要与scanf
一起使用:"%d"
、"%s"
、"%f"
、"%lf"
或" %c"
。 (但是没有逗号,没有固定的字符串,除了" %c"
中的显式空格之外没有空格,没有别的。例外:如上所述,可以使用类似%19s
的东西来限制正在读取的字符串的长度。
如果你需要做一些更复杂的事情,而你不能在这些规则范围内做,那么是时候了:
- 充分了解
scanf
如何真正工作(和不起作用),以便您可以尝试做自己想做的事情,但不会陷入这 17 个问题之一,或者 - 学习如何使用比
scanf
更好、更强大的方法进行输入,也许通过使用fgets
读取整行然后解析它们。
您在"message[i][j]"之前缺少一个"&"。
for (int i = 0; i < M; i++) {
for (int j = 0; j < columns; j++) {
scanf("%d", &message[i][j]);
}
}