scanf正则表达式 - C

12

我需要读取一个字符串,直到出现以下序列为止:\nx\n :

(.....)\n
x\n

\n是换行符,而(...)可以包含其他\n字符的任意字符。

据我所知,scanf允许使用正则表达式,但我无法使其读取字符串直到该模式。你能帮我设计scanf格式字符串吗?


我尝试了以下格式:

char input[50000];
scanf(" %[^(\nx\n)]", input);

但是它不起作用。


3
在任何标准的C语言中,scanf不支持正则表达式。 - stark
2
http://www.cplusplus.com/reference/cstdio/scanf/ - gongzhitaao
2个回答

26
据我所知,scanf不允许正则表达式。不幸的是,虽然其语法非常类似于正则表达式,但在scanf的实现中根本没有任何与正则表达式相似的东西。它只支持正则表达式的字符类,因此%[<something>]会被隐式地处理为[<something>]*。这就是为什么你调用scanf会被解释为读取一个由除了'(', ')', 'x', 和 '\n'之外的字符组成的字符串。
为了解决你目前的问题,你可以设置一个循环来逐个字符读取输入。每当你读取到一个'\n'时,检查以下几点:
  • 你迄今为止已经至少看到了三个字符;
  • 紧接在'\n'之前的字符是一个'x'
  • 'x'之前的字符是另一个'\n'
如果以上所有条件都成立,则你已经到达了你预期的输入序列的结尾;否则,你的循环应该继续执行。

13

scanf 不支持正则表达式。 它对字符类有限支持,但这完全不同。

永远不要使用 scanf, fscanf, 或 sscanf,因为:

  1. 数值溢出会触发 未定义行为。 C运行时允许仅因某人输入过多数字就 崩溃程序
  2. 某些格式说明符(特别是 %s)与 gets 一样不安全,即它们会愉快地写入超过提供的缓冲区的末尾并使您的程序崩溃。
  3. 它们使得处理畸形输入变得非常困难。

对于此案例,您不需要正则表达式;使用getline 每次读取一行,并在读取的行只是 "x" 时停止。然而,标准(不是ISO C,而是POSIX)正则表达式库的例程称为regcompregexec


5
请注意,大多数(全部?)真实的scanf实现(包括GNU系统上的实现)在整数溢出时不会使您的程序崩溃或执行任何不良操作。讨论[此处](https://groups.google.com/forum/#!topic/comp.std.c/P-VPAMpZu9c)建议可以重新措辞标准以要求合理行为,可能不需要更改任何实现。(具体请参见[Keith Thompson的帖子](https://groups.google.com/d/msg/comp.std.c/P-VPAMpZu9c/6kELb3kuBPMJ))。 然而,由于标准的措辞如此,对于“好”的C实现,无效输入的scanf是安全的,但不具备可移植性。 - Peter Cordes
即使没有UB,我也同意第三点:从匹配失败中恢复通常很困难。 - Peter Cordes
1
注意:可以通过使用长度修饰符来避免问题#2。 - Spikatrix
2
@CoolGuy 我个人认为,如果您必须采取额外的、可选的步骤来避免搞砸自己,那这就是一个设计不良好的API。 - zwol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接