我有一个Python脚本,它生成一个带有double值的Matrix并将它们保存在这样的txt文件中:
-5.70683 -9.72438 5.62137 -3.52453
-3.70381 7.25433 -4.21905 3.88678
-1.43741 7.39768 -6.84103 -3.45817
-5.66966 3.47989 -5.64204 -6.08512
现在我必须读取C文件中的.txt文件并将其转换为我的结构:
struct Matrix {
int rows;
int columns;
double **matrix;
};
这是我的C档案:
Matrix *readMatrix(const char filename[]) {
Matrix matrix;
FILE * matrix_file;
char * str;
int i, j;
//allocate pointer
matrix.matrix = malloc(4 * sizeof(double *));
for(i = 0; i < 4; i++)
matrix.matrix[i] = malloc(4 * sizeof(double *));
matrix_file = fopen(filename, "r");
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
if (!fscanf(matrix_file, "%lf", &matrix.matrix[i][j]))
break;
printf("%lf\n",matrix.matrix[i][j]);
}
}
fclose(matrix_file);
return &matrix;
}
我没有将它分配给4x4矩阵,而是想分配我的Pointer动态。所以我必须从文件中读出行和列。我怎么能这样做?
答案 0 :(得分:0)
事实证明,我只是写了类似于你问的东西。但是,我用C ++而不是C编写它,尽管大多数逻辑应该是相似的。所以,虽然不是一个完整的答案,但这应该能够引导你一点。
注意:我正在使用方形矩阵,我的文件以逗号分隔(不是空格),第一行包含文件中的行数。最后一点,这是供个人使用(而不是作业或生产代码),因此忽略了大量的错误检查和处理。
因此,值得一提的是,这是代码的缩写版本:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <string.h>
#include <random>
#include <math.h>
inline int makeNdx(int r, int c, int max) { return r*max + c;}
int populateMatrix(double**);
int main(int argc, char** argv)
{
unsigned int nSize;
double* tmatrix = nullptr;
if(0 != (nSize = populateMatrix(&tmatrix)))
{
// the matrix was manipulated here, this code not relevant to
// the answer...
}
if(nullptr != tmatrix) delete [] tmatrix;
return 0;
}
int populateMatrix(double** ppmat)
{
std::string strFileName;
std::string strLine;
std::string token;
unsigned int row = 0;
unsigned int size = 0;
int* pnorms = nullptr;
if(nullptr != *ppmat) delete [] *ppmat;
std::cout << "Enter the name of the data file: ";
std::cin >> strFileName;
std::ifstream infile(strFileName);
// read file and get matrix size...
getline(infile, strLine);
size = atoi(strLine.c_str());
// allocate space for matrix...
*ppmat = new double[size*size];
while(infile.good())
{
getline(infile, strLine);
std::istringstream strStream(strLine);
for(unsigned int col = 0; col < size; col++)
{
if(strStream)
{
getline(strStream, token, ',');
(*ppmat)[makeNdx(row, col, size)] = atoi(token.c_str());
}
}
row++;
}
return size;
}
因此,正如您所看到的,我将矩阵表示为二维的双维数组。因为我希望我的填充矩阵函数能够创建矩阵(即能够修改tmatrix
值)我需要通过引用函数来传递指针,因此我将它作为指针传递给它-a-指针。
请记住,在C(和C ++)中,二维数组是以行主体形式实现的,可以考虑放置第一行的一个大数组,然后是第二行,依此类推。因此,因为我更喜欢用行和列来思考,我有一个实用程序函数将行/列索引转换为适当的索引到一维数组中。
答案 1 :(得分:0)
假设您不知道先验行数和列数并希望从文件中推导出它,一种简单的方法是:
以下是可能代码的示例:
typedef struct _Matrix {
int rows;
int columns;
double ** matrix; // a pointer to an array of pointers is not a pointer to a 2D array!
double *data; // pointer to a 2D array
} Matrix;
#define MAX_LINE_SIZE 256
const char delim[] = " \t";
/*
Find the number of double presents on a line
*/
int getColumns(char *line) {
char *ix;
int cols = 0;
double val;
ix = strtok(line, delim);
for (;;) {
if(ix == NULL) break;
if (sscanf(ix, "%lg", &val) == 1) {
cols +=1;
}
else break;
ix = strtok(NULL, delim);
}
return cols;
}
/*
Parse a line on which strtok has been used to find the number of elements
*/
int parseLine(char * line, int ncols, double *val) {
int i;
for (i=0; i<ncols; i++) {
if (sscanf(line, "%lg", val) != 1) return 0;
line += strlen(line) + 1; /* skip over the null put here by strtok */
val += 1;
}
return 1;
}
/*
Return (by value) a matrix read from an already opened file
The elements data and matrix must be freed by caller if they are not null
rows is 0 if file is empty, -1 if it is incorrect
*/
Matrix readMatrix(FILE *fd) {
char line[MAX_LINE_SIZE];
Matrix matrix;
int maxrows, row = 0;
double *val; /* val will point the the beginning of the next row */
/* initializes the matrix */
matrix.rows = matrix.columns = 0;
matrix.matrix = matrix.data = NULL;
/* process first line to discover the number of columns */
if (NULL == fgets(line, sizeof(line), fd)) return matrix;
matrix.columns = getColumns(line);
maxrows = matrix.columns;
/* allocate the 2D array for data and 1D array of pointers for matrix
(to be able to use matrix.matrix[row][col] instead of
matrix.data[col + row.matrix.columns])
*/
matrix.matrix = malloc(maxrows * sizeof(double *));
val = matrix.data = malloc(maxrows * matrix.columns * sizeof(double));
if (parseLine(line, matrix.columns, val) == 0) {
matrix.rows = -1;
return matrix;
}
/* Ok one row have been read */
matrix.matrix[matrix.rows++] = val;
val += matrix.columns;
/* let's process the other rows */
for(;;) {
int cols;
if (NULL == fgets(line, sizeof(line), fd)) return matrix;
cols = getColumns(line);
if (cols == 0) return matrix; /* empty line denotes also the end of data to allow and empty last line */
if (cols != matrix.columns) {
matrix.rows = -1; /* incorrect number of cols: fatal */
return matrix;
}
if (matrix.rows == maxrows) { /* data is full: reallocate some more room */
int r;
maxrows += matrix.columns;
matrix.matrix = realloc(matrix.matrix, maxrows * sizeof(double *));
matrix.data = realloc(matrix.data, maxrows * matrix.columns * sizeof(double));
for (r=0; r<matrix.rows; r++) { /* ensure that the pointers from matrix actually point in data */
matrix.matrix[r] = matrix.data + r * matrix.columns;
}
val = matrix.data + matrix.rows * matrix.columns; /* ensure val points to the beginning of next row */
}
/* Ok, load the line */
matrix.matrix[matrix.rows++] = val;
if (parseLine(line, matrix.columns, val) == 0) {
matrix.rows = -1;
return matrix;
}
val += matrix.columns;
}
return matrix;
}
应该测试分配错误......