Мне кажется, что правильная структура данных для использования является std::unordered_map<std::string,std::vector<std::string>>
и неunordered_map<std::string,int>
, в качестве тока выполняется попытка реализации. Это потому, что поля, которые вы хотите сохранить, больше похожи на строки; некоторые из них вообще не являются.
Первый шаг - извлечь имена полей, чтобы впоследствии их можно использовать в качестве ключей unordered_map
. Затем начните извлечение строк данных, добавив их в поля. Затем, для каждого имени поля, push_back введите данные поля для данной строки CSV. Вот пример (использует некоторые C++ 11 конструкций):
#include <string>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <sstream>
std::vector<std::string> split (std::string);
int main() {
// Sample data for a self-contained example.
std::vector<std::string> raw_data {
"USN,Name,DOB,Sem,Percentage",
"111,abc,07/03,3,88",
"112,cde,18/07,4,77"
};
// Ordered container for field names, unordered for field vectors.
auto field_names = split(raw_data[0]);
std::unordered_map<std::string,std::vector<std::string>> parsed;
// Store fields as vector elements within our unordered map.
for(auto it = std::begin(raw_data) + 1; it != std::end(raw_data); ++it) {
auto fields = split(*it);
auto field_it = std::begin(fields);
for(auto name_it = std::begin(field_names);
name_it != std::end(field_names);
++name_it,
++field_it
) {
parsed[*name_it].push_back(*field_it);
}
}
// Dump our data structure to verify it's correct;
for(auto fn : field_names) {
std::cout << fn << "\t";
}
std::cout << "\n";
for (size_t ix = 0; ix != parsed[field_names[0]].size(); ++ix) {
for(auto fn : field_names) {
std::cout << parsed[fn][ix] << "\t";
}
std::cout << "\n";
}
std::cout << std::endl;
return 0;
}
std::vector<std::string> split (std::string instring) {
std::vector<std::string> output;
std::istringstream iss(instring);
std::string token;
while(getline(iss, token, ',')) {
output.push_back(token);
}
return output;
}
В моем примере я, начиная с входных данных, содержащихся в векторе имени raw_data
. В вашем случае вы извлекаете данные из файла. Поэтому я имею дело с наращиванием структуры данных, поскольку я исхожу из предположения, что обработка файлов не является основной частью вашего вопроса. Вы должны легко адаптировать токенизацию и наращивание структуры данных из моего примера.
Кроме того, я понимаю, что вы используете tr1 :: unordered_map, что, вероятно, означает, что вы не используете C++ 11. Тем не менее, мои C++ 11-isms на самом деле просто используют синтаксический сахар, который вы можете понизить до эквивалентной совместимости C++ 03 без особых усилий.
Обратите внимание, что это относительно наивный подход к анализу CSV. Он делает предположения, которые могут работать для ваших CSV-данных, но могут не работать для всех форм CSV. Например, он не имеет дело с цитированием полей, чтобы разрешить встроенные запятые в полях. Также он не справляется с пропущенными косой чертой, а также множеством других задач синтаксического анализа CSV.
Если ваш набор данных менее корректен, чем может иметь дело с этим парсером, вам следует искать полноценную библиотеку синтаксического анализа CSV вместо того, чтобы возиться с вашим собственным парсером. ... по крайней мере, это то, что я сделал бы, если бы мне было поручено анализировать менее тривиальные формы CSV.
так в чем ваш вопрос? – Nik
Итак, вам действительно нужно m быть unordered_map>, правильно? –
DavidO
@Nik: Мне нужна помощь в кодировании для хранения значений. так что, когда я хочу напечатать «имя», я получаю «abc, cde». – SauShi