【问题标题】:Assignment suppression flag in fscanffscanf 中的分配抑制标志
【发布时间】:2013-05-27 14:04:30
【问题描述】:

请看一下这段代码sn-p:

char line[80];
if(fscanf(stdin, "%*[\t\v\f ]%79[^\n]", line) != EOF)
        printf("%s\n", line);

输出:

$ gcc line.c -o line
$ ./line
 One space at the beginning.
One space at the beginning.
$ ./line
No space at the beginning.

$

现在如果是No space at the beginning,为什么整个字符串没有按原样打印?

$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3

【问题讨论】:

    标签: c scanf


    【解决方案1】:

    失败是因为"%*[\t\v\f ]"没有匹配,所以后面的格式说明符%79[^\n]没有被处理,line也没有被赋值。要跳过前导空格,请将扫描集替换为前导空格:

    if(fscanf(stdin, " %79[^\n]", line) == 1)
        printf("%s\n", line);
    

    【讨论】:

    • fscanfOne space at the beginning 的情况下也会失败,尽管不是在第一个字符处。并且不能在此处使用空格,因为它将消耗位于每行末尾的 \n 字符,如果有空行,这将产生问题。即仅包含 \n 的行。
    • @rootkea,我不确定您所说的不是在第一个字符是什么意思?
    • 对不起,我的意思是 [\t\v\f ]One space at the beginning 的情况下也失败了,虽然不是在第一个字符。
    • @rootkea,目标是跳过每一行的任何前导空格吗?
    • @rootkea,使用fgets() 读取一行。使用sscanf()从中提取。
    【解决方案2】:

    如果行首没有空格、制表符或分页符,scanf 将在第一次匹配 %*[\t\v\f ] 时失败。一旦失败,它将不会尝试匹配模式的其余部分。

    此外,您不需要手动匹配这些字符,格式字符串中的一个空格将扩展为输入字符串中任意数量的空格。请参阅isspace 的文档以检查哪些字符被视为空格。

    【讨论】:

    • 抱歉,不小心编辑了你的答案而不是我自己的。
    【解决方案3】:

    如果没有找到@hmjd 解释的字段,您将在扫描退出时遇到问题。

    注意:使用fgets() 是更好的方法,但要坚持 OP 风格:

    // consume select leading whitespaces, if any, but not \n
    fscanf(stdin, "%*[\t\v\f ]");
    
    // Scan non-eol chars
    char line[80];
    if (fscanf(stdin, "%79[^\n]", line) == 1) {
      printf("%s\n", line);
    }
    
    // scan a single EOL
    char eol[2];
    if (fscanf(stdin, "%1[\n]", eol) == 1) {
      ; // EOL found
    }
    

    通过分成 3 个 fscanf() 调用,依次尝试每种格式,即使之前的格式失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 1970-01-01
      • 2013-08-30
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多