我正在努力弄清楚如何将此文件读入地图。我开始将文件读入矢量。然后尝试在向量中获取字符串值并将其插入到地图中。我完全迷失了。
第一个值是键,有序对是值。我需要添加"无限数量的值"
1 2,1 8,2
2 1,1 3,1
3 2,1 4,1
4 3,1 5,1
5 4,1 6,1
6 5,1 7,1
7 6,1 8,1
8 7,1 1,2
当前阅读代码:
int main(int argc, char const *argv[]){
map<int, string> map;
vector<string> v;
vector<int> v2;
string line;
string fileName(argv[1]);
ifstream inputFile;
inputFile.open(fileName);
while(getline(inputFile, line)){
v.push_back(line);
}
return 0;
}
答案 0 :(得分:1)
你指定每行上的初始值是一个连续的键,每行的剩余值由空格分隔的tupled组成,每个元组是由逗号分隔的两个值,第一个值是其他值标识符,因此同一行上所有元组的第一个值将是唯一的。
因此,我建议采用以下数据结构:
typedef std::vector<std::map<int, int>> map_t;
矢量索引将是初始密钥。您的矢量索引是基于0的,并且在您的数据文件中它们是基于1的,但这很简单,可以动态处理。更改数据文件,或者只使用没有数据的密钥0继续。
向量中的每个值都是一个映射。地图的关键是“其他节点”ID,值是到另一个节点的距离 - 根据您对此数据的含义的描述。
此数据结构将很好地模拟此数据。现在,就读取和解析这些数据而言:
您的初始方法是正确的:使用std::getline()
一次将每行读入字符串:
map_t my_map;
std::string line;
while (std::getline(inputFile, line)) {
// Here be dragons
}
首先,将每个line
放入字符串向量中没有任何好处。我们可以在阅读时简单地解析每一行。在循环内部,我们将处理每行读取,并将其数据直接放入my_map
。那就是计划。简单,容易,直接。
在循环内部,我们首先将每一行放入std::istringstream
,以便解析它,然后提取初始节点id:
int node_id;
std::istringstream line_stream(line);
line_stream >> node_id;
足够简单。如果您需要处理错误的输入,您应该能够在此处以及其余代码中找出如何检查转换失败的方法。
现在,我们只需要拔出每个“other_node,distance”元组对:
std::string node_distance;
std::map<int, int> node_distance_map;
while (line_stream >> node_distance)
{
// Here be more dragons.
}
就是这样。在循环内部,有更多龙,node_distance
将是每个单独的“n,n”字符串,具有两个值。这很简单,你可以自己弄清楚:如何自己从这个字符串中提取这两个整数;然后更新node_distance_map
。然后,在此while_loop
之后,您先获取构建的node_distance_map
和node_id
提取,然后将整个内容填入my_map
。任务完成。那似乎并不是很困难,是吗?
答案 1 :(得分:0)
检查此解决方案,这不是最好的解决方案,但它实现了目标:
map<int, vector<pair<int, int>>> result;
ifstream infile("C:\\Users\\Mohamed\\Desktop\\test.txt");
string line;
while (getline(infile, line)) {
istringstream iss(line);
vector<string> tokens{istream_iterator<string>{iss},
istream_iterator<string>{}};
if(tokens.size() == 0) continue; // Workaround
int pair1FirstValue, pair1SecondValue, pair2FirstValue, pair2SecondValue;
string pair1 = tokens.at(1);
string pair2 = tokens.at(2);
sscanf(pair1.c_str(), "%d,%d", &pair1FirstValue, &pair1SecondValue);
sscanf(pair2.c_str(), "%d,%d", &pair2FirstValue, &pair2SecondValue);
vector<pair<int,int>> valueVector { make_pair(pair1FirstValue, pair1SecondValue), make_pair(pair2FirstValue, pair2SecondValue) };
result.insert(make_pair(stoi(tokens.at(0)), valueVector));
}
cout << "Printing the map: " << endl;
for(auto it = result.begin(); it != result.end(); it++) {
cout << it->first << " "
<< it->second.at(0).first << " " << it->second.at(0).second << " "
<< it->second.at(1).first << " " << it->second.at(1).second << endl;
}
为了构建代码,您需要包含以下头文件:
#include <iostream>
#include <sstream>
#include <fstream>
尝试理解代码,并修复变通方法,祝你好运。
答案 2 :(得分:0)
这是一个简单的阅读示例。它绝不是最佳选择,但应该易于阅读,理解,调试并启动OP。如果文件读取是处理时间的重要因素,请考虑使用类似状态机的东西。
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
int main(int argc, char const *argv[])
{
std::vector<std::map<int, int>>adjacencies;
std::string line;
if (argc >=2 ) // no argv[1] if argc < 2
{
std::ifstream inputFile(argv[1]);
while(getline(inputFile, line)) // get a line until no more lines
{
std::map<int,int> temp; // holder for adjacent nodes as we find them
std::stringstream ss(line); // stream to ease parsing of nodes from line
std::string node;
while (ss >> node) // get adjacent node on this line until end of line
{
std::stringstream ss2(node); //stream to ease taking nodes apart
int key;
char comma;
int weight;
if (ss2 >> key >> comma >> weight) // take apart node
{
temp[key] = weight; // put adjacent node in list
}
else
{
std::cerr << "File is bogus. Bailing\n";
return -1;
}
}
adjacencies.push_back(temp); // put node and all adjacencies in list
}
try
{
auto weight_of_15_8 = adjacencies[15-1].at(8);
//-1 because origin 0 indexing
}
catch(std::out_of_range &)
{
std::cerr << "node 15 is not adjacent to 8\n";
}
return 0;
}
else
{
std::cerr << "Usage <prog name here> <filename here>\n";
return -2;
}
}
异常特别愚蠢,但如果某个密钥不在map
中,map
将创建并默认初始化该值,如果您使用[]
。您不希望列表中包含邻接零节点,因此最好尽早将该错误压缩。