哪个是从C中获取用户输入的最佳方式?

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()如果行大于缓冲区,则可能无法读取整行,这在"严肃"程序中肯定是您应该考虑的.

  • @Twonky:就 C 而言,“fflush(stdin)”是未定义的(不过,它*确实*在某些平台上执行您建议的操作)。但是,是的,它在这方面可以变得更加强大。 (2认同)

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代码的最佳通用解决方案,因为它对要读取的行的长度没有任何静态限制.


Joh*_*ode 5

使用有几个问题scanf:

  • 使用普通%s转换说明符读取文本与使用时具有相同的风险gets(); 如果用户键入的字符串长度超过目标缓冲区的大小,则会出现缓冲区溢出;

  • 如果使用%d%f读取数字输入,某些不良模式不能被完全捕获和拒绝 - 如果你正在读取一个整数%d并且用户键入" 12r4",scanf将转换并分配,12r4在输入流中留下以填充下一个读;

  • 一些转换说明符跳过前导空格,其他转换说明符不跳过,并且未考虑到这一点会导致某些输入被完全跳过的问题;

基本上,使用防弹读取需要花费很多额外的精力scanf.

一个好的选择是使用读出所有的输入作为文本fgets(),然后标记化,并使用转换输入sscanf或组合strtok,strtol,strtod等.