нужна помощь с C ++, используя карты, чтобы отслеживать слова в файле INPUT - PullRequest
1 голос
/ 17 июня 2010

Допустим, у меня есть текстовый файл с

today is today but
tomorrow is today tomorrow

, а затем с помощью карт, как я могу отслеживать слова, которые повторяются?и по какой линии это повторяется?до сих пор у меня есть каждая строка в файле, считанная как временная, и она сохраняется следующим образом:

    map<string,int> storage;

    int count = 1 // for the first line of the file

    if(infile.is_open()){
     while( !infile.eof() ){ 
      getline(in, line);
      istringstream my_string(line);
      while(my_string.good()){
         string temp;
         my_string >> temp;

    storage[temp] = count
    }
    count++;// so that every string read in the next line will be recorded as that line.
}
}
   map<string,int>::iterator m;
   for(int m = storage.begin(); m!= storage.end(); m++){
      out<<m->first<<": "<<"line "<<m->second<<endl;
}

сейчас вывод просто

but: line 1
is: line 2
today: line 2
tomorrow: line 2

Но вместо этого... он должен распечатать (без повторяющихся строк):

today : line 1 occurred 2 times, line 2 occurred 1 time.
is: line 1 occurred 1 time, line 2 occurred 1 time.
but: line 1 occurred 1 time.
tomorrow: line 2 occurred 2 times.

Примечание: порядок строк не имеет значения.

Любая помощь приветствуется.Спасибо.

Ответы [ 4 ]

2 голосов
/ 17 июня 2010

карта хранит пару (ключ, значение) с уникальным ключом.Это означает, что если вы назначите одну и ту же клавишу более одного раза, будет сохранено только последнее заданное вами значение.

Похоже, что вы хотите вместо сохранения строки в качестве значения, вы хотитехранить другую карту линий-> вхождения.

Таким образом, вы можете сделать свою карту следующим образом:

typedef int LineNumber;
typedef int WordHits;
typedef map< LineNumber, WordHits> LineHitsMap;
typedef map< string, LineHitsMap > WordHitsMap;
WordHitsMap storage;

Затем вставить:

WordHitsMap::iterator wordIt = storage.find(temp);
if(wordIt != storage.end())
{
    LineHitsMap::iterator lineIt = (*wordIt).second.find(count);
    if(lineIt != (*wordIt).second.end())
    {
        (*lineIt).second++;
    }
    else
    {
        (*wordIt).second[count] = 1;
    }
}
else
{
    LineHitsMap lineHitsMap;
    lineHitsMap[count] = 1;
    storage[temp] = lineHitsMap;
}
1 голос
/ 17 июня 2010

вы пытаетесь получить 2 элемента информации из коллекции, когда в ней хранится только 1 элемент информации.

Самый простой способ расширить текущую реализацию - сохранить структуру вместоint.

Таким образом, вместо:

storage[temp] = count

вы должны сделать:

storage[temp].linenumber = count;
storage[temp].wordcount++;

, где определена карта:

struct worddata { int linenumber; int wordcount; };
std::map<string, worddata> storage;

распечатайте результаты, используя:

out << m->first << ": " << "line " << m->second.linenumber << " count: " << m->second.wordcount << endl;

edit: используйте typedef для определений, например:

typedef MYMAP std::map<std::string, struct worddata>;
MYMAP storage;

затем MYMAP::iterator iter;

0 голосов
/ 18 июня 2010

Помимо всего прочего, ваши циклы все не так. Вы должны никогда не зацикливаться на флагах eof или good, но на успехе операции чтения. Вы хотите что-то вроде:

while( getline(in, line) ){ 
      istringstream my_string(line);
      string temp;
      while(my_string >> temp ){
           // do something with temp
      }
}
0 голосов
/ 17 июня 2010

Тип данных хранилища недостаточен для хранения всей информации, которую вы хотите сообщить. Вы могли бы добиться этого, используя вектор для хранения счетчиков, но вам пришлось бы много заниматься бухгалтерским учетом, чтобы убедиться, что вы фактически вставляете 0, когда слово не встречается, и создаете вектор с правильным размером, когда новое слово встречается. Нетривиальная задача.

Вы можете переключить свою часть подсчета на карту чисел, сначала это строка, а вторая счет ... Это уменьшит сложность вашего кода, но точно не будет самым эффективным методом.

В любом случае, вы не можете делать то, что вам нужно, просто используя std :: map

Редактировать: просто подумал об альтернативной версии, которую было бы проще сгенерировать, но сложнее сообщить с помощью: std :: vector >. Для каждой новой строки в файле вы генерируете новую карту и помещаете ее в вектор. Вы можете создать вспомогательный набор типов , который будет содержать все слова, которые появляются в файле для использования в ваших отчетах.

Вероятно, так или иначе я бы сделал это, за исключением того, что я инкапсулировал все это дерьмо в классе, так что я просто сделал бы что-то вроде:

my_counter.word_appearance(word,line_no);
...