Получить значение из таблицы CSV в C - PullRequest
0 голосов
/ 04 октября 2018

Я сделал матрицу в MatLab и экспортировал ее как CSV.Я действительно не знаю, как использовать это в моем коде C все же.Например, моя таблица выглядит следующим образом (хотя значения намного больше и сложнее):

Height/Angle, 50, 550, 1050, 1550, 2050
5, 0.9, 0.8, 0.7, 0.6, 0.5
6, 0.8, 0.7, 0.6, 0.5, 0.4
7, 0.7, 0.6, 0.5, 0.4, 0.3
8, 0.6, 0.5, 0.4, 0.3, 0.2
9, 0.5, 0.4, 0.3, 0.2, 0.1

Итак, мне нужна функция, которая принимает два аргумента и возвращает соответствующее значение из таблицы.У меня есть программа, которая дает мне высоту и угол наклона плоскости, видимой с ИК-датчика, и, учитывая эти значения, я хочу соответствующее значение.Например: GetValueFromCSV(550,7); должно вернуть 0.6 в моем примере.Но я понятия не имею, как это сделать.Я провел некоторое исследование с помощью функции «strtok ()», но это не совсем то, что мне нужно.Пожалуйста, помогите noob.

1 Ответ

0 голосов
/ 04 октября 2018

.o O (да, код причины ответа только для кода не требует пояснений)

#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct row_tag
{
    int index;
    double *data;
} row_t;

size_t get_col_count(FILE *is)
{
    size_t col_count = 1;

    int ch;
    while ((ch = fgetc(is)) != EOF && ch != '\n')
        if (ch == ',')
            ++col_count;

    rewind(is);
    return col_count;
}

row_t* csv_read(FILE *is, size_t *cols, size_t *rows)
{
    *cols = get_col_count(is);
    *rows = 0;
    char const *origin_format = "%*[^ ,]%c";
    char const *row_header_format = "%d%c";
    char const *format = "%lf%c";
    row_t *csv = NULL;

    bool valid = true;
    for (size_t current_row = 0; valid; ++current_row) {
        csv = realloc(csv, (current_row + 1)* sizeof(row_t));
        csv[current_row].data = calloc(cols - 1, sizeof(double));

        for (size_t current_col = 0; valid && current_col < cols; ++current_col) {

            char delim;
            if (!current_col && !current_row) {
                if (fscanf(is, origin_format, &delim) != 1 || delim != ',') {
                    valid = false;
                    continue;
                }
                csv[0].index = -1;
            }
            else if (!current_col) {
                int result = -1;
                if ((result = fscanf(is, row_header_format, &csv[current_row].index, &delim)) != 2 || delim != ',') {
                    valid = false;
                    continue;
                }
            }
            else {
                if (fscanf(is, format, &csv[current_row].data[current_col - 1], &delim) != 2 || delim != ',' && delim != '\n')
                    valid = false;
            }
        }

        if (!valid)
            free(csv[current_row].data);
        else *rows = current_row + 1;
    }

    return csv;
}

void csv_free(row_t *csv, size_t rows)
{
    for (size_t row = 0; row < rows; ++row)
        free(csv[row].data);
    free(csv);
}

double csv_get_value(row_t *csv, int col_index, size_t cols, int row_index, size_t rows)
{
    size_t col;
    for (col = 1; csv[0].data[col] != col_index && col < cols; ++col);
    if (col >= cols || csv[0].data[col] != col_index)
        return 0.;

    size_t row;
    for (row = 1; csv[row].index != row_index && row < rows; ++row);
    if (row >= rows || csv[row].index != row_index)
        return 0.;

    return csv[row].data[col];
}

int main(void)
{
    char const *filename = "test.txt";
    FILE *is = fopen(filename, "r");
    if (!is) {
        fprintf(stderr, "Couldn't open \"%s\" for reading!\n\n", filename);
        return EXIT_FAILURE;
    }

    size_t cols;
    size_t rows;
    row_t *csv = csv_read(is, &cols, &rows);
    printf("Cols: %zu\nRows: %zu\n\n", cols, rows);

    fclose(is);

    // have fun with csv:
    for (size_t y = 0; y < rows; ++y) {
        printf("%2d: ", csv[y].index);
        for (size_t x = 0; x < cols - 1; ++x)
            printf("%f ", csv[y].data[x]);
        putchar('\n');
    }

    double value = csv_get_value(csv, 550, cols, 7, rows);
    printf("\n%f\n", value);


    csv_free(csv, rows);
}

Вывод:

Cols: 6
Rows: 6

-1: 50.000000 550.000000 1050.000000 1550.000000 2050.000000
 5: 0.900000 0.800000 0.700000 0.600000 0.500000
 6: 0.800000 0.700000 0.600000 0.500000 0.400000
 7: 0.700000 0.600000 0.500000 0.400000 0.300000
 8: 0.600000 0.500000 0.400000 0.300000 0.200000
 9: 0.500000 0.400000 0.300000 0.200000 0.100000

0.600000
...