我有一個結構如下的文本檔案:
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,并且矩陣具有與文本檔案不匹配的不正確邊。矩陣只是一個一維陣列,表示大小為 nodeCount * nodeCount 的二維矩陣。我不確定我在做什么導致矩陣填充不正確,我也不知道為什么跳過第一個數字。
uj5u.com熱心網友回復:
因為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();
}
uj5u.com熱心網友回復:
您需要分析您的源檔案,然后根據需要進行輸入操作。
鄰接矩陣似乎適用于有向和加權圖。我不清楚它是面向行還是面向列,但這對于 reding 操作并不重要。
那么,我們會看到嗎?
- 作為無符號整數的維度在其自己的行上
- 它遵循具有上述給定維度的矩形矩陣。行以逗號分隔值的形式給出。這,我們稱之為 CSV。并且,有很多方法可以將 csv 拆分為其組件:因為使用矩陣是二次的,所以會有維度行。
- 最后,我們有和 additionalline,包含 2 個值,起始坐標,用逗號分隔。
根據這些觀察,我們將決定如何閱讀。
第一行可以簡單地讀取,使用標準格式化輸入函式,使用提取器運算子>>. Formatted input將始終嘗試轉換輸入資料,直到看到空格(包括換行符'\n')。它不會消耗空白,所以 '\n')。
可以使用std::getline(未格式化的輸入)函式將下一行寫為整行。但請注意。std::getline將讀取,直到找到換行符 '\n'。請記住,輸入流中仍然有一個換行符。因此,如果您只是呼叫std::getline,它將讀取一個空字串,然后使用換行符。為了解決這個問題,我們可以簡單地使用std::ws函式。這將消耗但不會讀取文本前面的所有空白。所以,我們總是可以這樣寫:std::getline(file >> std::ws, data);This will first call file >> std::wsand then invoke 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::istringstreamandstd::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";
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/362115.html
