我试图从stdin
读取一行但我不知道在输入大小至少等于限制时正确处理这些情况。示例代码:
void myfun() {
char buf[5];
char somethingElse;
printf("\nInsert string (max 4 characters): ");
fgets (buf, 5, stdin);
...
printf("\nInsert char: ");
somethingElse = getchar();
}
现在,用户可以做三件事:
getchar()
正确等待用户输入; getchar()
会读取它; getchar()
读取它,至少留下一个换行。案例 2 和 3 需要使用stdin
之类的内容清空while(getchar() != '\n')
,而案例 1 不会&# 39; t需要任何额外的行动。正如我从阅读类似问题和c-faq的答案中所理解的那样,没有标准/可移植的方式来了解实际情况是否是 1 中描述的情况。
我说得好吗?或者实际上 是一种可移植的方式吗?或者可能采用完全不同的方法?
答案 0 :(得分:4)
如果有空间,fgets
函数会将换行符存储在缓冲区中。因此,如果字符串中的最后一个字符不是换行符,则表示您需要刷新缓冲区。
fgets (buf, 5, stdin);
if (strrchr(buf, '\n') == NULL) {
// flush buffer
int c;
while ((c = getchar()) != '\n') && (c != EOF));
}
答案 1 :(得分:2)
如果假设从未读过 null字符 '\0'
,那么@dbush答案就可以了。
如果读取空字符,则strrchr(buf, '\n')
找不到可能已被阅读的'\n'
。
代码可以预先设置缓冲区,以查看最后是否读取了'\n'
。
buf[sizeof buf - 2] = '\n';
if (fgets (buf, sizeof buf, stdin)) {
if (strrchr(buf, '\n') == NULL) {
// incomplete line read. (the usual detection)
} else if (buf[sizeof buf - 2] != '\n') {
// incomplete line read with prior null character (see below note).
}
}
然而,C标准并未指定过去buf[]
中读取的数据未更改,使用某种模式预先填充缓冲区不足以检测 null字符 { {1}}已被阅读。
是一种可移植的方式吗?
最便携的方法是使用'\0'
之类的重复来电,而不是fgetc()
。
可能是一种完全不同的方法?
我建议使用fgets()
或普通但不是C标准fgetc()
另一种选择:使用getline()
:非常繁琐,但可以采用便携式方式。它会跟踪scanf("%4[^\n]%n", buf, &n)
之前读取的字符数,即使某些空字符也是如此。
'\n'