2016-04-18 140 views
2

我试图创建一个程序,它接收来自.txt或类似文件的数据并要求用户输入要搜索的单词。输出结果应该显示关键字与原来在它前面的两个单词以及它后面的单词。 (EX:关键字:男孩会输出“,男孩跑了”)我可以找到该文件中的所有关键字与equal_range()函数的实例,但我不知道如何遍历地图中的数据访问其他文字的上下文。这里是我的代码到目前为止:访问mulimap中的元素

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循环底部的代码是错误的,但它是用于测试目的。

回答

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()是一些需要对迭代器,给你回的东西,你可以在使用范围为基础的表达。这不包括words(如果您选择前两个或最后两个单词中的一个作为关键字)的界限,但这应该使您走上正确的轨道。


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

+0

是as_range是否需要从算法,数学,向量和iostream以外的其他东西中加入?我的编译器告诉我这是未定义的,我无法在任何地方找到明确的答案 – littlenv

0

鉴于您的问题陈述,map不适合,因为您立即失去了所有的位置信息,而您仍然试图找到解决方法。如果您愿意将所有数据保存在容器中,则最好将其保存在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));