我有一个用户输入两个输入的程序。由于我无法控制用户输入的内容,因此用户可以超过阵列的固定大小。由于 String arr_name = "array 1";
....replace(String.format ("{\"%s\"", arr_name), "");
追加在空字符之前保留了一个换行符,如果在用户超出预期大小时换行符不适合,则空字符会截断输入。用户命中输入时的换行符是否仍存在于输入流中?如果是这样,这是fgets()
由于第一次输入换行而第二次跳过的原因吗?
fgets()
示例输入
#include <stdio.h>
int main(){
char str[5];
fgets(str,5,stdin);
printf("Output:%s",str);
fgets(str,5,stdin);
printf("Output:%s",str);
return 0;
}
输出
ABCDE\n
在阅读了这个SO回答fgets() isn't prompting user a second time
之后,问题似乎并没有通过Output:ABCDOutput:E
刷新输入流,但是我听到了相互矛盾的信息,因为这会导致未定义的行为。我的最后一个问题是,如果保留换行符导致问题,清除输入流的适当方法是什么?
答案 0 :(得分:4)
用户可以超过数组的固定大小。由于
之前的末尾附加换行符fgets()
在空字符
不,它没有。它将从输入读取的字符写入提供的缓冲区,直到并包括第一个换行符,或直到指定的缓冲区大小耗尽(字符串终结符少于一个字节),或者直到发生错误或者到达流的末尾,以先到者为准。换行符不是由fgets()
发明的;它来自输入。
,如果在用户超出预期大小时换行符不适合,则空字符会截断输入。用户命中输入时的换行符是否仍存在于输入流中?
用户输入但未复制到缓冲区中的所有字符仍等待在流中读取。如果用户输入了换行符,那将包括换行符。
如果是这样,这是因为第一次输入的换行符导致fgets()第二次跳过的原因吗?
fgets()
没有跳过,但它确实在前一个调用停止从输入到缓冲区传输字符的位置。没有字符丢失。这意味着如果第一个调用没有返回整个内容,第二个调用将返回第一个输入行的一部分。您需要以某种方式考虑输入不符合您的行长预期的可能性。
问题似乎不是通过
刷新输入流fflush(stdin)
,
不,不是。刷新用于将缓冲的输出发送到底层输出设备。刷新输入流会产生未定义的行为。原则上,这可能表现为缓冲区转储,并且给定的实现甚至可能指定此类行为, 但您不希望 因为可能有比缓冲更多的数据你想摆脱它。
但我听到有相互矛盾的信息说这会导致未定义的行为。我的最后一个问题是,如果保留换行符导致问题,清除输入流的适当方法是什么?
您从输入中读取,直到您阅读换行符。有很多I / O函数可供选择来完成此任务。 fgets()
本身可能很方便,因为你已经在使用它了:
char str[5];
if (fgets(str, 5, stdin)) {
printf("Output:%s", str);
// read and consume the tail of the line, if any (overwrites str)
while (!strchr(str, '\n') && fgets(str, 5, stdin)) { /* empty */ }
}
答案 1 :(得分:4)
fgets()
读到
1)新线
2)缓冲区满了
3)文件结束
4)输入错误(罕见)
此代码读取并处理#3&amp; #4
#define N 5
char buf[N];
if (fgets(buf, sizeof buf, stdin) == NULL) {
// Handle EOF or Error
return EOF;
}
区分是否存在'\n'
......(来自#1的#2)
// look for a lack of \n
if (strchr(buf, '\n') == NULL) {
如果是,请阅读直到找到它或EOF
。
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF);
}
-
请勿使用以下代码。可以通过读取 null字符作为第一个字符来利用它。
size_t len = strlen(buf);
if (buf[len - 1] != '\n') { // bad way to detect \n
可以使用
if (len > 0 && buf[len - 1] != '\n') { // Good
答案 2 :(得分:4)
因为我无法控制用户输入的内容......
不,你不能。
用户可以超过数组的固定大小。
右。这一直是一个问题。但是,一般来说,你会想要安排一些事情,这样很少发生。
例如,如果你真的想要将用户限制为(比方说)4个字符长的输入字符串,让他输入他想要的任何内容,然后查看他输入的内容,以及是否超过了你的限制,打印一个很好的错误消息或东西。但是,如果您预计输入4个字符加上换行符,我建议不要拨打fgets(str, 5, stdin)
,因为当用户输入的内容过多时(而不是如果)输入太多,这就太难以恢复了。 / p>
如果在用户超出预期大小时换行符不适合,则空字符会截断输入。用户命中输入时的换行符是否仍存在于输入流中?
绝对是的。
如果是这样,这是因为第一次输入的换行符导致fgets()第二次跳过的原因吗?
非常好。
我建议分配一个更大的缓冲区,然后继续这样的事情:
char inpbuf[512);
if(fgets(inpbuf, sizeof(inpbuf), stdin) == NULL) {
fprintf(stderr, "end of file\n");
return;
}
char *p = strrchr(inpbuf, '\n');
if(p == NULL) {
fprintf(stderr, "looks like you typed *way* too much\n");
return;
}
*p = '\0'; /* erase the \n */
if(strlen(inpbuf) > 4) {
fprintf(stderr, "you typed too much (max 4)\n");
return;
}
strcpy(str, inpbuf);
printf("Output:%s", str);
编写此代码的一个小问题是:如果用户在点击Return之前点击文件结束键(Unix / Linux上的control-D),你就会错误地得到&#34;看起来就像你输入方式太多&#34;消息。
答案 3 :(得分:3)
如果fgets
读取的字符串不以换行符结尾,则表示它仍在缓冲区中。在这种情况下,请在循环中调用getchar
,直到获得换行符。
fgets(str,5,stdin);
printf("Output:%s",str);
if (strchr(str, '\n') == NULL) {
int c;
while ((c = getchar()) != EOF && c != '\n');
}
fgets(str,5,stdin);
printf("Output:%s",str);