Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 48

Конвертирование из vector<string> в map

24.01.2016, 23:43. Показов 3576. Ответов 14

Студворк — интернет-сервис помощи студентам
Здравствуйте! Подскажите, пожалуйста, как из vector<string> считать элементы вектора в map.
Изначально дан текстовый файл, в котором записано следующее:
"Objects:
1 a
2 b
3 c
Nodes:"

Все строчки файла записаны в vector<string>. Необходимо "1 a 2 b 3 c" занести поочередно в map, дойдя до слова "Nodes" прекратить. Вот моя реализация, программа компилируется, но как я понимаю, в алгоритме ошибка, т.к. на консоль ничего не выводится.

C++
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
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <fstream>
#include <map>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <istream>
#include <string>
using namespace std;
 
int main()
{
    map<int,string> mymap;
    ifstream f("example.txt");
    string line;
    vector<string> lines;
    while (!f.eof())
    {
        while(getline(f,line))
        {
            lines.push_back(line);
        }
    }
for(vector<string>::iterator it = lines.begin(); it != lines.end(); ++it)
    {
        string tmpstr;
        while((*it)!= "Nodes:")
        {
            if((*it)!="Objects:")
            {
                int num;
                while((*it) != " ")// проверка на пробел 
                {
                      tmpstr+=(*it); //1
                      *it++;// пробел
            }
                      num = stoi(tmpstr);// эта строчка должна конвертировать 1 в int, но меня это смущает
                      tmpstr="";
                      *it++;
                      while((*it)!=" ")
                {
                      tmpstr+=(*it);
                      *it++;
            }
                      if(tmpstr!="")
                          mymap[num] = tmpstr; // как мне кажется, проблема в этой строчке
            }
 
        }
    }
    for(map<int, string>::iterator it = mymap.begin(); it != coll.end(); ++it)
    {
        cout << (*it).first << (*it).second << endl;
    }
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.01.2016, 23:43
Ответы с готовыми решениями:

Доступ к паре в map<string, vector<pair<string, string>>>Temp
Подскажите пожалуйста как получить данные в векторе пар ? void showData(const map&lt;string, vector&lt;pair&lt;string,...

Как перебрать все элементы в map<string, vector<string>>
Доброго времени суток. Решаю следующую задачу: В файле есть сведения об автомобилях: марка автомобиля, номер и фамилия владельца. ...

Вывод элементов map <string,vector<string>>
Доброго времени суток. Как можно вывести массив map &lt;string,vector&lt;string&gt;&gt; mp ? Могу только предположить, что нужно как-то...

14
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
25.01.2016, 00:10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    ifstream f("example.txt");
    if (!f)
    {
        cout << "Error!" << endl;
        system("pause");
        return 0;
    }
 
    map<int, string> mymap;
    int num;
    string tmpstr;
    f.ignore(255, '\n'); // пропускаем первую строку
    while (f >> num >> tmpstr) // на Nodes поток сломается и будет выход из чтения
    {
        mymap[num] = tmpstr;
    }
   
    for(map<int, string>::iterator it = mymap.begin(); it != mymap.end(); ++it)
    {
        cout << (*it).first << ' ' << (*it).second << endl;
    }
1
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 48
25.01.2016, 00:25  [ТС]
nord_v, спасибо) Правда, мне нужно именно из вектора брать эти данные и записывать в map, ">>" меня не спасёт)
0
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
25.01.2016, 00:41
Цитата Сообщение от oooooowl Посмотреть сообщение
Правда, мне нужно именно из вектора брать эти данные и записывать в map
Так ли уж нужно? В чём смысл именно из вектора?
C++
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
    ifstream f("example.txt");
    if (!f)
    {
        cout << "Error!" << endl;
        system("pause");
        return 0;
    }
 
    map<int, string> mymap;
    vector <string> vstr;
    int num;
    string tmpstr;
    while (getline(f, tmpstr))
        vstr.push_back(tmpstr);
    
    stringstream ss;
    for (int i = 0; i < vstr.size(); ++i)
    {
        if (vstr[i] != "Objects:" && vstr[i] != "Nodes:")
        {
            ss << vstr[i];
            ss >> num >> tmpstr;
            ss.clear();
            ss.str("");
            mymap[num] = tmpstr;
        }
    }
    
    for(map<int, string>::iterator it = mymap.begin(); it != mymap.end(); ++it)
    {
        cout << (*it).first << ' ' << (*it).second << endl;
    }
0
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 48
25.01.2016, 00:54  [ТС]
nord_v, в текстовом файле будут также храниться связи (nodes) и правило "rule", как я писала до этого и это будет выглядеть примерно так:
"Objects:
0 a/c
1 HB/a
2 b/c
3 AH/b
4 a^2
5 c*HB
6 b^2
7 c*AH
8 a^2 + b^2
9 c*(HB+AH)
10 c^2
Nodes:
0 = 1
2 = 3
4 = 5
6 = 7
8 = 9
9 = 10
Rule:
IF 8 = 9 THEN 8 = 10"

