在 C++ 中匹配正则表达式的惯用方法

Posted

技术标签:

【中文标题】在 C++ 中匹配正则表达式的惯用方法【英文标题】:Idiomatic way to match a regular expression in C++ 【发布时间】:2013-11-15 10:21:45 【问题描述】:

我想在 C++ 中比较两个字符串:

    有一个函数getName() 返回一个字符串。 现在我可以写 Out << getName(); 这将打印字符串。 但是,如果字符串的值为arpitarpit*N*,其中N 是整数,我想打印字符串only。如果它的值为arpitaarpitx,我不想打印它,其中 N 不是整数或空字符串。

我知道这很容易做到,但我想用最少的行数做到这一点。

到目前为止我所做的是:

char name1[] = getName();
char name2[] = "arpit";
for (int x = 0; x <= 4; x++)
    if (name1[x] == name2[x]) continue;
    else return ( Out << "not equal") ;
    
while(name1[x] ! = "\0")
    if(isdigit(name1[x])
    x++;
    else return (Out << "not equal") ;
    
Out << getName();

更新 1 getName() 在遇到空格之前返回一个字符串,并且不会返回任何行或 2 个或更多单词。

【问题讨论】:

嗯。你试过什么?表现出一些努力,拜托。仅仅寻求这样的解决方案并不是 SO 的目的。 std::string s = getName(); if (s.size() &gt;= 5 &amp;&amp; s.substring(0,5) == "arpit") Out &lt;&lt; s; boost::starts_with(getName(), "arpit") 呢? 使用“comaparison”解决问题标题过滤器的形式不佳。 @razlebe 他已经取消了更新 2。对于一个不断变化的问题,很难说什么。 【参考方案1】:

如果你有 C++11:

static std::regex const matcher( "arpit\\d*" );

if ( regex_match( name, matcher ) ) 
    //  matches...

如果您没有 C++11,boost::regex 几乎是相同的。

如果你没有C++11,而且你不能使用boost:

if ( name1.size() >= name2.size()
    && std::equal( name2.begin(), name2.end(), name1.begin() )
    && std::find_if( name1.begin() + name2.size(),
                     name1.end(),
                     []( unsigned char ch )  return !isdigit( ch ); 
                    ) == name1.end() )
    //  matches...

对于其余部分,您的代码有很多错误,不应该 编译。特别是,getName()nothing 可以返回可用于初始化char [];这 C++ 中字符串的类型是std::string,而你的变量 应该是:

std::string name1( getName() );
std::string name2( "arpit" );

(除了你需要更好的名字。第二个可能是 例如referenceheader。)

当然,调用isdigit 是未定义的行为 一个char;您必须先转换为unsigned char

【讨论】:

【参考方案2】:
auto s = getName();
if(s.size() >= 5 && s.substr(0,5) == "arpit")
    Out << s;

【讨论】:

getName 是否返回对其他地方存在的东西的引用?他说它返回了一个字符串。除非它返回一个引用,否则将它分配给一个引用只是多余的废话(并且可能会稍微减慢程序的速度)。 这是对auto的公然滥用,甚至可能导致程序不正确(例如getName()返回char const*。即使getName返回std::string,也没有必要混淆。 最后,当然,这不符合他的要求,因为它还会打印"arpita"等。(更不用说比较第一个更有效的方法了5 个字符而不是创建一个子字符串。)【参考方案3】:
std::set<std::string> m_allowed_strings;

std::string validate_string(const string & s)

    if(m_allowed_strings.find(s) != m_allowed_strings.end())
            return s;
    return "";


cout << validate_string(getName());

【讨论】:

看起来有点矫枉过正。我们需要拨打getName 两次吗?我们还没有被告知它实际上在做什么,例如,它可能会从名称文件中返回每一行。 我认为在这里使用set 是不可能的,而且这当然不合理。尽管他的示例在"arpit" 之后只有 1 个数字,但他的编码尝试表明可以有更多;这意味着有效字符串的集合是无限的。

以上是关于在 C++ 中匹配正则表达式的惯用方法的主要内容,如果未能解决你的问题,请参考以下文章

c++标准库中没有关于正则匹配字符串的函数么

使用正则表达式在 C++ 中提取匹配的字符串

正则表达式分组与 C++ 11 正则表达式库匹配

面试题19:正则表达式匹配(C++)

尝试在 C++ 中使用 boost 正则表达式匹配从字符串转换为 int 时出错

C++ Primer 5th笔记(chap 17 标准库特殊设施)正则表达式