Parsing through text file with C++

拜拜、爱过 提交于 2019-12-12 04:38:02

问题


I am trying to figure out the best way to read in numbers from a text file and set these numbers to variables. I am having trouble because there will be multiple text files that will be testing my code and they are all of different lengths and sizes. A sample test one looks like this:

0 (1,3) (3,5)
1 (2,6)
2 (4,2)
3 (1,1) (2,4) (4,6)
4 (0,3) (2,7)

Where the first number represents a vertex on a graph, the first number in a coordinate is the vertex it is going towards in a directed graph, and the second number is the weight of the edge. I tried doing getline and putting it into arrays but in certain test cases there could be 100 coordinates and I am not sure how to specify array size. I am also having trouble parsing through the parenthesis and comma and am not sure how to initialize the variables with the correct number from the text file.


回答1:


Parsing shouldn't be that difficult, espacially when you can use std::stringstream to separate all the elements from input. Indeed, you want to remove all the paranthesis first then emplace the elements into the container.

#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <cctype>

int main()
{
    std::ifstream read("file.txt");

    std::vector<std::vector<std::pair<int, int>>> graph;

    // read until you reach the end of the file
    for (std::string line; std::getline(read, line); ) {

        // removing punctuation like paranthesis, commas, etc.
        std::replace_if(std::begin(line), std::end(line), [] (char x) { return std::ispunct(x); }, ' ');

        // inserting the line into a stream that helps us parse the content
        std::stringstream ss(line);

        // read the node number
        int source, destination, weight;
        ss >> source;

        // create a new vector for the new node, so you can place all it's destinations / weights in it
        graph.insert(std::next(std::begin(graph), source), {{}});

        // read the dests / weights until you reach the end of the current line
        while (ss >> destination >> weight)
            graph[source].emplace_back(destination, weight);
    }

    read.close();
    std::ofstream write("output.txt");

    for (const auto node : graph) {
        for (const auto [dest, weight] : node)
            write << "(" << dest << ", " << weight << ") ";
        write << '\n';
    }
}

Note that you need C++17 to compile the code. You have to use basic loops instead of ranged-for loops and omit auto if you use an older C++ standard. Also I used a vector of pairs, but it's better if you use a struct / class for nodes, to make the code more maintanable.




回答2:


This works too.

#include<iostream>
#include<sstream>
#include<string>
using namespace std;
int main() {
    int vertices[1000][3], qv = 0;  //use number more than 1000 if it is required
    while (cin) {
        int n;
        char c;
        string s;
        getline(cin, s);
        istringstream is(s);
        is >> n;
        is >> c;
        while (c == '(') {
            vertices[qv][0] = n;
            is >> vertices[qv][1];
            is >> c;   //,
            is >> vertices[qv++][2];
            is >> c;   //)
            is >> c;   //(
        }
    }
    for (int i = 0; i < qv; i++) //unified view
        cout << vertices[i][0] << ' ' << vertices[i][1] << ' ' << vertices[i][2] << endl;
    for (int i = 0; i < qv; i++) {  //initial view
        cout << vertices[i][0];
        cout << " (" << vertices[i][1] << "," << vertices[i][2] << ")";
        while (i + 1 < qv && vertices[i][0] == vertices[i + 1][0]) {
            i++;
            cout << " (" << vertices[i][1] << "," << vertices[i][2] << ")";
    }
    cout << endl;
}

}




回答3:


I would use something like this:

#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <algorithm>

struct coordinate
{
    int vertex;
    int weight;
};

struct vertex_set
{
    int vertex;
    std::vector<coordinate> coordinates;
};

std::istream& operator>>(std::istream &in, coordinate &out)
{
    char ch1, ch2, ch3;
    if (in >> ch1 >> out.to_vertex >> ch2 >> out.weight >> ch3)
    {
        if ((ch1 != '(') || (ch2 != ',') || (ch3 != ')'))
            in.setstate(std::ios_base::failbit);
    }
    return in;
}

std::istream& operator>>(std::istream &in, std::vector<coordinate> &out)
{
    out.clear();
    coordinate coord;
    while (in >> coord)
        out.push_back(coord);
    return in;
}

std::istream& operator>>(std::istream &in, vertex_set &out)
{
    return in >> out.vertex >> out.coordinates;
}

std::ifstream f("file.txt");
std::string line;

while (std::getline(f, line))
{
    vertex_set vs;
    if (std::istringstream(line) >> vs)
    {
        // use vs.vertex and vs.coordinates as needed... 
    }
}


来源:https://stackoverflow.com/questions/46261431/parsing-through-text-file-with-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!