如何防止用户输入超过最大限制的数据?
这段代码要求用户提供数据,然后是一个数字:
$ 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
$
有没有办法在 fgets
调用后丢弃 STDIN
上的所有内容?
This code asks the user for data and subsequently a number:
$ 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);
}
$
The problem is that apart from the instruction that states the maximum number of chars, there is nothing that stops the user from entering more, which is subsequently read into num
as junk:
$ ./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
$
Is there a way to discard all that is there on STDIN
after the fgets
call?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
fgets
“可能发生什么”?EOF
时,它返回 NULL如何区分
1
和2
?与
feof
如何区分
3.1.
、3.2.
和3.3.
通过确定终止空字节和换行符的写入位置:
如果输出缓冲区有
'\n'
,则没有更多数据(缓冲区可能已完全填满)如果没有
'\n'
AND'\0'
位于缓冲区的最后位置,那么您就知道还有更多数据等待;如果'\0'
位于缓冲区的最后一个位置之前,则表示您在不以换行符结尾的流中命中了EOF
。像这样
通常的、不完整的测试是 buf[buflen - 1] == '\n' 并检查 fgets 返回值...
What "can happen" to
fgets
?NULL
when there is an error in inputNULL
when it finds anEOF
before any "real" charactersHow can you distinguish between
1
and2
?with
feof
How can you distinguish between
3.1.
,3.2.
and3.3.
By determining where the terminating null byte and line break were written:
If the output buffer has a
'\n'
then there is no more data (the buffer may have been completely filled)If there is no
'\n'
AND the'\0'
is at the last position of the buffer, then you know there is more data waiting; if the'\0'
is before the last position of the buffer, you've hitEOF
in a stream that doesn't end with a line break.like this
The usual, incomplete tests, are
buf[buflen - 1] == '\n'
and checkingfgets
return value ...我会读取数据,然后检查是否存在用户错误:
另一方面,如果您不想这样做,只需读取 num 两次并丢弃第一个。
I would read the data and then check it for user error:
On the other hand, if you don't want to do this, just read num twice and discard the first one.
scanf() 函数对于用户输入来说很糟糕,对于文件输入来说也不是那么好,除非您以某种方式知道输入数据是正确的(不要那么信任!)另外,您应该始终检查 fgets() 的返回值因为 NULL 表示 EOF 或其他一些异常。请记住,除非首先达到最大值,否则您将在 fgets() 数据末尾获取用户的换行符。我可能会这样做作为第一遍:
The scanf() function is terrible for user input, and it's not that great for file input unless you somehow know your input data is correct (don't be that trusting!) Plus, you should always check the return value for fgets() since NULL indicates EOF or some other exception. Keep in mind that you get the user's newline character at the end of your fgets() data unless the maximum is reached first. I might do it this way as a first pass:
据我所知,唯一的便携式解决方案是自己耗尽缓冲区:
请注意
fflush (标准输入);
是 不是答案。编辑:如果您只想丢弃字符直到下一个换行符,您可以执行以下操作:
To my knowledge, the only portable solution is to exhaust the buffer yourself:
Note that
fflush(stdin);
is not the answer.EDIT: If you only want to discard characters until the next newline, you can do: