Map (Введение)

Контейнер map, очень похож на остальные контейнеры, такие как vector, list, deque, но с небольшим отличием. В этот контейнер можно помещать сразу два значения. Если у Вас когда-то была мечта написать свой словарь, то лучше чем map, вам альтернативы не найти. И так, что же такое этот map, давай рассмотрим более подробнее на примере:

#include <iostream>
#include <map>    //подключили библиотеку для работы с map
using namespace std;

int main()
{
  map <string,int> myFirstMap = {{ "Mother", 37 },
                                 { "Father", 40 },///map явно инициализирована
                                 { "Brother", 15 },
                                 { "Sister", 20 }};

  ///вывод явно инициализированной map на экран
  for (auto it = myFirstMap.begin(); it != myFirstMap.end(); ++it)
  {
      cout << it->first << " : " << it->second << endl;
  }

  char c;
  map <char,int> mySecondMap;
  for (int i = 0,c = 'a'; i < 5; ++i,++c)
  {
      mySecondMap.insert ( pair<char,int>(c,i) );
  }

  ///вывод не явно инициализированной map на экран
  for (auto it = mySecondMap.begin(); it != mySecondMap.end(); ++it)
  {
      cout << (*it).first << " : " << (*it).second << endl;
  }
  return 0;
}

Пример выполнения программы:

CppStudio.com
Brother : 15
Father : 40
Mother : 37
Sister : 20
a : 0
b : 1
c : 2
d : 3
e : 4

Во 2 строке мы подключили библиотеку для работы с map. В строках 7-10 происходит явное объявление map, это объявление ничем не отличается от объявления векторов, массивов, за исключением того, что объявляются сразу два типа переменных (первый тип – string, второй тип — int). В кавычках объявляются строки, а через запятую соответствующее строке число. Если бы написали вместо string тип char, то объявление было-бы таким:

map <char,int> myFirstMap= {{ 'm', 37 },
                            { 'f', 40 },
                            { 'b', 15 },
                            { 's', 20 }};

Нужно добавить, что map можно использовать в виде ассоциативного массива. Массива который позволяет в себе хранить пару вида («ключ», «значение»), а так-же добавлять и удалять пары по ключу. У нас в роли ключа выступает тип string,  а в роли значения тип int.

Осуществление вывода ничем не отличается от вывода тех же векторов. Обратите внимание, что вывод осуществляется в алфавитном порядке, а заполнение map в строках 7-10, нет. Контейнер  map  сам выполняет сортировку по алфавиту. В строках 13-16 осуществляется вывод с помощью итератора it. Итератор it сначала указывает на начало map и с каждой новой итерацией увеличивается, пока не достигнет конца map. Самое интересное располагается в  строке 15. Запись вида it->first означает, что it при первой итерации указывает на строку Mother, потом на Father и так далее до конца цикла, соответственно, запись вида it->second означает, что it при первой итерации указывает на число 37, потом на 40 и так далее.

В строке 19 мы объявили map mySecondMap. В строках 20-23 заполняем его. Строка 22 содержит функцию map::insert(). Которая вставляет элементы в  map. Запись вида pair<char,int>(c,i) означает, что в   map помещаются две переменные типа char и int (первая – char, вторая — int), где типу char соответствует  переменная c, а типу int соответствует  переменная i. В строке 20 при каждой новой итерации наши переменные будут увеличиваться, т. е. сначала i=0, c=a, при следующей итерации i=1, c=b и т. д. В строке 28 показан альтернативный вывод map с помощью указателей. У map есть один небольшой недостаток, она не может содержать два одинаковых значения, но multimap решает эту проблему, пример:

#include <iostream>
#include <map>
using namespace std;

