如何从包含字符串和双精度数的.dat文件中读取并将双精度数写入矩阵?

时间:2019-06-14 23:33:08

标签: c file

我有一个包含以下结构的文件:

Caso Escp P1 P2 P3 P4 P5 P5+ Caos HCaos
Total 0.099601 82.921184 1.459357 1.576886 0.381672 0.250597 0.392030 12.918674 0.000000
Biest 0.199601 65.802794 2.895808 3.160080 0.764870 0.502196 0.785629 25.889022 0.000000
Monoest 0.000000 99.971372 0.028628 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

如您所见,它在同一文件中包含字符串和双打。我正在尝试获取这些双打,并将其写入矩阵并在屏幕上打印。我已经可以使用仅包含双打的文件来做到这一点,但是在这种情况下,我还没有找到解决方案。

这是我的代码示例:

#define lin 4
#define col 10
double N = 0.3;
char filename_porc[64], str[100];

int main()
{
    double mat[lin][col];       

    for (int k = 1; k < lin; k++)
    {
        for (int m = 1; m < col; m++)
        {
            printf("%f ", mat[k][m]);
        }
        printf("\n");
    }

    sprintf(filename_porc, "(N = %g) resp.dat", N); 
    input_result = fopen(filename_porc, "r");

    printf("\n\n");

    fgets(str, 100, input_result);
    for (int i = 0; i < lin; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if ((i > 0) && (j > 0))
            {
                fscanf(input_result, "%g", &mat[i-1][j-1]);
                printf("%g ", mat[i-1][j-1]);
            }
        }
        printf("\n");
    }

    fclose(input_result);
    printf("\n *** End of Execution ***");
    getchar();
}

编辑:

fgets(str, 100, input_result);

    for (int i = 0; i < lin; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (j == 0) { fscanf(input_result, "%s", str); }

            if ((i > 0) && (j > 0))
            {
                fscanf(input_result, "%g", &mat[i-1][j-1]);
                printf("%g ", mat[i-1][j-1]);
            }
        }
        printf("\n");
    }

2 个答案:

答案 0 :(得分:0)

您已经知道,您可以像这样读取一个数字:

fscanf(input_result, "%g", &x);

如果要使用一个命令读取两个数字,可以执行以下操作:

fscanf(input_result, "%g %g", &x, &y);

要读取字符串后跟数字:

char str[20];
fscanf(input_result, "%s %g", str, &x);

(请注意,“ str”没有与号,因为它是一个数组。)

因此,要读取一个字符串后跟多个数字,可以指定所有数字:

fscanf(input_result, "%s %g %g %g %g %g", str, &arr[0], &arr[1], &arr[2],...

或者您可以使用循环:

fscanf(input_result, "%s", str);
for(unsigned int k=0; k<col; ++k)
    fscanf(input_result, "%g", &arr[k]);

编辑: 要阅读整个第一行,请确保str足够大,然后使用fgets

char str[100];
fgets( str, 100, input_result);

答案 1 :(得分:0)

读取文件时,hardcode的行,列和缓冲区的数量非常有限。这是使用dynamic memory的更灵活的方法。

尽管如此,但并非没有关于输入文件的假设:文件应以换行符结尾,具有固定的列,没有格式错误,第一行是标题等。它还频繁调用realloc,这会导致在实践中不应导致许多系统调用,但可以通过将容量加倍而不是增加容量来加快速度。考虑一下这是一个概念证明。

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

typedef struct matrix {
    int rows;
    int cols;
    double **data;
} matrix;

int main() {
    matrix m = {0, 0, 0};
    m.data = malloc(sizeof(double *));
    int digit_buf_len = 0;
    char digit_buf[32];
    FILE *fin = fopen("resp.dat", "r");
    int c;

    // skip the first row
    while ((c = fgetc(fin)) != EOF && c != '\n');

    for (int col = 0; (c = fgetc(fin)) != EOF;) {
        if (isdigit(c) || c == '.') {
            digit_buf[digit_buf_len++] = c;
        }
        else if (digit_buf_len) {
            if (col) {
                m.data[m.rows] = realloc(m.data[m.rows], 
                                         (col + 1) * sizeof(double));
            }
            else {
                m.data = realloc(m.data, (m.rows + 1) * sizeof(double *));
                m.data[m.rows] = malloc(sizeof(double));
            }

            digit_buf[digit_buf_len] = '\0';
            sscanf(digit_buf, "%lf", &m.data[m.rows][col]);
            memset(digit_buf, 0, digit_buf_len);
            digit_buf_len = 0;
            col++;
        }

        if (c == '\n') {
            m.cols = m.cols > col ? m.cols : col;
            m.rows++;
            col = 0;
        }
    }

    for (int i = 0; i < m.rows; i++) {
        for (int j = 0; j < m.cols; j++) {
            printf("%f ", m.data[i][j]);
        }

        free(m.data[i]);
        puts("");
    }

    free(m.data);
    fclose(fin);
    return 0;
}

输出:

0.099601 82.921184 1.459357 1.576886 0.381672 0.250597 0.392030 12.918674 0.000000
0.199601 65.802794 2.895808 3.160080 0.764870 0.502196 0.785629 25.889022 0.000000
0.000000 99.971372 0.028628 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

如果文件更改为:

Caso Escp P1 P2 P3 P4 P5 P5+ Caos HCaos
Total 0.099601 82.921184 1.459357 1.576886
Biest 0.199601 65.802794 2.895808 3.160080
Mxxxxst 1.000000 99.971372 1.028628 2.000000
Mxxxxst 2.000000 19.971372 7.028628 3.000000
Mxxxxst 3.000000 29.971372 6.028628 5.000000
Mxxxxst 4.000000 29.971372 3.028628 6.000000

然后它仍然有效:

0.099601 82.921184 1.459357 1.576886
0.199601 65.802794 2.895808 3.160080
1.000000 99.971372 1.028628 2.000000
2.000000 19.971372 7.028628 3.000000
3.000000 29.971372 6.028628 5.000000
4.000000 29.971372 3.028628 6.000000
相关问题