定位字符串中匹配的单词

locating matched words in a string

本文关键字:单词 字符串 定位      更新时间:2023-10-16

我有一个文件a,有多个段落。我需要确定我在哪里匹配了另一个文件b中的单词。我需要告诉每个单词的段落、行号和单词号,包括那些与文件b中的单词匹配的单词。到目前为止,我已经放弃了向量、数组和字符串分割。我学过(我想)stringstream。目前,我读一行,然后在"。"上把它分成句子,然后再把这些句子读回去,在"上分开。我有行号计数,单词计数和匹配,但我似乎就是无法得到段落号(我已经意识到p++实际上是在计算行数,而l++也在计算单词数)。有人能帮帮我吗?edit每个段落用"n"分隔,每个句子用"。"分隔。我仍然需要找到一种方法来忽略所有其他标点符号,以便单词100%匹配,并且不会被逗号、分号或其他标点符号所遗漏。我猜这将是一个正则表达式在那里的某个地方。

从文件中输入的

文本看起来像:

我的狗虚弱的膝盖上长了跳蚤。这是一条直线。这段结束了。'n'跳蚤是一个可以匹配的词。这是另一行。这段结束了。'n'之前

输出应该看起来像这样:

<>之前第1段第1行第1词我的第1段第1行第2词狗第1段第1行第3字有第1段第1行第4字匹配!跳蚤之前
while (getline(fin, para)) { //get the paragraphs
    pbuffer.clear();
    pbuffer.str("."); //split on periods
    pbuffer << para;
    p++; //increase paragraph number
    while (pbuffer >> line) { //feed back into a new buffer
        lbuffer.clear();
        lbuffer.str(" "); //splitting on spaces
        lbuffer << line;
        l++; //line counter
        while (lbuffer >> word) { //feed back in
            cout << "l " << l << "   W:  " << w << "   " << word;
            fmatch.open("match.txt");
            while (fmatch >> strmatch) {  //did I find a match?
                if (strmatch.compare(word) == 0) {
                    cout << "  Matched!n";
                }
                else {
                    cout << "n";
                }
            }

既然您说可以在读取时写入每个单词,那么我们就不使用集合了。我们就用istringstreamistream_iterator来对指标。
假设fin是好的,我将简单地写入cout,您可以进行适当的调整以写入您的文件。

1st你需要在你的"fmatch.txt"读入vector<string>,像这样:

const vector<string> strmatch{ istream_iterator<string>(fmatch), istream_iterator<string> }

然后你只需要在嵌套循环中使用它:

string paragraph;
string sentence;
for(auto p = 1; getline(fin, paragraph, 'n'); ++p) {
    istringstream sentences{ paragraph };
    for(auto s = 1; getline(sentences, sentence, '.'); ++s) {
        istringstream words{ sentence };
        for_each(istream_iterator<string>(words), istream_iterator<string>(), [&, i = 1](const auto& word) mutable { cout << 'w' << i++ << ", p" << p << ", s" << s << (find(cbegin(strmatch), cend(strmatch), word) == cend(strmatch) ? ", word, " : ", namedEntity, ") << word << endl; });
    }
}
<<p> 生活例子/kbd> 编辑:

作为解释,我使用for_each对句子中的每个单词调用lambda。

让我们分解lambda并解释每个部分的作用:

  • [&通过引用,将lambda声明的作用域中的任何变量暴露给lambda以供使用:http://en.cppreference.com/w/cpp/language/lambda#Lambda_capture因为我在lambda中使用strmatch, ps,这些将通过引用
  • 捕获
  • , i = 1] c++ 14允许我们在auto类型的lambda捕获中声明一个变量所以iint每次进入lambda声明的作用域时都会重新初始化,这里是嵌套的for -loop
  • 的每个条目
  • (const auto& word)这是传递给lambda的参数列表:http://en.cppreference.com/w/cpp/language/lambda这里for_each将只是传递在string s
  • mutable因为我正在修改i,它是由lambda拥有的,我需要它是非const,所以我声明lambda mutable

在lambda的主体中,我将使用find和标准插入操作符来编写值。

EDIT2:

如果限于c++ 11,则不能在lambda捕获中声明变量。你可以在外部提供:

string paragraph;
string sentence;
for(auto p = 1; getline(fin, paragraph, 'n'); ++p) {
    istringstream sentences{ paragraph };
    for(auto s = 1; getline(sentences, sentence, '.'); ++s) {
        istringstream words{ sentence };
        auto i = 1;
        for_each(istream_iterator<string>(words), istream_iterator<string>(), [&](const auto& word){ cout << 'w' << i++ << ", p" << p << ", s" << s << (find(cbegin(strmatch), cend(strmatch), word) == cend(strmatch) ? ", word, " : ", namedEntity, ") << word << endl; });
    }
}

我终于弄明白了,但是我没有使用流交互器(对不起!)当然也没有那么优雅@jonathanMee

我对匹配的单词进行矢量化,并使用字符串流读入嵌套的字符。然后使用if语句检查段落,并在使用字符串流将数据从一个字符串输入到另一个字符串时进行分隔。在分隔数据时进行递增,然后进行匹配。例子:

            pholder.clear();
            pholder.str("."); //break on the delimiter
            pholder << para; //read from the paragraph into pholder
            l++;
            while (pholder >> line) {// here are all my lines now
                lholder.clear();
                lholder.str(" "); //breka on the spaces
                lholder << line; //read for it