2016-04-18 5 views
2

Ich versuche, ein Programm zu erstellen, das Daten aus einer TXT- oder ähnlichen Datei aufnimmt und den Benutzer nach einem Wort fragt, nach dem gesucht werden soll. Die Ausgabe sollte das Schlüsselwort im Zusammenhang mit den 2 Wörtern zeigen, die sich davor und dahinter befanden. (EX: Stichwort: Junge würde ausgeben "und der Junge rannte weg") Ich bin in der Lage, alle Instanzen des Schlüsselworts in der Datei mit der Funktion equal_range() zu finden, aber ich weiß nicht, wie ich die Daten in der Karte durchgehen soll um auf die anderen Wörter für den Kontext zuzugreifen. Hier ist mein Code so weit:Zugriff auf Elemente in einem 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; 
} 

Ich bin mir bewusst, dass der Code in der for-Schleife am unteren Rand falsch ist, aber es war zu Testzwecken.

Antwort

0

Sie benötigen bidirektionale Suche: Sie müssen ein Wort zu seinem Index zuordnen (das ist, was wordMap ist) und separat müssen Sie einen Index zu seinem Wort zuordnen (das ist was Sie vermissen). Lassen Sie uns also, dass hinzufügen, sowie zur Festsetzung Ihrer ersten Schleife:

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

Jetzt haben wir es in zwei Richtungen haben - da words Lookup durch Index ermöglicht. So haben wir:

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() etwas ist, das ein Paar von Iteratoren nimmt und gibt Ihnen wieder etwas, das Sie in einer bereichsbasierte für die Expression verwendet werden können. Dies berücksichtigt nicht die Grenzen von words (wenn Sie eines der ersten zwei oder die letzten zwei Wörter als Ihr Schlüsselwort auswählen), aber dies sollte Sie auf den richtigen Weg bringen.


Zusätzlich berücksichtigen std::map<std::string, std::vector<size_t>> statt std::multimap<std::string, size_t> verwenden, wenn Sie immer alle Werte sein werden Iterieren über und nicht Iterator Stabilität benötigen. Weitere Informationen finden Sie unter this question.

+0

Ist as_range etwas, das von etwas anderem als algorithm, math, vector und iostream enthalten sein muss? Mein Compiler sagt mir, dass es nicht definiert ist und ich nirgends eine klare Antwort finden kann – littlenv

0

Angesichts Ihrer Problemstellung ist ein map schlecht geeignet, da Sie sofort alle Positionsinformationen verlieren und Sie versuchen, einen Workaround zu finden. Wenn Sie möchten, dass alle Ihre Daten in einem Container gespeichert werden, können Sie es auch in einer vector halten und eine lineare Suche durchführen. Ja, ich weiß, es wird theoretisch langsamer, aber es ist eine faire Chance, es in der Praxis nicht sein ...

Für kichert, hier ist ein völlig anderer Ansatz mit <regex> Einrichtungen:

// 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));