use*_*057 40 c user-input
很多人说不scanf应该用在"更严肃的程序"中,与之相同getline.
我开始迷失:如果我遇到的每个输入功能都说我不应该使用它们中的任何一个,那么我应该使用什么?是否有更"标准"的方式来获取我不知道的输入?
Fat*_*ror 36
通常,fgets()被认为是一个不错的选择.它将整行读入缓冲区,从那里你可以做你需要的.如果你想要这样的行为scanf(),你可以将你读过的字符串传递给sscanf().
这样做的主要优点是,如果字符串无法转换,它很容易恢复,而你需要消耗scanf()输入stdin.另外,你也不会在混合使用面向行输入的陷阱拉闸scanf(),这会导致头痛,当事情好像\n被甩上stdin普遍领先的新编码器认为输入的呼叫已被完全忽略.
这样的事可能是你喜欢的:
char line[256];
int i;
if (fgets(line, sizeof(line), stdin)) {
if (1 == sscanf(line, "%d", &i)) {
/* i can be safely used */
}
}
Run Code Online (Sandbox Code Playgroud)
在上面你应该注意EOF或错误的fgets()回报NULL,这就是为什么我把它包裹在一个if.该sscanf()调用返回已成功转换的字段数.
请记住,fgets()如果行大于缓冲区,则可能无法读取整行,这在"严肃"程序中肯定是您应该考虑的.
unw*_*ind 11
对于可以在输入长度上设置固定限制的简单输入,我建议从终端读取数据fgets().
这是因为fgets()让你指定缓冲区大小(相反gets(),由于这个原因,它几乎从不用于读取人类的输入):
char line[256];
if(fgets(line, sizeof line, stdin) != NULL)
{
/* Now inspect and further parse the string in line. */
}
Run Code Online (Sandbox Code Playgroud)
请记住,它将保留例如换行符,这可能会令人惊讶.
更新:正如评论中指出的那样,如果您对跟踪记忆负责,那么还有更好的选择:getline().这可能是POSIX代码的最佳通用解决方案,因为它对要读取的行的长度没有任何静态限制.
使用有几个问题scanf:
使用普通%s转换说明符读取文本与使用时具有相同的风险gets(); 如果用户键入的字符串长度超过目标缓冲区的大小,则会出现缓冲区溢出;
如果使用%d或%f读取数字输入,某些不良模式不能被完全捕获和拒绝 - 如果你正在读取一个整数%d并且用户键入" 12r4",scanf将转换并分配,12而r4在输入流中留下以填充下一个读;
一些转换说明符跳过前导空格,其他转换说明符不跳过,并且未考虑到这一点会导致某些输入被完全跳过的问题;
基本上,使用防弹读取需要花费很多额外的精力scanf.
一个好的选择是使用读出所有的输入作为文本fgets(),然后标记化,并使用转换输入sscanf或组合strtok,strtol,strtod等.
| 归档时间: |
|
| 查看次数: |
49854 次 |
| 最近记录: |