需要正则表达式才能从字符串中提取字母和空格

时间:2011-04-04 14:31:21

标签: c++ regex

我正在构建一个小实用程序方法,它解析一行(一个字符串)并返回所有单词的向量。我下面的istringstream代码工作正常,除非有标点符号,所以自然我的修复是想在通过while循环运行它之前“清理”该行。

我很感激在c ++中使用正则表达式库的一些帮助。我最初的解决方案是我们substr()并去镇上,但这似乎很复杂,因为我将不得不迭代并测试每个角色,看看它是什么然后执行一些操作。

vector<string> lineParser(Line * ln)
{
    vector<string> result;
    string word;
    string line = ln->getLine();
    istringstream iss(line);
    while(iss)
    {
        iss >> word;
        result.push_back(word);
    }
    return result;
}

4 个答案:

答案 0 :(得分:7)

不需要仅为标点符号使用正则表达式:

// Replace all punctuation with space character.
std::replace_if(line.begin(), line.end(),
                std::ptr_fun<int, int>(&std::ispunct),
                ' '
               );

或者如果你想要除了字母和数字之外的所有东西都变成空间:

std::replace_if(line.begin(), line.end(),
                std::not1(std::ptr_fun<int,int>(&std::isalphanum)),
                ' '
               );

我们在这里:
你的while循环被打破,并将最后一个值推入向量两次。

应该是:

while(iss)
{
    iss >> word;
    if (iss)                    // If the read of a word failed. Then iss state is bad.
    {    result.push_back(word);// Only push_back() if the state is not bad.
    }
}

或更常见的版本:

while(iss >> word) // Loop is only entered if the read of the word worked.
{
    result.push_back(word);
}

或者您可以使用stl:

std::copy(std::istream_iterator<std::string>(iss),
          std::istream_iterator<std::string>(),
          std::back_inserter(result)
         );

答案 1 :(得分:2)

如果你没有替换匹配的字符,

[^A-Za-z\s]应该做你需要的。它应该删除所有不是字母和空格的字符。或[^A-Za-z0-9\s]如果你想保留数字。

您可以使用以下在线工具:http://gskinner.com/RegExr/来测试您的模式(替换标签)。实际上,根据您正在使用的正则表达式库,可能需要进行一些修改。

答案 2 :(得分:1)

我不是肯定的,但我认为这就是你要找的东西:

#include<iostream>
#include<regex>
#include<vector>

int
main()
{
    std::string line("some words: with some punctuation.");
    std::regex words("[\\w]+");
    std::sregex_token_iterator i(line.begin(), line.end(), words);
    std::vector<std::string> list(i, std::sregex_token_iterator());
    for (auto j = list.begin(), e = list.end(); j != e; ++j)
        std::cout << *j << '\n';
}

some
words
with
some
punctuation

答案 3 :(得分:0)

最简单的解决方案可能是创建过滤 streambuf将所有非字母数字字符转换为空格, 然后使用std :: copy:

进行阅读
class StripPunct : public std::streambuf
{
    std::streambuf* mySource;
    char            myBuffer;

protected:
    virtual int underflow()
    {
        int result = mySource->sbumpc();
        if ( result != EOF ) {
            if ( !::isalnum( result ) )
                result = ' ';
            myBuffer = result;
            setg( &myBuffer, &myBuffer, &myBuffer + 1 );
        }
        return result;
    }

public:
    explicit StripPunct( std::streambuf* source )
        : mySource( source )
    {
    }
};

std::vector<std::string>
LineParser( std::istream& source )
{
    StripPunct               sb( source.rdbuf() );
    std::istream             src( &sb );
    return std::vector<std::string>(
        (std::istream_iterator<std::string>( src )),
        (std::istream_iterator<std::string>()) );
}