我将如何读取这个文件到一个映射c++

How would i read this file into a map c++

本文关键字:一个 映射 c++ 文件 读取 何读取      更新时间:2023-10-16

我正在努力弄清楚如何将此文件读取为地图。我先把文件读入一个矢量。然后试图取向量中的字符串值并将它插入到map中。我完全迷路了。

第一个值是键,有序对是值。我需要添加"infinite number of values"

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

您指定每行上的初始值是一个连续的键,每行上的其余值由空格分隔的元组组成,每个元组是由逗号分隔的两个值,第一个值是其他标识符,因此同一行上所有元组的第一个值将是唯一的。

因此,我建议使用以下数据结构:
typedef std::vector<std::map<int, int>> map_t;

向量索引将是初始键。您的矢量索引是基于0的,而在数据文件中它们是基于1的,但这很简单,可以在运行中处理。要么更改数据文件,要么继续使用没有数据的键0。

vector中的每个值都是一个map。映射的键是"other node"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"字符串,有两个值。这很简单,你们自己就能弄明白如何从这个字符串中提取这两个int;然后更新node_distance_map。然后,在此while_loop之后,您使用构建的node_distance_map和之前的node_id提取,并将整个内容填充到my_map中。任务完成这似乎并不难,对吧?

检查这个解决方案,它不是最好的解决方案,但它达到了目标:

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>

试着理解代码,并修复工作区,祝你好运。

这是一个简单的阅读示例。它绝不是最优的,但它应该易于阅读、理解、调试和启动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. Bailingn";
                    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 8n";
        }
        return 0;
    }
    else
    {
        std::cerr << "Usage <prog name here> <filename here>n";
        return -2;
    }
}

这个异常特别慢,但是如果一个键不在map中,如果你使用[], map将创建并默认初始化这个值。你不会想要一个满是邻接零节点的列表,所以最好早点消除这个bug。