Чтение текстового файла и возврат количества слов построчно в С++

Мы начинаем переходить с C на C++ в моем классе программирования, и наше текущее лабораторное задание состоит в том, чтобы создать программу, которая по заданному текстовому файлу считывает его содержимое, а затем возвращает список слов в файле вместе с номером строки, в которой они появляются. on и количество раз, которое это слово появляется в каждой строке в формате Word Line:Count.

Foo bar bar
Baz
Foo
<EOF>

Что должно вернуться:

Foo  1:1 3:1
Bar  1:2
Baz  2:1

Единственные структуры данных, которые мы рассмотрели до сих пор, — это карты, с помощью которых мы написали следующую программу, которая выводит общее количество слов.

int main(int argc, const char*argv[]) {
    map<string, unsigned int> table;
    string word;

    while (cin >> word) {
        ++table[word];
    }

    for (std::map<string, unsigned int>::iterator itr = table.begin();
            itr != table.end(); ++itr) {
        cout << itr->first << "\t" << itr->second << endl;
    }

    return 0;
}

Нам сказали, что эту программу можно (немного) изменить минимально, чтобы она печатала номер строки и количество слов. Мой вопрос: есть ли способ использовать карту, чтобы иметь 2 значения для каждого ключа? Или есть лучший способ реализовать что-то подобное?


person Zakery Alexander Fyke    schedule 14.04.2015    source источник
comment
1) Вам придется изменить код ввода, чтобы заметить номера строк, прежде чем беспокоиться о том, как их сохранить, 2) иметь 2 значения для каждого ключа сложно и недостаточно для ответа, но 3 ) вот большая подсказка: вместо map<string, int> подумайте о map<string, map<int, int>>.   -  person Beta    schedule 14.04.2015


Ответы (1)


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

Используйте карту со строковым ключом и вектором значений для хранения, индекс = WordLine, значение в индексе = Count

#include <vector>       // std::vector

using namespace std;
map<string, vector<int>> words;

Когда вы встретите слова, найдите их на карте и увеличьте вектор по индексу line_num, чтобы обозначить количество раз, которое оно появляется в строке.

#include <sstream>
using namespace std;

string line;
string word;
int line_num = 0;
while (getline(cin, line)) {
    istringstream words_iss(line); 
    while(line >> word) {
        ++words.at(word)[line_num];
    }
    ++line_num;
}

Неэффективность возникает из-за использования индекса для представления номера строки, поскольку слово может не отображаться до строки n. Однако, когда он помещает его в вектор с индексом n, он собирается выделить пространство для 0 - (n-1) целых чисел для вектора. Также при печати вам придется проверять каждое значение в векторе, чтобы убедиться, что оно не равно 0.

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

Как упоминалось в комментариях, другим решением было бы использование

map<string, map<int, int>> 

с похожей логикой. Что было бы более эффективным для большинства случаев.

person ZachSand    schedule 14.04.2015