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

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

  1. 有一个函数getName() 返回一个字符串。
  2. 现在我可以写 Out << getName(); 这将打印字符串。
  3. 但是,如果字符串的值为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。对于一个不断变化的问题,很难说什么。

标签: c++ regex string


【解决方案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 个数字,但他的编码尝试表明可以有更多;这意味着有效字符串的集合是无限的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多