2015-06-04 2 views
1

Итак, у меня есть текстовый файл, который довольно длинный (10k + words), и я пытаюсь поместить каждое уникальное слово в хэш-карту, используя стандартную картографическую библиотеку.Ввод слов из файла в хэш-карту (C++)

У меня есть цикл while, читающий каждое слово из файла. Проблема в том, что цикл while никогда не заканчивается. Я даже поставил оператор if в цикле, так что, если он достигнет eof(), он сломает цикл. Это еще не конец. Вот мой код до сих пор:

#include <iostream> 
#include <map> 
#include <string> 
#include <fstream> 
#include <cctype> 
using namespace std; 


string lowerCase(string isUpper); 

void main() 
{ 
//create hash map 
map<string, int> stringCounts; 

//temp string 
string nextString; 

//import file/write file 
ofstream writeFile; 
ifstream gooseFile; 

//open file to read from 
gooseFile.open("goose.txt"); 
if (gooseFile.is_open()) { 
    //read file word by word 
    while (gooseFile >> nextString) { //WORKS DO NOT CHANGE 
     //check for punctuation 
     for (int i = 0; i < nextString.length(); i++) { //WORKS DO NOT CHANGE 
      if (nextString[i] == ',' || nextString[i] == '!' || nextString[i] == ';' || nextString[i] == '-' || nextString[i] == '.' || nextString[i] == '?' || nextString[i] == ':' || nextString[i] == '"' || nextString[i] == '(' || nextString[i] == ')' || nextString[i] == '_' || nextString[i] == '\'') { 
       nextString.erase(i, i); 
       i--; 
      } 
     } 
     //put all into lowercase 
     nextString = lowerCase(nextString); //WORKS DO NOT CHANGE 
     //cout << nextString << endl; 

     //increment key value 
     stringCounts[nextString]++; 

     if (gooseFile.eof()) 
      break; 
    } 
} 

//close current file 
gooseFile.close(); 
cout << "I GOT HERE!"; 
//now print to an output file 
writeFile.open("output.txt"); 
if (writeFile.is_open()) { 
    cout << "ITS OPEN AGAIN"; 
    //write size of map 
    writeFile << "The size of the hash map is " << stringCounts.size() << endl; 
    //write all words in map 
    //create iterator 
    map<string, int>::iterator i = stringCounts.begin(); 
    //iterate through map 
    while (i != stringCounts.end()) { 
     writeFile << "The key and value is : (" << i->first << "," << i->second << ")\n"; 
     i++; 
    } 
} 
else 
    cout << "CANT OPEN\n"; 
} 


string lowerCase(string isUpper) 
{ 
    string toReplace = isUpper; 
    for (int i = 0; i < toReplace.length(); i++) { 
     if (toReplace[i] >= 65 && toReplace[i] <= 90) { 
      toReplace[i] = tolower(toReplace[i]); 
     } 
    } 
    return toReplace; 
} 
+0

'std :: map' не реализован с использованием хэш-таблиц - обычно это делается с помощью BST – Alejandro

ответ

3
nextString.erase(i, i); 

Я сомневаюсь, что это то, что вы хотите. string::erase (тот, который вы вызываете) ожидает позицию (для которой следует начинать стирание) и счетчик (для количества стираемых символов). Таким образом, эта строка стирает несколько символов, эквивалентных положению символа в строке. Так, например, если i равно 0, это приведет к стиранию 0 символов. Объедините этот факт со следующей строки:

i--; 

И если первый символ пунктуации, i останется на 0 и цикл никогда не закончится. Если вы хотите просто стереть 1 символ, вы можете сделать это:

nextString.erase(i, 1); 

Но было бы гораздо лучше, чтобы заменить что весь цикл и использовать только удалить/стирания идиомы.

auto new_end = std::remove_if(nextString.begin(), nextString.end(), 
     [](char c) { 
      // return true if c is punctuation 
     }); 
nextString.erase(new_end, nextString.end()); 
Смежные вопросы