2017-09-17 128 views
0

我想弄清楚从文本文件中读取数字并将这些数字设置为变量的最佳方法。我遇到了麻烦,因为会有多个文本文件将测试我的代码,并且它们的长度和大小都不相同。样品测试一个看起来像这样:使用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个坐标,我不知道如何指定数组大小。我也无法解析圆括号和逗号,也不知道如何用文本文件中的正确数字初始化变量。

+1

为什么不使用矢量? –

+0

@RetiredNinja我还没有真正教过什么矢量,但如果这将是一个更简单的解决方案,我会考虑这样做。感谢您的想法 – justinbg10

+0

正如退休忍者所说,使用矢量(实际上可能是矢量矢量)。至于解析,我会读一行,然后使用字符串操作来分隔行中的值。您可以一次读取一个字符,但它需要一个小型状态机来跟踪您所在的解析过程中的哪个位置,这对于像这样的相对简单的解析器来说似乎过分了。 –

回答

0

解析不应该那么困难,特别是当您可以使用std::stringstream来分隔输入中的所有元素时。事实上,你想首先删除所有的paranthesis,然后将元素放入容器中。

#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。此外,我使用了一个对的向量,但如果您使用结构/类作为节点,则会更好,以使代码更加友好。

+0

A)不要给学校项目的完整答案,B)代码几乎不会帮助初学者“还没有std :: vector”了解如何编写代码来解析字符串。 –

0

我会用这样的:

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

这工作了。

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

}