You are perfectly understandable, but you are not saying enough to give
really helpful answers.
You're very kind
Despite binary file, here in ascii, I have a file named data.csv and
another named data.def
data.csv contains data
data.def contains definition of each field
data.csv
H,5,25,79.911
E,4,24,27.553
J,8,11,51.952
K,8,22,14.606
D,3,4,80.156
C,1,3,99.218
L,10,19,29.637
H,6,31,29.771
L,10,12,89.283
L,10,29,6.949
data.def
0113
# 0 char | 1 int | 2 float | 3 double
both files are unknown at compile time
I wan to load all data without spend 8 bytes for each field in the
struct
Ok, it's very hard to me to explain, let speak to C:
Note: This code uses flexible array, must be compiled with c99 flag
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum {type_chr, type_int, type_flt, type_dbl};
#define FILE_LINE_SIZE 100
typedef struct TTable {
struct TCol *col_first;
struct TRow *row_first;
struct TCol *col_last;
struct TRow *row_last;
int cols;
int rows;
} Table;
typedef struct TCol {
struct TTable *table;
struct TCol *prev;
struct TCol *next;
int id;
int type;
} Col;
typedef union TData {
char as_chr;
int as_int;
float as_flt;
double as_dbl;
} Data;
typedef struct TRow {
struct TTable *table;
struct TRow *prev;
struct TRow *next;
Data data[]; /* Array flexible */
} Row;
static Table *table_create()
{
Table *new;
new = malloc(sizeof(Table));
if (new == NULL) {
fprintf(stderr, "Nos hemos quedado sin memoria.");
exit(EXIT_FAILURE);
}
new->col_first = NULL;
new->row_first = NULL;
new->col_last = NULL;
new->row_last = NULL;
new->cols = 0;
new->rows = 0;
return new;
}
static Col *table_add_col(Table *table, int type)
{
Col *new;
new = malloc(sizeof(Col));
if (new == NULL) {
fprintf(stderr, "Nos hemos quedado sin memoria.");
exit(EXIT_FAILURE);
}
new->table = table;
new->id = table->cols++;
new->type = type;
if (table->col_last) {
table->col_last->next = new;
new->prev = table->col_last;
} else {
table->col_first = new;
new->prev = NULL;
}
new->next = NULL;
table->col_last = new;
return new;
}
static Row *table_add_row(Table *table)
{
Row *new;
new = malloc(sizeof(Row) + (sizeof(Data) * table->cols));
if (new == NULL) {
fprintf(stderr, "Nos hemos quedado sin memoria.");
exit(EXIT_FAILURE);
}
new->table = table;
if (table->row_last) {
table->row_last->next = new;
new->prev = table->row_last;
} else {
table->row_first = new;
new->prev = NULL;
}
new->next = NULL;
table->row_last = new;
table->rows++;
return new;
}
static Row *table_delete_row(Row *row)
{
Row *res = NULL;
if (row) {
if (row->prev) {
row->prev->next = row->next;
} else {
row->table->row_first = row->next;
}
if (row->next) {
row->next->prev = row->prev;
} else {
row->table->row_last = row->prev;
}
res = row->next;
row->table->rows--;
free(row);
}
return res;
}
static void table_clear(Table *table)
{
while ((table->row_first = table_delete_row(table->row_first)));
}
static void table_free(Table *table)
{
Col *col;
table_clear(table);
while (table->col_first) {
col = table->col_first->next;
free(table->col_first);
table->col_first = col;
}
free(table);
}
static void table_raise_error(Table *table, const char *err)
{
table_free(table);
fprintf(stderr, "%s", err);
exit(EXIT_FAILURE);
}
static void table_print(Table *table)
{
Row *row;
Col *col;
for (row = table->row_first; row; row = row->next) {
printf("-\n");
for (col = table->col_first; col; col = col->next) {
switch (col->type) {
case type_chr:
printf("\tCampo %d = %c\n", col->id, row->data[col-
break;
case type_int:
printf("\tCampo %d = %d\n", col->id, row->data[col-
break;
case type_flt:
printf("\tCampo %d = %f\n", col->id, row->data[col-
break;
case type_dbl:
printf("\tCampo %d = %f\n", col->id, row->data[col-
break;
}
}
}
}
int main(void)
{
Table *table;
Col *col;
Row *row;
FILE *file;
char c, s[FILE_LINE_SIZE], *p;
table = table_create();
file = fopen("data.def", "r");
if (file == NULL) {
table_raise_error(table, "No se puede abrir el archivo data.def
en modo lectura.\n");
}
/* Por cada tipo declarado en data.def ... */
/* For each type in data.def */
while ((c = fgetc(file))) {
if ((c < '0') || (c > '3')) break;
/* ... creo una columna */
/* ... create a col */
table_add_col(table, c - '0');
};
fclose(file);
if (table->cols == 0) {
table_raise_error(table, "Sin campos no puedo hacer mucho!!!\n");
}
/* Leo data.csv cargando la estructura */
/* Load data.csv */
file = fopen("data.csv", "r");
if (file == NULL) {
table_raise_error(table, "No se puede abrir el archivo data.csv
en modo lectura.\n");
}
while ((p = fgets(s, FILE_LINE_SIZE, file)) != NULL) {
row = table_add_row(table);
col = table->col_first;
while (col) {
switch (col->type) {
case type_chr: sscanf(p, "%c", &row->data[col->id].as_chr);
break;
case type_int: sscanf(p, "%d", &row->data[col->id].as_int);
break;
case type_flt: sscanf(p, "%f", &row->data[col->id].as_flt);
break;
case type_dbl: sscanf(p, "%lf", &row->data[col->id].as_dbl);
break;
}
if ((col = col->next)) {
while (*++p != ',');
p++;
}
}
}
fclose(file);
if (table->rows == 0) {
table_raise_error(table, "Sin datos no puedo hacer mucho!!!\n");
}
table_print(table);
table_free(table);
return 0;
}