我尝试使用以下代码从用户读取字符串
char array[4];
fgets(array , 5, stdin);
我之所以使用fgets命令,是因为scanf会读取整个字符串,而不管数组的大小,如果它不适合数组,它会自动更改数组的大小,以使字符串适合数组。我希望总是读取最大长度为4的字符串,这就是我使用fgets的原因。因为fgets将始终获取您要求它获取的字符,而不管来自用户的字符串有多长。
我的问题是,正如你所看到的,我声明了大小为4的数组,但是在fgets里面我必须写5,因为它比数字少读一个字符。为什么它会这样做?为什么它比数字少读一个字符?我做错了什么吗?
2条答案
按热度按时间6mzjoqzu1#
C语言中的字符串是包括终止零字符
'\0'
的字符序列。所以这个数组
可以包含一个字符串,除了终止零字符
'\0'
之外,最多还有三个字符。如果要输入三个以上的字符,则至少需要声明如下数组:
然后你就可以写
在这种情况下,与按下的Enter键相对应的新行字符
'\n'
将不会存储在数组中,而将留在输入缓冲区中。因此,如果您在此之后再调用一个
fgets
,则将读取仅包含新行字符'\n'
(如果不计算终止零字符'\0'
)的字符串。因此,最好像下面这样声明数组
若要从数组中移除换行字符,您可以写入
至于这通电话
则如果您尝试输入四个字符,它将调用未定义的行为,因为终止零字符
'\0'
将由该函数写入数组外部的内存中。至于函数
scanf
,则可以按以下方式使用它或
注意格式字符串中的前导空格。它允许跳过白色字符,例如新的行字符
'\n'
,它可以在前面调用scanf
后存储在缓冲区中。lf5gs5x22#
编写防呆的输入例程是 * 困难的。* 许多传统的 *nix程序在遇到不寻常或极端的输入(例如,非常长的行)时都会失败。
不幸的是,初学者的问题经常处理手动输入。我看到以下策略,取决于用例(eidogg.,确切的赋值)。
1.忽略所有的输入问题,不要处理任何错误。假设没有一个单词超过x字节,没有一行超过y字节,没有一个文件超过z字节。即使你相当确定你的手动输入不会违反你的任意假设,这也是不推荐的:约束被遗忘,例程被重新使用,不可避免地,你会有一个程序以这样或那样的方式出现故障。
1.做一些明智的错误检查。这是传统的 nix程序在黑客攻击成为问题之前所做的。处理最常见的错误(找不到文件)和最有可能导致问题的约束(行长度),并在超过这些时失败。你的程序在某些情况下仍然可能失败,而且它很容易受到攻击。
1.让你的程序防呆。这是相对困难的,即使是对于简单的程序,并且倾向于通过错误检查和处理来模糊实际的控制流和目的。另一方面,你可以确信当你的例程是plugged into the software for the next bigger rocket时,它会触发一个Assert,否则会优雅地失败。
在您的情况下,您必须:
1.确保例程读取的字符数不超过缓冲区中的可用空间,Vlad已经为您提供了相关信息。
1.想想你是如何发现过长的单词或行的。
1. 妥善处理 * 检测到的情况。
顺便说一句,
scanf("%5s", buf)
也将读取最多5个字符,并且在这些字符之后存储一个空字符,因此缓冲区数组必须是6个字符大。