我的这个问题是基于我之前提出的问题。
Multi level hash/dictionary creation in C++
我有这个结构,我需要使用indexof函数存储在unordered_map中。我正在使用上一个问题中指定的配置文件。我需要将第一行存储为索引,将后续值存储为该索引下的数组。
到目前为止,我已经能够做到这一点。
#include <cstdlib.h>
#include <stdafx.h>
#include <string.h>
#include <stdio.h>
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std::tr1;
#define false 0
#define true 1
int main()
{
unordered_map <std::string, int> m;
FILE *f;
char c[255];
char * pnt;
f=fopen("Config.csv","r");
if(f==NULL)
return 1;
while(!feof(f))
{
fgets(c, 255, f); //go to the next line
pnt = strtok( c, ",");
while( pnt!= NULL )
{
//the code for storing the values goes here.
pnt = strtok( NULL, "," );
}
}
fclose(f);
return 0;
}
我的CSV文件看起来像这样----
USN,Name,DOB,Sem,Percentage
111,abc,07/03,3,88
112,cde,18/07,4,77
答案 0 :(得分:0)
在我看来,正在使用的正确数据结构是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形式,我会怎么做。