繁体   English   中英

使用 C++ 解析文本文件

[英]Parsing through text file with C++

我试图找出从文本文件中读取数字并将这些数字设置为变量的最佳方法。 我遇到了麻烦,因为将有多个文本文件将测试我的代码,它们的长度和大小都不同。 示例测试如下所示:

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

其中第一个数字表示图上的一个顶点,坐标中的第一个数字是它在有向图中走向的顶点,第二个数字是边的权重。 我尝试做 getline 并将其放入数组中,但在某些测试用例中可能有 100 个坐标,我不确定如何指定数组大小。 我也无法通过括号和逗号进行解析,并且不确定如何使用文本文件中的正确数字初始化变量。

解析不应该那么困难,尤其是当您可以使用std::stringstream将所有元素与输入分开时。 实际上,您想先删除所有括号,然后将元素放入容器中。

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

请注意,您需要 C++17 来编译代码。 如果您使用较旧的 C++ 标准,则必须使用基本循环而不是ranged-for loops并省略auto 我也使用了一个向量对,但如果你对节点使用结构/类会更好,以使代码更易于维护。

我会使用这样的东西:

#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... 
    }
}

这也有效。

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

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM