【发布时间】:2015-06-12 20:03:38
【问题描述】:
我正在创建一个带有提示的命令行应用程序。只要输入适合缓冲区,它就可以正常工作,但是当输入较大时,我会遇到一些奇怪的行为。下面是一个简化的最小示例,它具有相同的错误。
int main()
{
for (;;) {
const int size = 8;
char str[size];
printf("> ");
fgets(str, size, stdin);
toupper_str(str);
printf("Result: %s\n", str);
}
}
如果输入小于size,它可以正常工作。
> asdf
Result: ASDF
>
当输入较大时,处理范围内的输入部分,并在下一次循环迭代中,立即从fgets 返回给定输入的其余部分。这导致输入的那部分也被处理和一些奇怪的输出。
> asdfghjk
Result: ASDFGHJ
> Result: K
>
我可以通过将最后一个字符与换行符进行比较来查看输入是否大于或等于 size。 fgets 保留换行符,只要它适合。
fgets(str, size, stdin);
if (str[strlen(str) - 1] != '\n') {
fprintf(stderr, "Input too long\n");
}
当检测到这一点时,如何阻止它在下一次迭代中读取剩余的过长输入?
我在这里看到过类似的问题,但没有人提出相同的问题。
【问题讨论】:
-
fgets就是这样工作的。它确实不丢弃输入的其余部分,您的代码应该考虑到这一点。如果末尾没有newline,则该行较长(文件的最后一行除外)。虽然如果您错过了 1 的长度,下一个输入可能包含 onlynewline. -
@WeatherVane 问题是如何考虑它。这显然是
fgets的工作方式。 -
您还没有说是要丢弃其余的太长输入还是考虑它。前者:如果
fgets字符串不以newline结尾(当然在nul之前)继续阅读getchar直到newline或EOF。后者:如果输入不包含最终的newline,则使用分配的缓冲区和realloc。这里有一个不同的问题是一种使用该技术的方法。 stackoverflow.com/questions/28254245/… -
我认为您的问题最好表述为如何处理所有输入,而不是找到转储您无法处理的输入的方法:这会导致 GIGO。
-
@WeatherVane 正如您在提供的代码中看到的那样,缓冲区是在堆栈上分配的,因此不能是
realloced。
标签: c