从文本文件

时间:2018-04-18 21:38:20

标签: c multidimensional-array text-files

我正在使用稀疏矩阵并且我给出了这样的文本文件:

0 3 1.2
2 5 3.2
3 0 2.1
3 5 4.2
4 5 2.2
0 0 5.2

基本上它的工作方式是位置[0] [3]上的数字1.2和未提及的matriz的元素保持为0,所以在这种情况下它应该是这样的:

5.2 0 0 1.2 0 0
0 0 0 0 0 0
0 0 0 0 0 3.2
2.1 0 0 0 0 4.2
0 0 0 0 0 2.2

5 个答案:

答案 0 :(得分:3)

OP在评论中写道:

  

我很抱歉,但我的老师刚才澄清了一切......事实证明,对于每一行,第一个数字是行,第二个是列,第三个是元素。我上面的例子是{ {1}}必须进入1.2的位置。矩阵不必是正方形。

这使每件事都与众不同。如果你不知道的尺寸 矩阵,然后你必须先读取所有内容,然后计算矩阵 维度,为矩阵分配空间,然后用值填充它。

我这样做:

[0][3]

输出(对于包含样本数据的文件)

#include <stdio.h>
#include <stdlib.h>

#define BLOCK 1024

struct matrix_info {
    int col;
    int row;
    double val;
};

void free_matrix(double **matrix, size_t rows)
{
    if(matrix == NULL)
        return;

    for(size_t i = 0; i < rows; ++i)
        free(matrix[i]);
    free(matrix);
}

double **readmatrix(const char *fname, size_t *rows, size_t *cols)
{
    if(fname == NULL || rows == NULL || cols == NULL)
        return NULL;

    double **matrix = NULL;
    struct matrix_info *info = NULL;
    size_t mi_idx = 0; // matrix info index
    size_t mi_size = 0;

    FILE *fp = fopen(fname, "r");
    if(fp == NULL)
    {
        fprintf(stderr, "Cannot open %s\n", fname);
        return NULL;
    }

    *rows = 0;
    *cols = 0;

    for(;;)
    {
        if(mi_idx >= mi_size)
        {
            struct matrix_info *tmp = realloc(info, (mi_size + BLOCK) * sizeof *info);
            if(tmp == NULL)
            {
                fprintf(stderr, "not enough memory\n");
                free(info);
                fclose(fp);
                return NULL;
            }

            info = tmp;
            mi_size += BLOCK;
        }

        int ret = fscanf(fp, "%d %d %lf", &info[mi_idx].row, &info[mi_idx].col,
                    &info[mi_idx].val);

        if(ret == EOF)
            break; // end of file reached

        if(ret != 3)
        {
            fprintf(stderr, "Error parsing matrix\n");
            free(info);
            fclose(fp);
            return NULL;
        }

        if(*rows < info[mi_idx].row)
            *rows = info[mi_idx].row;

        if(*cols < info[mi_idx].col)
            *cols = info[mi_idx].col;

        mi_idx++;
    }

    fclose(fp);

    // mi_idx is now the length of info
    // *cols and *rows have the largest index
    // for the matrix, hence the dimension is (rows + 1) x (cols + 1)
    (*cols)++;
    (*rows)++;

    // allocating memory

    matrix = calloc(*rows, sizeof *matrix);
    if(matrix == NULL)
    {
        fprintf(stderr, "Not enough memory\n");
        free(info);
        return NULL;
    }

    for(size_t i = 0; i < *rows; ++i)
    {
        matrix[i] = calloc(*cols, sizeof **matrix);
        if(matrix[i] == NULL)
        {
            fprintf(stderr, "Not enough memory\n");
            free(info);
            free_matrix(matrix, *rows);
            return NULL;
        }
    }

    // populating matrix

    for(size_t i = 0; i < mi_idx; ++i)
    {
        int r,c;
        r = info[i].row;
        c = info[i].col;
        matrix[r][c] = info[i].val;
    }

    free(info);
    return matrix;
}

int main(void)
{
    const char *fn = "/tmp/matrix.txt";

    size_t rows, cols;

    double **matrix = readmatrix(fn, &rows, &cols);

    if(matrix == NULL)
        return 1;

    for(size_t i = 0; i < rows; ++i)
    {
        for(size_t j = 0; j < cols; ++j)
            printf("%0.3f ", matrix[i][j]);

        puts("");
    }

    free_matrix(matrix, rows);
    return 0;
}

