【问题标题】:confused about getchar and scanf对 getchar 和 scanf 感到困惑
【发布时间】:2014-01-07 11:36:25
【问题描述】:

我真的很困惑getchar()scanf() 的用法。这两者有什么区别?

我知道scanf() [和家人] 从用户 [或文件] 获取一个字符一个字符并将其保存到一个变量中,但它是立即执行此操作还是在按下某些内容 (Enter) 之后执行此操作?

我不是很理解这段代码,我看到很多代码都使用getchar(),它们都让你在屏幕上输入你想要的任何东西,但没有响应,但是当你按下enter时,它就会退出。

int j, ch;

printf("please enter a number : \n");

while (scanf("%i", &j) != 1) {
    while((ch = getchar()) != '\n') ;
    printf("enter an integer: ");
}

在这段代码中,我不能使用scanf() 逐个字符地获取并测试它吗?还有,这条线是什么意思?

scanf("%i", &j) != 1

因为当我按下 1 时,按下 2 时并没有什么不同?这件作品有什么作用?

这条线什么时候会发生?

printf("enter an integer: ");

因为它永远不会发生。

【问题讨论】:

    标签: c printf getchar


    【解决方案1】:

    嗯,scanf 是一个通用的实用函数,它可以根据格式字符串读取多种类型的数据,而getchar() 只能读取一个字符。

    基本上,

    char someCharacter = getchar();
    

    等价于

    char someCharacter;
    scanf("%c", &someCharacter);
    

    我不是 100% 肯定,但如果您只需要读取一个字符,getchar() 可能比scanf() '便宜',因为处理格式字符串的开销不存在(这可能算作某些事情如果您阅读 许多 个字符,例如在一个巨大的 for 循环中)。

    第二个问题。

    这段代码:

    scanf("%i", &j) != 1
    

    表示您希望scanf 读取变量“j”中的整数。如果读取成功,即流中的下一个输入实际上是一个整数,scanf 将返回 1,因为它正确读取并分配了 1 个整数。

    有关scanf 返回值的更多详细信息,请参阅this SO question 的最早回复。

    【讨论】:

    • "如果读取成功,即流中的下一个输入实际上是一个整数,scanf会返回1"这里有个问题,我看了scanf()返回的是它读取的字符数,而不是如果它读取整数返回1,我试过了,它真的发生了,当输入一个整数时,它返回1,当我输入一个字符“字符串”时返回0。那么它如何返回它读取的字符数?我很困惑
    • @Salahuddin 它返回“成功匹配和分配的输入项的数量”,无论它们是什么。假设这个调用接收到正确的输入:scanf("%i%c%s", &someInt, &someChar, &someString),它将返回 3。
    • @nestedloop getchar() 返回 int 而不是 char。当遇到 EOF 时,我们应该怎么知道。
    • @hetepeperfan 是的,getchar() 返回一个转换为 int 的无符号字符,除非出现 EOF。但是,我说的是 scanf 返回的内容,而不是 getchar。
    • @nestedloop 我认为答案中的代码示例应该促进良好的风格并防止错误。在我看来,char c = getchar(); 并不提倡良好的风格。
    【解决方案2】:

    据我所知, getchar 函数将一次读取您输入的一个字符。 scanf 将读取所有类型的数据,并且对于定义数据组更有用。 但是,就字符串而言,我的老师建议使用gets 而不是scanf。这是因为 scanf 将在您输入的第一个空白处停止“获取”数据,就像在一个句子中一样......

    【讨论】:

      【解决方案3】:
      while (scanf("%i", &j) != 1) {
          while((ch = getchar()) != '\n') ;
          printf("enter an integer: ");
      }
      

      以下是此代码的分解方式。

      1. scanf() 使用输入流中的单个字符,直到它发现一个字符 匹配%i 转换说明符1,并且该不匹配字符留在输入流中;
      2. scanf() 尝试将输入文本转换为适当类型的值;即如果输入字符串"1234\n",则将其转换为整数值1234,转换后的值将赋给变量j,而'\n'将留在输入流中;
      3. 如果输入字符串中没有与转换说明符匹配的字符(例如"abcd"),则不执行任何转换,也不会为j 分配任何内容;
      4. scanf() 返回成功转换和分配的数量。
      5. 如果scanf()调用的结果不是1,那么用户没有输入有效的整数字符串;
      6. 由于输入流中留下了不匹配的字符,我们需要先将它们删除,然后才能尝试另一个scanf()调用,所以我们使用getchar()来消耗字符,直到看到换行符,此时我们提示用户再次尝试并再次执行scanf() 呼叫。


      1。 %i 转换说明符跳过任何前导空格并接受可选的八进制、十进制或十六进制格式的有符号整数常量。因此它将接受[+|-]{0x[0-9a-fA-F]+ | 0[0-7]+ | [1-9][0-9]*} 形式的字符串

      【讨论】:

        【解决方案4】:

        scanf 可以扫描任意格式的数据并将其解析为多种类型(整数、浮点数、字符串等)。 getchar 函数只获取一个字符并返回它。

        表达式

        scanf("%i", &j) != 1
        

        从标准输入中读取一个(可能有符号的)整数,并将其存储在变量j 中。然后它比较scanf 函数的返回值(返回成功扫描的转换次数)并将其与1 进行比较。这意味着如果scanf 没有读取或转换整数值,则表达式将为“真”。所以只要scanf失败,循环就会继续循环。

        您可能想查看this scanf reference

        printf 没有发生可能是因为它从未发生(使用调试器来找出),或者它只是 看似没有发生,但它确实发生了,因为输出需要冲洗。通过打印换行符或fflush 函数来刷新输出:

        fflush(stdout);
        

        【讨论】:

        • "scanf 函数的返回值(返回成功扫描的转换次数)" 这并没有发生在我身上,scanf() 输入整数时返回 1,输入整数时返回 0输入的字符串
        • @Salahuddin 这就是它应该如何工作的。当您输入一个整数时,它成功扫描并转换了您要求的整数,因此它返回1,因为它扫描并转换了一项。当您输入字符串时,它无法将其转换为整数,因此在扫描并转换零个项目时返回 0
        • 对不起,但我所知道的只是 scanf() 扫描输入并将其保存在某个地方,那么“转换”和“当您输入整数时”是什么意思它成功扫描并转换了您要求的整数”,我没有要求它将其转换为整数
        • @Salahuddin scanf 读取文本(字符序列)并根据您提供的格式代码转换它。使用"%i" 格式,您要求scanf 读取文本并将其转换为整数。
        【解决方案5】:

        据我所知,考虑到指定的输入格式,scanf 将读取用户输入直到第一个空格。但是,getchar 只能读取一个字符。

        scanf 将返回已成功读取的格式列表的参数数量,如here 所述。按下 1 或 2 时获得相同的结果,因为它们都被 %i 格式说明符成功读取。

        【讨论】:

          【解决方案6】:

          getchar 从输入中一次读取一个字符。根据您指定的数据类型,scanf 可以读取更多内容。

          使用 scanf() 不是一个好习惯尝试使用 fgets(),它比 scanf 更有效和安全。

          【讨论】:

          • fgets() 只能用于读取字符串/行。所以对于阅读数字 fgets() 是相当无用的。对于读取字符串,使用它比 scanf() 更有效。
          • @JoelKlinghed, fgets 在读取字符串时绝对比使用 scanf 更安全。对于其他数据类型,它是没用的,或者你必须在之后使用sscanf
          • scanf("%a") 通常比fgets 好,但它与getline() 一样非标准,我认为这是最好的。
          • @Devolus,是的,我混淆了gets()fgets(),并在我看到你的评论之前修复了我的评论。
          • @JoelKlinghed,大声笑,我昨天犯了一个类似的错误,将 fgets 与 fscanf 混淆了。 :)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-27
          • 2021-11-28
          • 1970-01-01
          • 2013-03-29
          • 2014-11-02
          • 1970-01-01
          • 2014-03-18
          相关资源
          最近更新 更多