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

Posted

技术标签:

【中文标题】%[^\\n] 在 scanf() 格式字符串中是啥意思【英文标题】:What does %[^\n] mean in a scanf() format string%[^\n] 在 scanf() 格式字符串中是什么意思 【发布时间】:2014-10-27 22:03:29 【问题描述】:

我在这个网站上看到: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;

【问题讨论】:

匹配无限多个字符但不匹配\n,并将它们放入对应参数指向的char[]。 (因此它属于char* 类型,不是char** 谷歌搜索fscanf 将我带到msdn.microsoft.com/en-us/library/kwwtf9ch.aspx,只需点击三下鼠标。 请注意 new char[1001](); 不是 C -- 它是 C++ 代码。 尾随的() 是什么? 您应该将p 传递给fscanf(),而不是&amp;p。您几乎肯定应该在fout 的输出中包含一个换行符。您应该在打印之前检查输入是否成功。 FILE * 变量应该是 main() 的本地变量,而不是全局变量。可以说,您应该在退出之前关闭文件(尽管运行时系统会自动关闭它们,但通常认为关闭您打开的文件是更好的做法 - 这在长时间运行的程序中确实很重要,尽管它不会损害这一点一)。 【参考方案1】:

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

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

来自 C11 标准:

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


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


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

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

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

【讨论】:

这就是它的意思,读取从 scanf 到 \n 字符的所有内容。我看到你在说同样的话,或者我不明白。如果它做到了,为什么它不适用于该输入? @MihneaGafton 你没有解释它在什么方面不起作用。究竟发生了什么?它与您的预期有何不同? 对不起,没有正确解释,当我尝试使用该输入编译该代码时,它会在控制台上给我类似无限循环的错误。【参考方案2】:

% introduces a format-specifier, [ 表示它是一个扫描集并打开它,^ 在扫描集中的第一个位置从“匹配所有”反转为“匹配所有 in",\n 是换行符,] 关闭扫描集。

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

因此该参数必须具有 char* 类型。&amp;p 恰好是一个过多的地址,并且它指向的缓冲区 (new char[1001]) 是无限订单量级太小了。

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


其他要点:

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

    char buf[1001];
    

    或者,至少使用智能指针,这样你就不会忘记delete []它:

    std::unique_ptr<char> p = new char[1001];
    
    为什么要对它进行值初始化?那是多余的。使用new char[1001] 而不是new char[1001]()。 不要忘记检查fscanf的返回值,它应该是成功的赋值数。 C++(和 C99)在 main 的末尾有一个隐式的 return 0;。 你真的应该关闭你打开的所有文件 (fopen->fclose)。

【讨论】:

“限制匹配的长度(通过在扫描集和 % 之间放置 1000)。”这意味着像fscanf(fin, "%1000[^\n]", &amp;p); 这样写,我试过了,它向我显示了一个类似控制台错误的无限循环,类似于第一种情况。 @jonathan:我不认为“infinitely”是一个错字,虽然“infinitely”更准确一些,但它并没有强调无限的本质。 @MihneaGafton: ??无论如何,您是否阅读过关于额外的&amp; 存在错误的部分? @BenVoigt:我同意这种变化可能会引起争议——事实上,既然你提出了质疑,那就是有争议的。这取决于一个人如何理解“无限”。宇宙中没有足够的基本粒子来存储无限数量的字符,因此字符串无法容纳无限数量的字符。只有当“无限”字符数为 1000 或更少时,它才是安全的。如果 Deduplicator 对象,他可以“无限”恢复。 @Deduplicator 我做了,不工作,谢谢。一旦我弄清楚如何将此问题标记为已解决,我就会这样做。

以上是关于%[^\n] 在 scanf() 格式字符串中是啥意思的主要内容,如果未能解决你的问题,请参考以下文章

c语言中snum和cnum是啥意思,求教!

(n,) 在 numpy 和向量的上下文中是啥意思?

这个f在这句话中是啥意思? [复制]

scanf 格式说明符中的星号是啥意思? [复制]

java正则表达式中是啥意思

在C语言里printf是啥意思?怎么用??