Как читать из файла .dat, который содержит строки и двойники, и записывать двойники на матрице? - PullRequest
2 голосов
/ 15 июня 2019

У меня есть файл, который имеет следующую структуру:

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 голосов
/ 15 июня 2019

При чтении файла достаточно ограничить жестким кодом количеством строк, столбцов и буферов.Вот более гибкий подход, использующий динамическую память .

Не без предположений относительно входного файла, однако: файл должен заканчиваться символом новой строки, иметь фиксированные столбцы, без ошибок форматирования, первая строкаэто также заголовки и т. д. Он также делает частые вызовы 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
0 голосов
/ 15 июня 2019

Как вы уже знаете, вы можете прочитать одно число, как это:

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]);

EDIT: Чтобы прочитать всю первую строку, убедитесь, что str достаточно большой, и используйте fgets:

char str[100];
fgets( str, 100, input_result);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...