1

I'm working with a custom vector, and currently the code looks like this:

struct Edge {
    int source, dest, weight;
};

int main()
{
    // initialize edges as per the above diagram
    // (u, v, w) represent edge from vertex `u` to vertex `v` having weight `w`
    vector<Edge> edges =
    {
        {0, 1, 10}, {0, 4, 3}, {1, 2, 2}, {1, 4, 4}, {2, 3, 9},
        {3, 2, 7}, {4, 1, 1}, {4, 2, 8}, {4, 3, 2}
    };
 
    // total number of nodes in the graph (labelled from 0 to 4)
    int n = 5;
 
    // construct graph
    Graph graph(edges, n);
}

I want to change from using hard-coded values into using a .txt file that will look like this:

0 1 2
0 2 3
0 3 3
1 2 4

How can I switch into taking those numbers in the same fashion as before, but with a .txt input instead of hard-coded numbers?

I've tried things like this:

std::vector<std::string> vecOfStr;
bool result = getFileContent("my/path/to/file", vecOfStr);
    
std::vector<int> ints;
std::transform(vecOfStr.begin(), vecOfStr.end(), std::back_inserter(edges),
    [&](std::string s) {
        std::stringstream ss(s);
        int i;
        ss >> i;
        return i;
    });
 
for (auto &i: edges) {
    //std::cout << i << ' ';
}

But didn't succeed.

I have a problem because reading from a file is always as strings and I somehow need to transform each line to my custom struct.

Offtopic: BTW, it's a Dijkstra algorithm path finding program, finding path for each vertice...

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    An idea: Perhaps break this up into pieces. Implement `operator>>` for `std::istream` in [the canonical way](https://stackoverflow.com/a/4421719/364696), with the reading perhaps reading a single line from the provided `std::istream`, putting it in a `std::stringstream`, and then extracting the three `int`s from that (you could extract the three `int`s directly, but that has issues with handling invalid data; not fun when you leave the stream out of sync). Test that functionality alone to read a single `Edge` at a time. Once that's working, reading from a whole file is relatively easy. – ShadowRanger Jun 08 '22 at 19:10
  • "*And didn't succeed*" avoid generic phrases like this, instead try to describe what you actually tried (you have a `vector` of `Edge`, not `int`) and the problem you encountered. – MatG Jun 08 '22 at 19:14
  • @ShadowRanger Thank you shadow ranger, you've given me an idea on how to approach the problem and I managed to get it working. I am very thankful. – Patryk Piwowarczyk Jun 08 '22 at 19:30

2 Answers2

0

I am sorry for how this question was stated. I agree it wasn't well paraphrased. Anyways... I managed to do the job by adding this code:

void readInstance(string filename, Instance &instance){
    instance.instanceName = filename;
    ifstream file(filename);
    
    if (file.is_open()) {
        string line;
        int i = 0;
        
        while (getline(file, line)) {
            if(i == 0){
                instance.n = stoi(line);
            }
            else{
                istringstream ss(line);
                string aux1, aux2, aux3;
                ss >> aux1;
                ss >> aux2;
                ss >> aux3;
                Edge p;
                p.source = stod(aux1);
                p.dest = stod(aux2);
                p.weight = stod(aux3);
                instance.Edges.push_back(p);
            }
            
            i++;
        }
        
        file.close();
    }
    else {
        cout << "Error opening instance file" << endl;
        exit(1);
    }
}
  • Using streams I was able to break it into pieces and get each thing that I needed from the file and then use it in my program. I am leaving this question for future ppl and closing the thread. – Patryk Piwowarczyk Jun 08 '22 at 19:31
0

Assuming that you have input in the following format in the text file

0 1 2
0 2 3
0 3 3
1 2 4

You can use the following code to read integers directly into the vector. No need to use std::transform to convert string into integer.

#include <iostream>
#include <vector>
#include <fstream>

struct Edge {
    int source, dest, weight;
};

std::ostream& operator<<(std::ostream& os, const Edge edge) {
    os << "(" << edge.source << ", " << edge.dest << ", " << edge.weight << ")\n";
    return os;
}

int main()
{
    // initialize edges as per the above diagram
    // (u, v, w) represent edge from vertex `u` to vertex `v` having weight `w`
    std::vector<Edge> edges;

    std::ifstream fin("in.txt");

    if (!fin.is_open()) {
        std::cerr << "fail";
        return 1;
    }

    int s, d, w;
    while (fin >> s >> d >> w) {
        edges.emplace_back(Edge{s, d, w});
    }
    fin.close();

    for (auto &edge: edges) {
        std::cout << edge;
    }

    return 0;
}

Aamir
  • 1,974
  • 1
  • 14
  • 18