此代码向用户询问数据,然后询问数字:
$ cat read.c
#include<stdio.h>
#include<stdlib.h>
#define MAX 10
int main() {
char* c = (char*) malloc(MAX * sizeof(char));
int num;
printf("Enter data (max: %d chars):\n", MAX);
fgets(c, MAX, stdin);
// how do I discard all that is there on STDIN here?
printf("Enter num:\n");
scanf("%d", &num);
printf("data: %s", c);
printf("num: %d\n", num);
}
$
问题在于,除了说明最大字符数的指令外,没有什么可以阻止用户输入更多字符,随后将其作为垃圾读入num
:
$ ./read
Enter data (max 10 chars):
lazer
Enter num:
5
data: lazer
num: 5
$ ./read
Enter data (max 10 chars):
lazerprofile
Enter num:
data: lazerprofnum: 134514043
$
在STDIN
来电之后,有没有办法放弃fgets
上的所有内容?
答案 0 :(得分:5)
据我所知,唯一的便携式解决方案是自己耗尽缓冲区:
while (getchar() != EOF);
请注意,fflush(stdin);
为not the answer。
编辑:如果您只想在下一个换行符之前丢弃字符,则可以执行以下操作:
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
答案 1 :(得分:5)
scanf()函数对于用户输入来说太糟糕了,除非你以某种方式知道你的输入数据是正确的(不要那么信任!),它对于文件输入来说并不是那么好。另外,你应该总是检查返回值fgets()因为NULL表示EOF或其他一些异常。请记住,除非首先达到最大值,否则在fgets()数据末尾会得到用户的换行符。我可以这样做,作为第一次通过:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10
void eat_extra(void) {
int ch;
// Eat characters until we get the newline
while ((ch = getchar()) != '\n') {
if (ch < 0)
exit(EXIT_FAILURE); // EOF!
}
}
int main() {
char c[MAX+1]; // The +1 is for the null terminator
char n[16]; // Arbitrary maximum number length is 15 plus null terminator
int num;
printf("Enter data (max: %d chars):\n", MAX);
if (fgets(c, MAX, stdin)) { // Only proceed if we actually got input
// Did we get the newline?
if (NULL == strchr(c, '\n'))
eat_extra(); // You could just exit with "Too much data!" here too
printf("Enter num:\n");
if (fgets(n, sizeof(n) - 1, stdin)) {
num = atoi(n); // You could also use sscanf() here
printf("data: %s", c);
printf("num: %d\n", num);
}
}
return 0;
}
答案 2 :(得分:1)
fgets
会发生什么?
NULL
NULL
时会返回EOF
如何区分1
和2
?
与feof
如何区分3.1.
,3.2.
和3.3.
通过确定写入终止空字节和换行符的位置:
如果输出缓冲区有'\n'
则没有更多数据(缓冲区可能已被完全填充)
如果没有'\n'
AND ,'\0'
位于缓冲区的最后位置,那么您知道有更多数据在等待;如果'\0'
位于缓冲区的最后一个位置之前,则您在未以换行符结束的流中点击EOF
。
/* fgets fun */
/*
char buf[SOMEVALUE_LARGERTHAN_1];
size_t buflen;
*/
if (fgets(buf, sizeof buf, stdin)) {
buflen = strlen(buf);
if (buflen) {
if (buf[buflen - 1] == '\n') {
puts("no more data (3.1. or 3.2.)"); /* normal situation */
} else {
if (buflen + 1 == sizeof buf) {
puts("more data waiting (3.3.)"); /* long input line */
} else {
puts("EOF reached before line break (3.1.)"); /* shouldn't happen */
}
}
} else {
puts("EOF reached before line break (3.1.)"); /* shouldn't happen */
}
} else {
if (feof(stdin)) {
puts("EOF reached (2.)"); /* normal situation */
} else {
puts("error in input (1.)");
}
}
通常的不完整测试是buf[buflen - 1] == '\n'
并且检查fgets
返回值...
while (fgets(buf, sizeof buf, stdin)) {
if (buf[strlen(buf) - 1] != '\n') /* deal with extra input */;
}
答案 3 :(得分:-1)
我会读取数据然后检查它是否有用户错误:
bool var = true;
while var {
printf("Enter data (max: %d chars):\n", MAX);
fgets(c, MAX, stdin);
// how do I discard all that is there on STDIN here?
if(strlen(c) <= 10)
var = false;
else
printf("Too long, try again! ");
}
另一方面,如果您不想这样做,只需读取num两次并丢弃第一个。