Затем поток istringstream (см. раздел 8.3) используется для обработки каждого слова только что прочитанной строки. Внутренний цикл while использует оператор ввода класса istringstream для чтения каждого слова текущей строки в строку word. В цикле while используется оператор индексирования карты для доступа к связанному со словом указателю shared_ptr и связи ссылки lines с этим указателем. Обратите внимание, что lines — это ссылка, поэтому внесенные в нее изменения будут сделаны с элементом карты wm.
Если слова еще нет в карте, оператор индексирования добавит строку word в карту wm (см. раздел 11.3.4). Ассоциируемый со строкой word элемент инициализирован значением по умолчанию. Это значит, что ссылка lines будет нулевой, если оператор индексирования добавит строку word в карту wm. Если ссылка lines будет нулевой, резервируем новый набор и вызываем функцию reset() для обновлении указателя shared_ptr, на который ссылается ссылка lines, чтобы он указывал на этот только что созданный набор.
Независимо от того, был ли создан новый набор, происходит вызов функции insert(), добавляющей текущий номер строки. Поскольку lines — это ссылка, вызов функции insert() добавляет элемент в набор карты wm. Если данное слово встречается несколько раз в той же строке, вызов функции insert() не делает ничего.
QueryResultКласс QueryResult обладает тремя переменными-членами: строка, представляющая слово, указатель shared_ptr на вектор, содержащий входной файл; и указатель shared_ptr на набор номеров строк, в которых присутствует это слово. Его единственная функция-член — конструктор, инициализирующий эти три члена:
class QueryResult {
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
QueryResult(std::string s,
std::shared_ptr
std::shared_ptr
sought(s), lines(p), file(f) { }
private:
std::string sought; //
std::shared_ptr
std::shared_ptr
};
Единственная задача конструктора — сохранить свои аргументы в соответствующих переменных-членах, что он и делает в списке инициализации конструктора (см. раздел 7.1.4).
query()Функция query() получает строку, которую она использует для поиска соответствующего набора номеров строк в карте. Если строка найдена, функция query() создает объект класса QueryResult из заданной строки, переменной-члена file класса TextQuery и набора, извлеченного из карты wm.
Единственный вопрос: что следует возвратить, если заданная строка не найдена? В данном случае никакого набора возвращено не будет. Решим эту проблему, определив локальный статический объект, являющийся указателем shared_ptr на пустой набор номеров строк. Когда слово не найдено, возвратим копию этого указателя shared_ptr:
QueryResult
TextQuery::query(const string &sought) const {
//
static shared_ptr
//
//
auto loc = wm.find(sought);
if (loc == wm.end())
return QueryResult(sought, nodata, file); //
else
return QueryResult(sought, loc->second, file);
}
Функция print() выводит заданный объект класса QueryResult в заданный поток:
ostream &print(ostream &os, const QueryResult &qr) {
//
os << qr.sought << " occurs " << qr.lines->size() << " "
<< make_plural(qr.lines->size(), "time", "s") << endl;
//
for (auto num : *qr.lines) //
//
os << "\t (line " << num + 1 << ") "