%[^ \ n]在scanf()格式字符串中的含义是什么

时间:2014-10-27 22:03:29

标签: c++ string pointers

我在这个网站上看到:fscanf(fin, "%[^\n]", &p);可用于从我的输入文件(fin)读取到该char类型指针(*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;
}

2 个答案:

答案 0 :(得分:4)

%[符号引入了一种称为“scanset”的东西,它有点像正则表达式(但不是那么强大)。

在您的具体示例中,它表示格式说明符指示scanf保持扫描与\n之外的任何内容匹配的字符(遇到不匹配的字符将终止扫描)。

来自C11标准:

  

转换说明符包括中的所有后续字符   格式字符串,包括匹配的右括号(])。该   括号之间的字符(扫描列表)组成扫描集,   除非左括号后的字符是旋音(^), in   在哪种情况下,scanset包含所有未出现的字符   旋转和右支架之间的扫描列表


即使将它与正则表达式进行比较也会拉伸它:标准简单地说:“匹配来自一组预期字符的非空字符序列”。


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

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

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

答案 1 :(得分:2)

% introduces a format-specifier[表示它是扫描设置并打开它,^在扫描设置的第一个位置反转来自&#34;匹配全部&# 34;要&#34;匹配&#34;中的所有\n是换行符,]会关闭扫描集。

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

因此,该论点必须具有char*类型 &p只是一个地址 - 太多,它所指向的缓冲区(new char[1001])的数量级太小。

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


其他要点:

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

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

    std::unique_ptr<char> p = new char[1001];
    
  3. 为什么要重视它?这是多余的。使用new char[1001]代替new char[1001]()
  4. 不要忘记检查fscanf的返回值,它应该是成功分配的数量。
  5. C ++(和C99)在return 0;末尾隐含main
  6. 你真的应该关闭你打开的所有文件(fopen - &gt; fclose)。