【问题标题】:C, Buffer not clearing as expected?C、缓冲区没有按预期清除?
【发布时间】:2013-10-10 19:00:46
【问题描述】:

我在理解教授给我的一些 C 代码时有些困难。代码如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  char name[1000];

  printf( "What's your name? " );
  scanf( "%s", name );
  printf( "name is %s\n", name );

  scanf( "%[^\n]", name ); /* read the entire line (up to but not
                              including the '\n' at then end) */

  getchar(); /* consume the newline from the input */

  printf( "name is %s\n", name );

  return EXIT_SUCCESS;
}

用户输入一个名字并打印两次:

What's your name? Dan
name is Dan
name is Dan

这让我很困惑。提示用 printf 打印,输入用 scanf 读入缓冲区,缓冲区用 printf 打印。但是,第二个 printf 中的 \n 应该清除缓冲区,那么第二个 scanf 从哪里读取?我认为它会等待用户输入(给定一个空缓冲区),但它不会,它只知道名称。 这是如何运作的?

【问题讨论】:

    标签: c buffer


    【解决方案1】:

    第二个scanf() 调用卡住了,什么也没做,因为下一个要读取的字符是\nscanf() 不处理“空”输入,只是保持 name 缓冲区不变。由于name 未更改,因此名称的第二个printf() 与名称的第一个printf() 相同。

    如果您检查scanf() 的返回值,您会注意到第二个返回0,这意味着它没有扫描任何输入。

    此代码使用scanf() 的方式存在危险。由于输入说明符不会通知scanf() 要读取多少字节,因此输入可能会超出name 缓冲区。这可能导致未定义的行为,在最坏的情况下,会被用于堆栈粉碎攻击。您可以通过通知scanf() 不要扫描太多字节来避免此问题:

        scanf( "%999s", name );
    
        scanf( "%999[^\n]", name );
    

    必须在scanf() 的格式字符串中拼出长度,无法在变量参数中提供此信息作为参数。通常认为使用fgets()处理用户输入,然后使用sscanf()解析更可靠。

        /* get the name */
        char input[sizeof(name)];
        input[sizeof(input)-2] = '\n'
        if ( fgets( input, sizeof(input), stdin ) != 0 ) {
            if ( sscanf( "%s", name ) == 0 ) name[0] = '\0';
        }
    
        /* get the rest of the line in case it was really long */
        while ( input[sizeof(input)-2] && input[sizeof(input)-2] != '\n' ) {
            input[sizeof(input)-2] = '\n';
            if ( fgets( input, sizeof(input), stdin ) == 0 ) break;
        }
    

    【讨论】:

    • 漂亮而快速的总结+1
    • 所以给定一个像 "\n" 这样的字符,scanf() 既不会把它当作输入(把名字改成 "\n")也不会把它当作空输入(等待用户输入) ?
    • 我不确定您是否可以像尝试那样使用格式字符串。在发布此答案之前,我在这里阅读:en.wikipedia.org/wiki/Scanf_format_stringcplusplus.com/reference/cstdio/scanf
    • 您的第二个扫描字符串显示“扫描由除\n 之外的任何字符组成的字符串”。因为下一个字符是\nscanf() 只是卡住了,意思是,它表现为:“因为输入中没有非\n 字符,所以我什么都不做”。也就是说,你不能使用scanf()函数来扫描一个空字符串。
    猜你喜欢
    • 2013-01-01
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    • 2014-02-25
    • 1970-01-01
    相关资源
    最近更新 更多