int main()
{
  map <char,int> myFirstMap;///объявили map

  ///заполняем myFirstMap
  myFirstMap.insert ( pair<char,int>('a',10) );
  myFirstMap.insert ( pair<char,int>('a',20) );
  myFirstMap.insert ( pair<char,int>('a',10) );

  cout << "myFirstMap contains:\n";
  for (auto it = myFirstMap.begin(); it != myFirstMap.end(); ++it)///вывод на экран
  {
      cout << it->first << " : " << it->second << endl;
  }
  multimap <char,int> myFirstMultimap;///объявили multimap

  ///заполняем myFirstMultimap
  myFirstMultimap.insert ( pair<char,int>('a',10) );
  myFirstMultimap.insert ( pair<char,int>('a',20) );
  myFirstMultimap.insert ( pair<char,int>('a',10) );

  cout << "myFirstMultimap contains:\n";
  for (auto it = myFirstMultimap.begin(); it != myFirstMultimap.end(); ++it)///вывод на экран
  {
     cout << it->first << " : "<< it->second << endl;
  }
  return 0;
}

Пример выполнения программы:

CppStudio.com
myFirstMap contains:
a : 10
myFirstMultimap contains:
a : 10
a : 20
a : 10

Работа программы должна быть полностью понятна, так, что на ней останавливаться не будем. Как видите контейнер myFirstMap может содержать только одно не повторяющееся значение <char, int>, а multimap нет. С этой целью и был создан контейнер multimap. Multimap ничем не отличается от map, за исключением того, что в нем можно хранить повторяющиеся элементы. Думаю, для начала достаточно.

Автор: Marienko L.
Дата: 16.02.2014
Поделиться:

Комментарии

  1. TonyVCLCSA .

    Не желает со string работать.

    error C2679: бинарный «<<«: не найден оператор, принимающий правый операнд типа «const std::string» (или приемлемое преобразование отсутствует)

    с типами char и int все работает.

  2. npavelFax

    Официальная работа в интернете

  3. Vitaliy Sobol

    Add -std=c++11 to your compiler flags (with gcc/icc/clang) if you want to use auto (and other C++11 features)…from-> http://stackoverflow.com/questions/22880431/iterate-through-unordered-map-c

  4. NaikoN

    eagle_vik Не могу ответить на Ваш вопрос, т.к. не использую MVS2012 Ultimate Edition.

    • eagle_vik

      eagle_vik

      Серёжа а что используешь?? Code::Blocks? Я поставил уже себе Visual Studio 2013 Express, и всё работает отлично, видимо в 2012-й студии не полностью реализован стандарт был!!! Уже всё пашет!

      • NaikoN

        eagle_vik, да я использую Сode::blocks :)

  5. eagle_vik

    eagle_vik

    Первый пример не работает!!! (MVS2012 Ultimate Edition)
    Порылся на форумах, написано что даже со стандартом С++11 необходимо каждый раз инициализировать через insert!!!
    вот как у меня получилось:

    //	map_main.cpp
    //
    
    #include <iostream>
    #include <map>
    #include <string>
    
    using std::endl;
    using std::cout;
    using std::map;
    using std::pair;
    using std::string;
    
    int main()
    {
    	map<string, int> myFirstMap;
    	myFirstMap.insert(pair<string, int>("Mother", 37));
    	myFirstMap.insert(pair<string, int>("Father", 40));		//	map явно инициализирована
    	myFirstMap.insert(pair<string, int>("Brother", 15) );
    	myFirstMap.insert( pair<string, int>("Sister", 20));
    
    	//	вывод явно инициализированой map на экран
    	for(auto it = myFirstMap.begin(); it != myFirstMap.end(); ++it)
    	{
    		cout << it->first << " : " << it->second << endl;
    	}
    
    	map<char, int> mySecondMap;
    	for(int i(0), c('a'); i < 5; ++i, ++c)
    	{
    		mySecondMap.insert(pair<char, int>(c, i));
    	}
    	//	вывод неявно инициализированой map на экран
    	for(auto it = mySecondMap.begin(); it != mySecondMap.end(); ++it)
    	{
    		cout << (*it).first << " : " << (*it).second << endl; 
    	}
    	
    	return 0;
    }
    
    
    
    • eagle_vik

      eagle_vik

      писало error: Ошибка  C2552: инициализация не агрегированных данных с помощью списка инициализации не допускается…

      так вот

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.