Вывод мультикарты после копирования с карты
Вопрос
Эта программа сохраняет пары на карте, подсчитывая, сколько раз встречается слово.Цель состоит в том, чтобы данные были отсортированы по количеству вхождений и выведены в виде значения / строки.Очевидно, что карта нормалей сортируется по строковому ключу, поэтому мне пришлось изменить ее местами.
Чтобы сделать это, я читаю словами и соответствующим образом увеличиваю их значения на карте.Затем я создаю мультимап и копирую пары с карты в мультимап, но в обратном порядке.Затем я выполняю итерацию по мультикарте, выводя пары.Однако при попытке вывести пары возникает ошибка времени выполнения, и я не уверен, почему.
Вот этот код:
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<string, int> words;
multimap<int, string> words2;
string s;
while (true) {
cin >> s;
if (s == "0") break;
++words[s];
}
map<string, int>::iterator p;
for (p = words.begin(); p!=words.end(); ++p)
words2.insert(make_pair(p->second, p->first));
multimap<int, string>::iterator p2;
for (p2 = words2.begin(); p2!=words2.end(); ++p2)
cout << p->first << ": " << p->second << '\n';
}
Любая помощь приветствуется.
P.S.Я читал в разных местах, что multimap может иметь несколько вхождений ключа (именно поэтому я использовал его в первую очередь) и / или несколько значений в одном ключе.Было бы неплохо внести некоторые уточнения относительно того, что является правдой или верны и то, и другое.
Также существует ли какой-либо тип алгоритма копирования для карт?Я решил просто использовать цикл for для простоты, и, вероятно, было бы довольно легко написать пользовательскую копию, но мне просто интересно (для копирования карт в другие парные контейнеры и копирования в output).
Решение
for (p2 = words2.begin(); p2!=words2.end(); ++p2)
cout << p->first << ": " << p->second << '\n';
Разве p в вашем выводимом операторе не должно быть p2 ?
Другие советы
Похоже, вы используете p вместо p2 при печати, измените выходную строку на:
cout << p2->first << ": " << p2->second << '\n';
Этой ошибки можно было бы избежать, если бы вы объявили p в цикле for, а не перед ним, поскольку он вышел бы из области видимости после завершения первого цикла for.
Я знаю, что это с 2009 года, но чтобы ответить на вторую часть вопроса, да, существуют алгоритмы в std
для копирования элементов между диапазонами.При копировании между контейнерами с одинаковым типом значения используйте std::copy
с std::inserter
будет делать:
map<string, int> wordsA;
multimap<string, int> wordsB;
copy(wordsA.begin(), words.end(), inserter(wordsB, wordsB.begin()));
Поскольку вы копируете в контейнер другого типа, вы можете использовать std::transform
чтобы применить функцию преобразования к элементам перед вставкой их во второй контейнер:
transform(words.begin(), words.end(),
std::inserter(words2, words2.begin()),
[](const pair<string, int>& x) -> pair<int, string>
{
return make_pair(x.second, x.first);
}
);
Как это обычно бывает, на самом деле получается больше строк кода, чем в вашем простом цикле, и делает по сути то же самое :)
Пожалуйста, обратите внимание, что std::copy
, std::transform
и т.д...будет работать практически с любым контейнером из std
.Это не относится конкретно к std::map
.Вы также можете использовать std::front_inserter
и std::back_inserter
с контейнерами, которые имеют push_front()
соответственно. push_back()
методы.