在C语言中,获取用户输入的最佳方式是什么?

24 浏览
0 Comments

在C语言中,获取用户输入的最佳方式是什么?

很多人说,"更严肃的程序"中不应该使用scanf,同样也不应该使用getline。我开始迷茫了:如果每个我遇到的输入函数都被人说不应该使用,那我应该使用什么呢?是否有一种更"标准"的方法来获取输入,而我不知道呢?

0
0 Comments

在C语言中,从用户获取输入的最佳方法是什么?

对于简单的输入,可以设置输入长度的固定限制,我建议使用fgets()从终端读取数据。这是因为fgets()允许您指定缓冲区大小(与此相反,gets()因为这个原因应该基本上永远不要用于从人类读取输入):

char line[256];
if(fgets(line, sizeof line, stdin) != NULL)
{
  /* 现在检查并进一步解析line中的字符串。 */
}

请记住,它会保留换行符字符,这可能会让人感到惊讶。

更新:正如评论中指出的,如果您可以负责跟踪内存,那么有一个更好的选择:getline()。这可能是POSIX代码的最佳通用解决方案,因为它对要读取的行的长度没有任何静态限制。

“可以设置输入长度的简单输入”听起来不像是“严肃”的程序。POSIX的getline函数更加灵活。

如果我能为我的问题找到两个赢家,那么你会是第二个,因为你详细解释了getline()的细节以及你解释的gets()的行为。但是FatalError的答案对于如何使用这种技术有更多的细节。

0
0 Comments

在C语言中,从用户获取输入的最佳方法是什么?

使用scanf存在以下几个问题:

  • 使用纯粹的%s转换说明符读取文本时存在与使用gets()相同的风险;如果用户输入的字符串长度超过目标缓冲区的大小,就会发生缓冲区溢出;
  • 如果使用%d%f来读取数值输入,无法完全捕获和拒绝某些错误模式——如果使用%d读取整数,用户输入"12r4",scanf将转换并赋值为12,而将r4留在输入流中,干扰下一次读取;
  • 某些转换说明符跳过前导空格,而其他则不跳过,如果不考虑这一点,可能导致某些输入完全被跳过;

基本上,使用scanf需要付出很多额外的努力来确保读取的安全性。

一个好的替代方法是使用fgets()将所有输入作为文本读取,然后使用sscanfstrtokstrtolstrtod等组合对输入进行标记化和转换。

谢谢,现在我知道人们为什么说scanf可能不好的原因了。

0
0 Comments

在C语言中,从用户获取输入有多种方法,其中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可以安全使用 */
    }
}

上述代码中需要注意的是,fgets()在EOF或错误时返回NULL,这就是为什么我将其包裹在if中的原因。sscanf()返回成功转换的字段数。

请记住,如果行的长度大于缓冲区大小,fgets()可能无法读取整行,这在一个“严肃”的程序中是您应该考虑的。

那么,在fgets()之后添加fflush(stdin)以确保超过255个字符的输入缓冲区不会影响后续对fgets()的调用呢?

fflush(stdin)在C语言中是未定义的(尽管在某些平台上确实会执行您的建议)。但是是的,这样可以使其更加健壮。

0