2

我正在尝试创建一个程序,该程序从 .txt 或类似文件中获取数据,并要求用户输入要搜索的单词。输出应在上下文中显示关键字,其中包含最初位于其前面和后面的 2 个单词。(例如:关键字:男孩会输出“男孩跑了”)我可以使用 equal_range() 函数在文件中找到关键字的所有实例,但是我不知道如何遍历地图中的数据访问上下文的其他词。到目前为止,这是我的代码:

typedef multimap<string, int> templateMap;
templateMap wordMap;
typedef pair<templateMap::iterator, templateMap::iterator> searchTemplate;
searchTemplate search;
typedef pair<templateMap::const_iterator, templateMap::const_iterator> innerIteratorTemplate;
multimap<string, int>::iterator tempMap;
string tempWord;
string keyword;

// omitted code

for (size_t i = 0; !inData.eof(); i++)  
{
    inData >> tempWord;
    wordMap.insert(pair<string, int>(tempWord, i));
}

search = wordMap.equal_range(keyword);

for (multimap<string, int>::iterator itr = search.first; itr != search.second; ++itr)
{
    cout << "The keyword " << keyword << " is found at location " << itr->second << endl;

    tempMap = itr;
    itr->second = itr->second - 2;
    cout << itr->first << endl;
}

我知道底部 for 循环中的代码是错误的,但它是出于测试目的。

4

2 回答 2

0

您需要双向查找:您需要将一个单词映射到它的索引(这就是wordMap它的用途),另外您需要将一个索引映射到它的单词(这就是您所缺少的)。因此,让我们添加它,以及修复您的初始循环:

std::vector<std::string> words;
while (inData >> tempWord) {
    wordMap.insert(std::make_pair(tempWord, words.size()));
    words.push_back(tempWord);
}

现在,我们有它双向 - 因为words允许按索引查找。因此,我们有:

for (auto const& pair : as_range(wordMap.equal_range(keyword))) {
    for (size_t idx = pair.second - 2; idx < pair.second + 3; ++idx) {
        std::cout << words[idx] << ' ';
    }
    std::cout << '\n';
}

as_range()是需要一对迭代器并返回一些可以在基于范围的 for 表达式中使用的东西。这并没有考虑到words(如果您选择前两个或最后两个词中的一个作为关键字)的范围,但这应该让您走上正确的轨道。


此外,如果您总是要迭代所有值并且不需要迭代器稳定性,请考虑使用std::map<std::string, std::vector<size_t>>而不是。std::multimap<std::string, size_t>有关更多信息,请参阅此问题

于 2016-04-19T00:27:57.773 回答
0

鉴于您的问题陈述, amap不适合,因为您会立即丢失所有位置信息,并且您只能尝试寻找解决方法。如果您愿意将所有数据保存在一个容器中,您不妨将其保存在一个容器中vector并执行线性搜索。是的,我知道,理论上它会更慢,但它很有可能不会在实践中......

对于傻笑,这是一种完全不同的<regex>设施方法:

// Data.
string const text = "Pack my box with five dozen liquor jugs. The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.";

// Word to search for.
string target;
cin >> target;

// Capture the target and up to two words before and after.
regex const context(R"((?:([^\s]+)\s)?(?:([^\s]+)\s)?()" + target + R"()(?:\s([^\s]+))?(?:\s([^\s]+))?)");

// Perform search.
smatch matches;
regex_search(text, matches, context);

// Print results.
copy_if(matches.begin() + 1, matches.end(), ostream_iterator<string>(cout, "\n"), mem_fn(&smatch::value_type::matched));
于 2016-04-19T08:22:41.223 回答