[英]Read text file containing 2D matrix and associated data
我有一个结构如下的文本文件:
6
0,2,0,0,5,0
3,0,4,0,0,0
0,0,0,6,1,0
0,0,0,0,2,0
0,0,0,0,2,4
1,0,0,0,0,0
0,5
第一个数字表示顶点数,二维矩阵是邻接矩阵。 最后一行包含起点和终点。 我了解如何使用数据及其用途; 我正在苦苦挣扎的是正确读取数据,以便我可以处理它。 我目前有这个:
void directedGraphAnalysis() {
//Open file, read contents, write to graph
ifstream file("test2a.txt");
string data = ""; //Each line will be read as a string and converted to an int
int nodeCount = 0;
int* matrix = nullptr;
int matrixIndex = 0;
int count = 0;
int v1 = INT_MAX;
int v2 = INT_MAX;
while (getline(file, data, ',')){
int x = stoi(data);
++count;
if (count == 1) {
nodeCount = x;
matrix = new int[nodeCount * nodeCount];
}
else if (count < (nodeCount * nodeCount) - 1) {
matrix[matrixIndex++] = x;
}
else if (v1 == INT_MAX) {
v1 = x;
}
else {
v2 = x;
}
cout << "X: " << x << endl;
}
//DirectedGraph graph = DirectedGraph(matrix, nodeCount);
//graph.displayGraph();
cout << "ANALYSIS COMPLETE." << endl;
}
此实现似乎使节点数正确,但之后的每一行都会跳过第一个数字,这意味着 v1 和 v2 从未设置,并且矩阵具有与文本文件不匹配的不正确边。 Matrix 只是一个一维数组,表示大小为 nodeCount * nodeCount 的二维矩阵。 我不确定我在做什么导致矩阵填充不当,我也不知道为什么要跳过第一个数字。
因为std::getline
只接受单个字符作为分隔符。 如果使用,
作为分隔符,则NEW LINE(0x0D, 0x0A)
是正常字符。
例如,在第一个,
字符之前, std::getline
读取:
6
0
并将其转换为
6
那么下一行的第一位数字丢失了。
我尝试修复逻辑如下:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
void directedGraphAnalysis() {
//Open file, read contents, write to graph
ifstream file("test2a.txt");
string data = ""; //Each line will be read as a string and converted to an int
string line = "";
int nodeCount = 0;
int* matrix = nullptr;
int matrixIndex = 0;
int count = 0;
int v1 = INT_MAX;
int v2 = INT_MAX;
while (getline(file, line)){
stringstream stream(line);
while (getline(stream, data, ',')){
int x = stoi(data);
++count;
if (count == 1) {
nodeCount = x;
matrix = new int[nodeCount * nodeCount];
}
else if (count < (nodeCount * nodeCount) - 1) {
matrix[matrixIndex++] = x;
}
else if (v1 == INT_MAX) {
v1 = x;
}
else {
v2 = x;
}
cout << "X: " << x << endl;
}
}
//DirectedGraph graph = DirectedGraph(matrix, nodeCount);
//graph.displayGraph();
cout << "ANALYSIS COMPLETE." << endl;
}
int main()
{
directedGraphAnalysis();
}
您需要分析您的源文件,然后根据需要进行输入操作。
邻接矩阵似乎适用于有向和加权图。 我不清楚它是面向行还是面向列,但这对于 reding 操作并不重要。
那么,我们会看到吗?
根据这些观察,我们将决定如何阅读。
第一行可以简单地读取,使用标准格式的输入函数,使用提取操作符>>. Formatted input
>>. Formatted input
将始终尝试转换输入数据,直到看到空格(包括换行符 '\\n')。 它不会消耗空白,所以 '\\n')。
可以使用std::getline
(未格式化输入)函数将下一行写为整行。 但请注意。 std::getline
将读取,直到找到换行符 '\\n'。 请记住,输入流中仍然有一个换行符。 因此,如果您只是调用std::getline
,它将读取一个空字符串,然后使用换行符。 为了解决这个问题,我们可以简单地使用std::ws函数。 这将消耗但不会读取文本前面的所有空白。 所以,我们总是可以这样写: std::getline(file >> std::ws, data);
这将首先调用file >> std::ws
然后调用std::getline
。
好了,这个理论现在应该清楚了。
然后,我们需要创建一个二维数组。 您只是在创建一个一维数组。 这可以通过首先为行创建一个数组,然后为每一行创建额外的列数组来完成。 这我们可以像下面这样:
// allocate memory for rows
int** matrix = new int* [dimension];
// For each row, allocate memory for the columns
for(unsigned int row=0; row < dimension; ++row)
matrix[row] = new int [dimension];
现在我们有一个二维数组,我们可以用matrix[row][col];
接下来,因为我们知道维度,我们可以创建一个循环并调用std::getline
维度次。
读完一行后,我们需要拆分该行并存储值。 为此,我们将使用一种常用方法,即使用std::istringstream
和std::getline
直到看到逗号。
最后,我们读取最后一行并以相同的方式提取开始坐标。
对于每个读取操作,都应添加错误检查。
然后一个示例程序可能如下所示。
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main() {
// Open the file
std::ifstream fileStream{ "r:\\text2a.txt" };
// Check, if we could open the file
if (fileStream) {
// Read the dimension of the matrix and check for valid input
unsigned int dimension{};
if ((fileStream >> dimension) and (dimension > 0)) {
// Now we haveopened the file and read the dimension
// Allocate array. Firs,allocate memory for rows
int** matrix = new int* [dimension];
// And now, for each row, allocate space for columns
// Then read the rows with the column values
for (unsigned int row = 0; row < dimension; ++row) {
matrix[row] = new int[dimension] {};
// Read next line from file
std::string line{};
if (std::getline(fileStream >> std::ws, line)) {
// Put the line into an std::istringstream, so that we can extract the column values
std::istringstream iss(line);
// Extract all columns
for (unsigned int col = 0; col < dimension; ++col) {
std::string valueAsString{};
if (std::getline(iss, valueAsString, ',')) {
matrix[row][col] = std::stoi(valueAsString);
}
else {
// Could not read column value. Show error message
std::cerr << "\n\n*** Error. Could not read value at row " << row << ", column: "<< col << "\n\n";
}
}
}
else {
// Could not read row with column values
std::cerr << "\n\n*** Error. Could not read row number " << row << "\n\n";
}
}
// Now we have read the matrix.
// Get the start point
unsigned int rowStart{}, columnStart{};
char comma{};
if ((fileStream >> rowStart >> comma >> columnStart) and comma == ',') {
// Now, we have all data
// Show some debug output
std::cout << "Adjancency matrix\n\nDimension: " << dimension << "\n\nMatrix:\n\n";
for (unsigned int row = 0; row < dimension; ++row) {
for (unsigned int col = 0; col < dimension; ++col) {
std::cout << matrix[row][col] << ' ';
}
std::cout << '\n';
}
std::cout << "\n\nStart point: " << rowStart << ", " << columnStart << '\n';
// Release all allocated memory
for (unsigned int row = 0; row < dimension; ++row)
delete[] matrix[row];
delete[] matrix;
}
else {
// Could not read start values
std::cerr << "\n\nError: Could not read start values\n\n";
}
}
else {
// Invalid input for dimension of adjacency matrix. Show error message
std::cerr << "\n\n*** Error. Invalid dimentsion found\n\n";
}
}
else {
// File could not be opened. Show error message
std::cerr << "\n\n*** Error. Could not open source file\n\n";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.