fscanf中的分配抑制标志

fscanf中的分配抑制标志,c,scanf,C,Scanf,请查看此代码段: 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. $ 现在如果开头没有空格

请查看此代码段:

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.

$
现在如果
开头没有空格
为什么整个字符串没有按原样打印

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

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


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

它失败,因为%*[\t\v\f]“不匹配,因此后续的格式说明符
%79[^\n]
未被处理且
未分配。要跳过前导空格,请将扫描集替换为前导空格:

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

如果找不到字段,您的扫描将很难退出@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()
调用,每种格式都会依次尝试,即使之前的一个失败。

对此表示抱歉,意外地编辑了您的答案而不是我自己的。
fscanf
开头一个空格的情况下也会失败,尽管不是在第一个字符。并且不能在此处使用空格,因为它将使用驻留在每行末尾的
\n
字符,如果有空行,则会产生问题。i、 e.仅包含
\n
的行。@rootkea,我不确定你说的不在第一个字符是什么意思?对不起,我的意思是
[\t\v\f]
开头有一个空格的情况下失败,尽管不是在第一个字符。@rootkea,目标是跳过每行的任何前导空格吗?@rootkea,使用
fgets()
读取一行。使用
sscanf()
从中提取。