. o O ( yes, code-only answer cause code is quite self-explanatory )
#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);
}
Output:
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