Соответственно, легче (как мне кажется) сразу помещать файл построчно в вектор, а потом уже из него по очереди вычленять объекты, связи и правило. То есть, чтение из файла не будет прекращаться на nodes, так как эти nodes нам пригодятся потом для установления связей и правил.
Может, конечно, легче по очереди считать все в map, а потом в vector<string>, но я не совсем понимаю, как это осуществить при парсинге файла.

Добавлено через 12 минут
nord_v, извините, не увидела сразу код
ругается на stringstream ss:
ошибка: aggregate 'std::stringstream s' has incomplete type and cannot be defined
stringstream s;
^
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.01.2016, 01:11
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

http://rextester.com/IHDDE45044

C++
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// --- закомментируйте эту строчку для релиза
#define DEBUG
 
 
// ========================================================================================
// ===================================== trim =============================================
 
// обрезает пробельные символы в начале и в конце строки
 
// TODO:
// функции ltrim и rtrim
// работают без учета локали
// по хорошему это нужно исправить
 
#include <algorithm>
#include<functional>
#include <cctype>
#include <locale>
 
// удаляет пробелы слева от текста
inline std::string& ltrim(std::string& s)
{
    s.erase(s.begin(),  
        std::find_if(s.begin(), s.end(), std::ptr_fun<int, int>(std::isgraph))
    );
    return s;
}
 
// удаляет пробелы справа от текста
inline std::string& rtrim(std::string& s)
{
    s.erase(
        std::find_if(s.rbegin(), s.rend(), std::ptr_fun<int, int>(std::isgraph)).base(), 
        s.end() 
    );
    return s;
}
 
// удаляет пробелы слева и справа от текста
inline std::string& trim(std::string& s) { return ltrim(rtrim(s)); }
 
// удаляет все пробельные символы из строки
inline std::string& remove_spc(std::string& s) 
{ 
    const auto lambda = [](const char ch)
    {
        static std::locale loc("");
        return std::isspace(ch, loc);
    };
    s.erase(
        std::remove_if(s.begin(), s.end(), lambda),
        s.end()
    );
    return s;
}
 
// ========================================================================================
// ========================================================================================
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
 
#ifdef DEBUG
    #define dENDL "\n"
#else
    #include <fstream>
#endif
 
// функция получает на входе список слов
// а на выходе дает map
std::map<int, std::string> to_map(const std::vector<std::string>& src);
 
 
// функция вернет true,
// если value совпадает с etalon
// при этом пробельные символы не учитываются
bool is_section(const std::string& etalon, const std::string& value);
 
 
int main()
{
 
#ifdef DEBUG
    // --- на этапе разработки 
    // будем брать исходные данные прямо из исходника
    // (так удобнее)
    const std::string content =
        "Objects: " dENDL
        "1 a"       dENDL
        "2 b"       dENDL
        "3 c"       dENDL
        "Nodes : "  dENDL;
 
    std::stringstream f(content);
#else
 
    // в релизе грузим данные с диска
    std::ifstream f("example.txt");
#endif
 
    // --- перегружаем данные из файла в контейнер строк
    // примечание: std::vector не самый лучший выбор для этой цели
    // лучше было бы использовать std::list
 
    std::vector<std::string>   
        lines;
 
    { // --- ограничиваем область видимости переменной line
        std::string line;
        while (std::getline(f, line))
            lines.push_back(line);
    }
 
#ifdef DEBUG
    // на этапе разработки
    // покажем содержимое файла
    // который нужно распарсить
    std::cout << "content of file:\n";
    for (const auto& s : lines)
        std::cout << "line: '" << s << "'\n";
    std::cout << '\n' << std::endl;
#endif
 
    // --- теперь на базе загруженных строк
    // по нашим правилам
    // формируем std::map
    const auto mymap = to_map(lines);
 
    // --- покажем результат работы
    std::cout << "map:\n";
    for (const auto& pair_ : mymap)
        std::cout << "key = '" << pair_.first 
        << " : value = '" << pair_.second << "'\n";
 
}
 
// ========================================================================================
// ========================================================================================
 
bool is_section(const std::string& etalon, const std::string& value)
{
    auto check = value;
    remove_spc(check);
    return check == etalon;
}
 
// ========================================================================================
// ========================================================================================
 
std::map<int, std::string> 
to_map(const std::vector<std::string>& src)
{
    std::map < int, std::string >
        result;
 
    for (const auto& line : src)
    {
        // --- сначала удаляем лишние пробелы
        auto cur = line;
        trim(cur);
 
        if (is_section("Nodes:", cur))
            break;
        if (is_section("Objects:", cur))
            continue; 
 
        // --- извлекаем ключ и значение:
        std::stringstream ss(cur);
        std::string key, value;
        ss >> key >> value;
        result[ std::stoi(key) ] = value;
 
        // TODO: по хорошему нужно добавить проверки:
        // проверка случая, когда такой ключ уже существует
        // проверить, что ss не поломался
    }
    return result;
}
2
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 48
25.01.2016, 10:34  [ТС]
hoggy, спасибо большое! Нас, правда, ругают за использование констант типа
Цитата Сообщение от hoggy Посмотреть сообщение
const std::string content = "Objects: " dENDL "1 a" dENDL "2 b" dENDL "3 c" dENDL "Nodes : " dENDL;
да и вообще за константы ругают, но не думаю, что это главное.
Почему на Ваш взгляд list удобнее?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.01.2016, 19:18
Цитата Сообщение от oooooowl Посмотреть сообщение
Почему на Ваш взгляд list удобнее?
потому что вам заранее не известно количество строк,
которое попадет в вектор.
зато емкость вектора ограничена, и когда резерв исчерпается,
вектор начнет искать новый кусок памяти,
и копировать туда все свои элементы.

