%[^n]在scanf()格式字符串中是什么意思

What does %[^ ] mean in a scanf() format string

本文关键字:格式 字符串 意思 是什么 scanf      更新时间:2023-10-16

我在这个网站上看到:fscanf(fin, "%[^n]", &p);可以用于从我的输入文件(fin)读取到字符类型指针(*p)中的所有字符,直到第一个输入命中为止。在某些输入中,它可以正常工作,但在其他输入中则不然。

这是我应该处理但不能处理的输入:

(((zahar 100 ou 3) 5 unt 100 nuca 200) 4 (lapte 200 cacao 50 zahar 100)3)20

这是我的全部代码:

#include <string.h>
#include <stdio.h>
FILE *fin, *fout;
int main()
{
    fin =  fopen("reteta.in", "r");
    fout = fopen("reteta.out", "w");
    char *p;
    p = new char[1001]();
    fscanf(fin, "%[^n]", &p);
    fprintf(fout, "%s", &p);
    return 0;
}

%[表示法引入了一种称为"扫描集"的东西,它有点像正则表达式(但没有那么强大)。

在您的特定示例中,这意味着格式说明符指示scanf继续扫描与除n之外的任何字符匹配的字符(遇到不匹配的字符将终止扫描)。

来自C11标准:

转换说明符包括格式字符串,最多包含匹配的右括号(])。这个括号(扫描列表)之间的字符组成扫描集,除非左括号后的字符是扬抑符(^),在这种情况下,扫描集包含未出现在位于扬抑符和右括号之间的扫描列表


即使将其与正则表达式进行比较,也会对其进行扩展:标准只是简单地说:"匹配一组预期字符中的非空字符序列"。


Jonathan Leffler发现的代码的真正问题是:

fscanf(fin, "%[^n]", &p);
                      ^

删除&,因为您要传递p,而不是"p的地址"。

%引入了一个格式说明符,[表示它是一个扫描集并打开它,扫描集中第一个位置的^从"match all in"反转为"match allnotin",n是换行符,]关闭扫描集。

因此,它意味着:无限期地匹配许多不是n的字符,并将它们放入参数所指向的char[]中。

因此,该参数的类型必须为char*
&p正是一个太多的地址,并且它所指向的缓冲区(new char[1001])太小了无数个数量级。

限制匹配的长度(通过在扫描集和%之间放置1000)
或者,最好使用fgets


其他要点:

  1. 您的缓冲区应该是堆栈分配的,因为它足够小:

    char buf[1001];
    
  2. 或者,至少使用一个智能指针,这样你就不会忘记delete [] it:

    std::unique_ptr<char> p = new char[1001];
    
  3. 为什么要对其进行值初始化?这是多余的。使用new char[1001]而不是new char[1001]()
  4. 不要忘记检查fscanf的返回值,它应该是成功分配的次数
  5. C++(和C99)在CCD_ 25的末尾具有隐含的CCD_
  6. 您确实应该关闭所有打开的文件(fopen->fclose