我的代码还可以还是在某些情况下会失败?
我最近了解了键盘缓冲区以及从用户获得输入后清洁它的重要性。因此,我制作了此功能来处理它:
// Get input from user
void get_input(char *buff, int size)
{
fgets(buff, size, stdin);
int newlineIndex = strcspn(buff, "\n");
/* If no newline is found, fgets stopped at `size` and
didn't read all input. Keyboard buffer is dirty */
if (newlineIndex == strlen(buff))
{
// Clear keyboard buffer
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
else
{
// Remove newline from buff
buff[newlineIndex] = '\0';
}
}
在这里,buff
是您要存储输入的地方,size
is size> size> sizeof(buff)
。使用fgets读取用户的输入后,我然后查找带有strcspn()
的fgets留下的\ n
字符。如果newlineIndex == strlen(buff)
,则找不到\ n
newline,这意味着用户键入的字符比size
> ,因此我继续使用以下方式清除键盘缓冲区:
int c;
while ((c = getchar()) != '\n' && c != EOF);
否则,键盘缓冲区没有脏,因此我从用户输入中删除\ n
,以便更轻松地作为字符串作为字符串。
我的代码还可以还是我错过了什么?有更有效的方法吗?
I recently learned about the keyboard buffer and how important it is to clean it after getting input from the user. So I made this function to handle that:
// Get input from user
void get_input(char *buff, int size)
{
fgets(buff, size, stdin);
int newlineIndex = strcspn(buff, "\n");
/* If no newline is found, fgets stopped at `size` and
didn't read all input. Keyboard buffer is dirty */
if (newlineIndex == strlen(buff))
{
// Clear keyboard buffer
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
else
{
// Remove newline from buff
buff[newlineIndex] = '\0';
}
}
Here, buff
is where you want to store the input and size
is sizeof(buff)
. After using fgets to read input from the user, I then look for the \n
character left by fgets with strcspn()
. If newlineIndex == strlen(buff)
, the \n
newline wasn't found, which means that the user has typed more characters than size
, so I proceed to clear the keyboard buffer with:
int c;
while ((c = getchar()) != '\n' && c != EOF);
else, the keyboard buffer didn't get dirty, so I remove \n
from the user input to handle with it more easily as a string later.
Is my code okay or am I missing something? Is there a more efficient way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
它比必要的更复杂和低效,特别是考虑到在C 中工作。您无需搜索 newline 。它要么在字符串的末端,要么不是 - 您需要查看的唯一位置是在字符串的末端。
fgets()
可以返回null
如果例如在读取任何字符之前遇到EOF - 例如,如果使用文件中的输入重定向,则可以很容易地发生。因此,您应该检查一下。您的代码 Will 以不可预测的方式失败,例如buff [0]!='\ 0'
在输入和fgets()
返回 fgets()代码> null 。通常,返回某物 - 即使您经常丢弃返回值,也很有用。您可以在错误上返回错误指示或返回有效(但空)字符串,或者可能返回输入字符串的长度以保存呼叫者的另一个
strlen()
traversal。我个人建议将指针返回调用者的缓冲区和初始化buff [0] ='\ 0'
以确保始终返回有效的字符串。这样您就可以做以下操作:因此,我建议:
一个可能有用的修改,因为您遇到确定输入长度的麻烦是通过参考参数将其返回给呼叫者:
例如:
或如果要丢弃长度:
It is somewhat more complex and inefficient than necessary, especially given the way strings work in C. You do not need to search for the newline. It is either at the end of the string, or it is not - the only place you need to look is at the end of the string.
fgets()
can returnNULL
if for example EOF is encountered before any characters are read - this can easily happen if using input redirection from a file for example. So you should check for that. Your code will fail in unpredictable ways as-is ifbuff[0] != '\0'
on entry andfgets()
returnsNULL
.It is normally useful to return something - even if often you discard the return value. You could return an error indication or return a valid (but empty) string on error, or possibly return the length of the input string to save the caller yet another
strlen()
traversal. Personally I'd suggest returning a pointer to the caller's buffer and initialisingbuff[0] = '\0'
to ensure a valid string is always returned. That way you can do things such as:So I would suggest:
One possibly useful modification, since you go to the trouble of determining the length of the input would be to return that to the caller via a reference parameter:
Then for example:
Or if you want to discard the length:
是的。
缺少从
fgets()
中检查返回值。fgets()
返回null
指示刚刚发生的即时文件终止或输入错误,因此get_input()
也应该发生。在这种情况下,对于OP的代码,buff []
处于不确定状态,因为strcspn(buff,“ \ n”);
风险不确定的行为(ub)。代码无法返回成功或错误的任何指示(文件终止,输入错误或过度长行。)。
Extreme 缓冲区大小可能超过
int
范围。size_t size
不会超过数组或分配大小。strcspn(buff,“ \ n”)
返回size_t
,而不是int
。如果值大于int_max
。strcspn(buff,“ \ n”)
无法检测'\ n'
,如果读取了先前的 null字符。 /p>标准C缺乏将A line 读为 string 的强大方法。
fgets()
主要将我们带到那里。Yes.
Missing check of return value from
fgets()
.fgets()
returnsNULL
to indicate an immediate end-of-file or input error just occurred, so shouldget_input()
. In such cases for OP's code,buff[]
is in an indeterminate state as sostrcspn(buff, "\n");
risks undefined behavior (UB).Code fails to return any indication of success or error (end-of-file, input error that occurred here or excessive long line.).
Extreme buffer sizes may exceed the
int
range.size_t size
will not exceed an array or allocation size.strcspn(buff, "\n")
returns asize_t
, notint
. Saving in anint
will cause issues if the value was more thanINT_MAX
.strcspn(buff, "\n")
fails to detect a'\n'
if a prior null character was read.Standard C lacks a robust way to read a line into a string.
fgets()
gets us mostly there.是的,您的代码还可以,并且不应该失败。但是,请始终检查fgets失败:(手册)
Yes, your code is ok, and it should not fail. However always check for fgets fail: (from manual)