快速解释我正在做的事情:

我读取文件并在动态分配的数组中存储信息 关于列,行和值。这些信息存储在 5.200 0.000 0.000 1.200 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 3.200 2.100 0.000 0.000 0.000 0.000 4.200 0.000 0.000 0.000 0.000 0.000 2.200

我的想法是我读取每一行并提取三个值。我读的时候 在文件中,我还存储了列和行的最大索引

struct matrix_info *info

所以当读取文件时,我知道矩阵的尺寸。现在所有价值观 与他们的行&amp;列存储在 ... if(*rows < info[mi_idx].row) *rows = info[mi_idx].row; if(*cols < info[mi_idx].col) *cols = info[mi_idx].col; ... 数组中,因此下一步是 为矩阵分配内存并根据info填充值 条目。

info[i]

最后我释放for(size_t i = 0; i < mi_idx; ++i) { int r,c; r = info[i].row; c = info[i].col; matrix[r][c] = info[i].val; } 的内存并返回矩阵。

另一个有趣的部分是:

info

因为你提到你对矩阵的唯一了解就是它 可能包含多达10000个元素,那么输入文件可能会非常大。 我没有为每个循环上的 if(mi_idx >= mi_size) { struct matrix_info *tmp = realloc(info, (mi_size + BLOCK) * sizeof *info); if(tmp == NULL) { fprintf(stderr, "not enough memory\n"); free(info); fclose(fp); return NULL; } info = tmp; mi_size += BLOCK; } 元素重新分配内存,而是分配 一次有1024个(infoBLOCK个元素的块。因此,一旦一个块满了, 分配下一个块,依此类推。所以我每1024只拨打info 迭代。

答案 1 :(得分:2)

首先需要使用:

'static

您开始阅读该文件,在第一行读取后您知道colums的nomber,行数是读取的行数。如果需要,可以减少矩阵。

float* sparseMatrix = malloc(sizeof(float) * 10000); 

答案 2 :(得分:1)

您根本没有足够的信息来构建合适的矩阵。在您引用的案例中,您知道至少 5行且至少 6列,但您并不确切知道行数mn位于矩阵中。所以对于你的输入:

0 3 1.2
2 5 3.2
3 0 2.1
3 5 4.2
4 5 2.2
0 0 5.2

您可以使用5x6矩阵:

5.2  0.0  0.0  1.2  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  3.2
2.1  0.0  0.0  0.0  0.0  4.2
0.0  0.0  0.0  0.0  0.0  2.2

或者您可以使用10x6矩阵:

5.2  0.0  0.0  1.2  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  3.2
2.1  0.0  0.0  0.0  0.0  4.2
0.0  0.0  0.0  0.0  0.0  2.2
0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0

这种模糊性是一个问题,因为第一个矩阵与第二个矩阵差别很大。

此外,sparse matrix的要点是内存和/或处理时间有效。如果您分配了一整列m行和n列,那么您将拥有密集矩阵表示。

答案 3 :(得分:0)

您可以测量行数和列数,然后定义2d数组。当然,这会增加时间复杂度!如果您不关心内存的大小,可以使用最大列数和行来定义数组!所以你应该选择大时间复杂度和大内存大小。

答案 4 :(得分:0)

除非您先自己完全阅读文件,否则没有真正的方法可以了解文件中的内容。

由于您知道将有最多10k个元素,您可以静态首先分配该大小的数组,然后将数字加载到您解析EOF之前。

float sparseMatrix[10000];

这只意味着您的程序将始终为10k元素分配空间,而不管数组中实际有多少元素。如果你假设每个元素占用4个字节,那么你只能使用~40kB的内存。这可能是最简单的解决方案。

另一种选择是完全读取文件,找出所需的大小,动态分配该大小,然后在填充元素时再次读取整个文件。

// Assume numberOfElements was determined by reading through the file first
float* sparseMatrix = malloc(sizeof(float) * numberOfElements); 

虽然这种方法会占用更少的内存,但它需要两次完整的文件读取+调用malloc的开销。