1 2 3 4 5 6 7 8 9 10 11 12 13 |
//С++ Листинг #1 #include <map> struct Test{ int x, y, z; }; int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; m[t1] = 0; //В качестве ключа используется структура. Ошибка! не определена операция сравнения } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//C++ Листинг #2.1 Внешняя подгрузка операции < для сравнения ключей в map #include <map> #include <iostream> #include <tuple> using namespace std; struct Test{ int x, y, z; }; bool operator <(Test left, Test right){ return left.x < right.x && left.y < right.y && left.z < right.z; //Сравнение со скрытой ошибкой } int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; //В качестве ключа используется структура. OK. Код запускается m[t2] = 1; //Карта записывается m[t3] = 2; cout << m[t1] << '\n'; cout << m[t2] << '\n'; cout << m[t3] << '\n'; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//C++ Листинг #2.2 Внутренняя для класса-ключа операции < (для сравнения ключей в map) #include <map> #include <iostream> #include <tuple> using namespace std; struct Test{ int x, y, z; bool operator <(Test item) const{ //метод должен быть константным! return x < item.x && y < item.y && z < item.z; //Сравнение со скрытой ошибкой } }; int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; //В качестве ключа используется структура. OK. Код запускается m[t2] = 1; //Карта записывается m[t3] = 2; cout << m[t1] << '\n'; cout << m[t2] << '\n'; cout << m[t3] << '\n'; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//C++ Листинг #2.3 Использование кортежей для операции сравнения для ключей map #include <map> #include <iostream> #include <tuple> using namespace std; struct Test{ int x, y, z; bool operator <(Test item) const{ //метод должен быть константным! return tie(x, y, z) < tie(item.x, item.y, item.z); //Теперь сравнение корректно } }; int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; //В качестве ключа используется структура. OK. Код запускается m[t2] = 1; //Карта записывается m[t3] = 2; cout << m[t1] << '\n'; cout << m[t2] << '\n'; cout << m[t3] << '\n'; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//C++ Листинг #2.4 Использование лексикографичекого сравнения для ключей map #include <map> #include <iostream> #include <tuple> using namespace std; struct Test{ int x, y, z; bool operator <(Test item) const{ //метод должен быть константным! return x < item.x || (x == item.x && y < item.y) || (x == item.x && y == item.y && z < item.z); } }; int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; //В качестве ключа используется структура. OK. Код запускается m[t2] = 1; //Карта записывается m[t3] = 2; cout << m[t1] << '\n'; cout << m[t2] << '\n'; cout << m[t3] << '\n'; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//C++ Листинг #3.1 Не все обобщённые алгоритмы работают с map #include <map> #include <iostream> #include <tuple> using namespace std; struct Test{ int x, y, z; }; bool operator <(Test left, Test right){ return tie(left.x, left.y, left.z) < tie(right.x, right.y, right.z); } int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; //В качестве ключа используется структура. OK. Код запускается m[t2] = 1; //Карта записывается m[t3] = 2; sort(m.begin(), m.end()); //Ошибка компиляции! } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
//C++ Листинг #4.1 Некоторые обощённые алгоритмы умеют работать с map #include <map> #include <iostream> #include <tuple> #include <vector> #include <algorithm> #include <iterator> using namespace std; struct Test{ int x, y, z; }; bool operator <(Test left, Test right){ return tie(left.x, left.y, left.z) < tie(right.x, right.y, right.z); } int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; m[t2] = 1; m[t3] = 2; vector<pair<Test, int>> v; //Вектор пар для копирования пар из map copy(m.begin(), m.end(), back_inserter(v)); //Используем обобщённый алгоритм copy для map /*ОБХОДИМ ВЕКТОР ПАР*/ for (const auto &i: v){ cout << '{' << i.first.x << ',' << i.first.y << ',' << i.first.z << '}' << "==>" << i.second << '\n'; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
//C++ Листинг #6.1 find для map #include <map> #include <iostream> #include <algorithm> #include <utility> using namespace std; struct Test{ int x, y, z; }; bool operator <(const Test &left, const Test &right){ return tie(left.x, left.y, left.z) < tie(right.x, right.y, right.z); } /* (2. Перегрузка операции = для сравнения объектов Test между собой */ bool operator ==(const Test &left, const Test &right){ return tie(left.x, left.y, left.z) == tie(right.x, right.y, right.z); } /* (1. Перегрузка = для алгоритма find) */ bool operator ==(const pair<Test, int> key, const Test& item){ return key.first == item; } int main(){ map<Test, int> m; Test t1 = {1, 2, 3}; Test t2 = {3, 2, 1}; Test t3 = {2, 3, 1}; m[t1] = 0; m[t2] = 1; m[t3] = 2; cout << find(m.begin(), m.end(), Test{3, 2, 1})->second << '\n'; //t2 ==> 1 //Долгий способ поиска cout << m.find(Test{3, 2, 1})->second << '\n'; //t2 ==> 1 //Быстрый способ поиска } |
1 2 3 4 5 6 7 8 9 10 11 |
//C++ Листинг #7.1 Мусорные значения после find #include <map> #include <iostream> #include <string> using namespace std; int main(){ map<string, int> m; cout << m.find("str1")->second; // выводится какое-то значение } |
1 |
cout << m.find("str1")->second << " | " << m.end()->second; // выводится какое-то значение |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//C++ Листинг #7.2 Проверяем find на конечную позицию #include <map> #include <iostream> #include <string> using namespace std; int main(){ setlocale(LC_ALL, ""); map<string, int> m; map<string, int>::iterator it; it = m.find("str1"); if (it != m.end()){ cout << it -> second << '\n'; } else { cout << "ключ str1 не найден\n"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//C++ Листинг #8.1 Операция индексации посягает на запись в константный map #include <iostream> #include <map> using namespace std; int main(){ const map<int, int> m = { //если убрать const, то всё ОК {10, 20}, {30, 40}, {50, 60}, }; cout << m[10] << '\n'; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//C++ Листинг #8.2 Раздули map #include <iostream> #include <map> #include <string> int main(){ std::string arr[] = { "abc", "ass", "sds" }; std::string words[] = { "asgf", "dgr", "adghs", "bddfa" }; std::map<std::string, int> map; /*считаем слова*/ for(const auto& s: words){ ++map[s]; } /*выводим информацию на экран*/ for(const auto& s: arr){ std::cout << "word: " << map[s] << "\n"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//C++ Листинг #8.3 Раздули map #include <iostream> #include <map> using namespace std; int main(){ map<int, int> m; //Пустой map int count_ = 0; for (int i = 0; i < 1000; i++){ if (m[i] % 100 == 0){ ++count_; } } cout << count_ << '\n'; //1000 значений, делящиеся на 100! } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//C++ Листинг #8.2/1 Исправление 8.2 #include <iostream> #include <map> #include <string> #include <set> //Для того, чтоб не выводить элементы повторно using namespace std; int main() { std::string arr[] = { "raz", "dwa", "tri", "dwa" }; std::string words[] = { "asgf", "dwa", "adghs", "dwa" }; std::map<std::string, int> map; /*Заполняем map количеством встречаемости слов*/ for(const auto& s: words){ ++map[s]; } set<string> s{begin(arr), end(arr)}; //уникализируем массив, чтобы не выводить одинаковые результаты /*Обходим уникализированный массив s для анализа встречаемости его слов в words*/ for(const auto& i: s){ auto it = map.find(i); //Используем итератор для обнаружения слова и применяем find if (it != map.end()){ //Основываясь на результате find, выводим результаты cout << it->first << ' ' << it->second << '\n'; } else { //cout << i << ' ' << '0' << '\n'; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//C++ Листинг #8.3/1 Исправление 8.3 #include <iostream> #include <map> using namespace std; int main(){ map<int, int> m; //Пустой map int count_ = 0; for (const auto &i: m){ //Тип i автоматически будет приведён к итератору if (i.second % 100 == 0){ ++count_; } } cout << count_ << '\n'; //OK } |
Добавить комментарий