我如何将这个文件读入地图c ++

时间:2016-10-06 00:53:48

标签: c++ dictionary insert maps

我正在努力弄清楚如何将此文件读入地图。我开始将文件读入矢量。然后尝试在向量中获取字符串值并将其插入到地图中。我完全迷失了。

第一个值是键,有序对是值。我需要添加"无限数量的值"

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;
}

3 个答案:

答案 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_mapnode_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将创建并默认初始化该值,如果您使用[]。您不希望列表中包含邻接零节点,因此最好尽早将该错误压缩。