【问题标题】:Read no more than size of string with scanf()使用 scanf() 读取不超过大小的字符串
【发布时间】:2012-08-31 15:47:02
【问题描述】:

编辑:对于我的班级,我必须使用scanf。所以推荐其他输入方式不是我正在寻找的解决方案(如果有涉及scanf的解决方案)。


如果我正在阅读小型项目(例如游戏)的用户输入。假设我问would you like to play? 这将接受yesno 的答案。所以我写了一些像这样的简单代码:

#include <stdio.h>

int main(void)
{
     char string[3]; //The max number of letters for "yes".

     printf("Would you like to play?");
     scanf("%s", string);
}

所以这段代码应该只要求他们输入yesno。我将char array 的长度设置为3 的大小。这样它就足够容纳yesno。但是,如果有人输入无效输入,例如yesss,我知道如何在之后比较字符串以处理此类事件,但这不会在技术上/可能覆盖我已声明的其他局部变量,因为它会延伸到长度之外我的阵列?如果是这样,有没有办法处理这个限制3个输入字符或什么?如果不是,为什么/如何知道只输入 3 的大小?

【问题讨论】:

  • 逐个字符进行可能更安全。我不确定 C 是否有任何东西可以为你做这件事。
  • 你能解释一下怎么做吗?我会在“scanf”中做一堆“%c”的事情,然后我将如何将它们分配给数组的一个字符? [IE。我需要 &string[0] 什么的。另外,如果他们输入“否”,那么我只会使用 3 个“%c”中的 2 个。
  • 自己处理任何长度需要一个数组,该数组可以在运行时更改大小,并在输入字符出现时插入字符,同时确保不溢出数组。幸运的是,scanf 似乎内置了该功能。

标签: c string scanf format-specifiers


【解决方案1】:

您的数组需要能够容纳四个 chars,因为它还必须包含 0 终止符。固定后,在格式中指定最大长度,

scanf("%3s", string);

确保scanf 读取的字符不超过 3 个。

【讨论】:

  • 顺便说一句,由于宽度说明符仅指示要读取的最大个字符数,如果您需要读取精确个数,请使用上面的方法,然后检查消耗的字符数(通过%n)。
  • 我只是想知道这是非常棒的事情,那么为什么人们一直说 scanf 是不安全的,显然他们可以这样做来限制输入并阻止缓冲区溢出攻击。 ??
  • “确保 scanf 读取不超过 3 个字符。” --> 不完全是。 "%3s" 将首先读取无限数量的前导空白字符。然后它将读取并保存最多 3 个非空白字符。最后附加一个 null 字符.
  • @SurajJain 人们普遍反对 scanf 不是因为它不能安全使用,而是因为它很难使用。当人们第一次学习 C 时,学习解析输入字符串会比花时间学习 scanf 格式语言的弱点更好。 scanf 在生产代码中很少使用;在绝大多数地方它可能是合适的,C 无论如何都是错误的语言。
【解决方案2】:

http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

使用“宽度”修饰符;

%[*][width][modifiers]type

【讨论】:

    【解决方案3】:

    最安全的方法是使用

    fgets(string, 4, stdin);
    

    在这里您最多可以存储 3 个字符,包括为 NULL ('\0') 字符保留的一个空格。

    【讨论】:

    • 没错!最好的(也是最具创新性的)方式,待定!谢谢
    • 通常读取的“最多 3 个字符”中的最后一个是 '\n'
    • fgets() 读取任何字符(包括空格),直到 EOF 或 \n。所以它不是 scanf() 的替代品,它负责读取字符串的格式。
    【解决方案4】:

    您应该使用scanf()width 修饰符并将其设置为比字符串的大小小一,以便确保存在空间NULL终结者。

    所以,如果你想存储“是”,你首先需要一个比你拥有的更大的数组;一个大小为 4、3 个字符加 1 个用于空终止符。此外,您应该指示 scanf() 读取不超过 size - 1 个字符,其中 size 是数组的长度,因此在这种情况下为 3,如下所示:

    #include <stdio.h>
    
    int main(void)
    {
         char string[4];
         scanf("%3s", string);
    }
    

    【讨论】:

    • 这将扫描一个数字3...而不是使用"%3s"
    • 我什至不知道我当时在想什么...谢谢@JonathanLidbeck,已更正!
    猜你喜欢
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多