вот и получается, что он будет туда-сюда копировать строки.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
25.01.2016, 20:32
Цитата Сообщение от oooooowl Посмотреть сообщение
да и вообще за константы ругают
И что говорят? Чем обосновывают?
Цитата Сообщение от hoggy Посмотреть сообщение
вот и получается, что он будет туда-сюда копировать строки.
али перемещать, при возможности.
0
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
25.01.2016, 20:59
Цитата Сообщение от hoggy Посмотреть сообщение
потому что вам заранее не известно количество строк,
которое попадет в вектор.
Известно там всё:
Цитата Сообщение от oooooowl Посмотреть сообщение
в текстовом файле будут также храниться связи (nodes) и правило "rule", как я писала до этого и это будет выглядеть примерно так:
"Objects:
0 a/c
1 HB/a
2 b/c
3 AH/b
4 a^2
5 c*HB
6 b^2
7 c*AH
8 a^2 + b^2
9 c*(HB+AH)
10 c^2
Nodes:
0 = 1
2 = 3
4 = 5
6 = 7
8 = 9
9 = 10
Rule:
IF 8 = 9 THEN 8 = 10"
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.01.2016, 22:05
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от Croessmah Посмотреть сообщение
али перемещать, при возможности.
ага. при возможности.
http://rextester.com/SQEXU69463


C++
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
//-------------------------------------------------------------------------        
//---------- кросс-платформенный макрос отображения имени функции ---------
//-------------------------------------------------------------------------        
 
#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #define dFUNCTION __PRETTY_FUNCTION__
#else
    #ifdef _MSC_VER
        #define dFUNCTION __FUNCSIG__
    #else
        #define dFUNCTION __FUNCTION__
    #endif
#endif
 
//-------------------------------------------------------------------------         
//-------------------------------------------------------------------------        
//-------------------------------------------------------------------------        
 
#include <vector>
#include <iostream>
 
struct sample
{
    sample()              { std::cout << dFUNCTION << std::endl; } 
    sample(const sample&) { std::cout << dFUNCTION << std::endl; } 
    sample(sample&&)      { std::cout << dFUNCTION << std::endl; } 
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    std::vector<sample> vec;
    
    for(size_t n=0; n<10; ++n)
        vec.push_back( std::move(sample()) );
}
1
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
25.01.2016, 22:07
Цитата Сообщение от hoggy Посмотреть сообщение
при возможности.
noexcept забыли
C++
1
sample(sample&&)noexcept      { std::cout << dFUNCTION << std::endl; }
http://rextester.com/SOEJ22589
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.01.2016, 22:07
Цитата Сообщение от nord_v Посмотреть сообщение
Известно там всё:
хотите сказать, что "Objects:" всегда будет ровно 10 штук?
а "Nodes:" - ровно 9?
0
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
25.01.2016, 22:10
Цитата Сообщение от hoggy Посмотреть сообщение
хотите сказать, что "Objects:" всегда будет ровно 10 штук?
а "Nodes:" - ровно 9?
Точно так. А если будут и другие цифры, то они тоже будут заранее известны, так что память можно зарезервировать. Файл тут, вообще, для красоты.
Тему почитай, что она делает: Доступ по итератору к элементу вектора
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
25.01.2016, 22:16
Цитата Сообщение от Croessmah Посмотреть сообщение
И что говорят? Чем обосновывают?
Ну, здесь наверно макросы имеются в виду. В плюсах их не рекомендуют.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.01.2016, 22:16
Помогаю со студенческими работами здесь

Словарь map<string, vector<int> (n)>
Нужно, чтобы при объявлении ключа в словаре создавался vector&lt;int&gt; из n элементов Грубо говоря int n; cin &gt;&gt; n; ...

Как вставить элемент и вывести элементы на экран в map<string, map<string,int>> ?
У меня есть map&lt;string, map&lt;string,int&gt;&gt;, в него надо добавить элементы (типа Ivanov potato 200) Использовать именно map&lt;string,...

Не могу вставить элемент в second(vector) мультимапа. multimap<string, vector<string>>
#include &lt;iostream&gt; #include &lt;map&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; #include &lt;string&gt; #include &lt;iterator&gt; int main() ...

Обращение к элементам vector, который находится в map, находящийся в map
Всем добрый день! Имеется такой контейнер. Как обращаться к элементам вектора и как пушбэчить его? map...

Запись значения в map<string, map<string,string>>
Как корректно записать значение в map&lt;string, map&lt;string,string&gt;&gt;? Добавлено через 27 минут Забыл добавить. Не создавая кучу других...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru