csv

Unnamed repository
Log | Files | Refs

commit ba408993ea59685a9be3d9bc837f31c2ec45e47e
parent 25a9500caba30aeb01ed4e8931a82dc6ae1efde1
Author: aabacchus <ben@bvnf.space>
Date:   Sat,  2 Oct 2021 20:10:35 +0100

use csv struct and create/destroy functions

Diffstat:
Mcsv.c | 81++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 56 insertions(+), 25 deletions(-)

diff --git a/csv.c b/csv.c @@ -6,13 +6,52 @@ #define MAX_LINE 2048 +struct csv { + int cols, rows; + char **headers; /* array of strings */ + float **data; /* array of arrays of floats */ +}; + +struct csv * +csv_create(void) { + struct csv *c; + c = malloc(sizeof c + sizeof(char *) + sizeof(float *)); + if (c == NULL) + return NULL; + + c->cols = 0; + c->rows = 0; + + char **h = malloc(sizeof (char *) * MAX_LINE); + if (h == NULL) + return NULL; + c->headers = h; + + float **d = malloc(sizeof (float *)); + if (d == NULL) + return NULL; + c->data = d; + + return c; +} + +void +csv_destroy(struct csv *c) { + int i; + for (i = 0; i < c->cols; i++) + free(c->headers[i]); + for (i = 0; i < c->rows; i++) + free(c->data[i]); + free(c); +} + /* read_header reads each header field name from the first line of the file * into *header, and returns the number of columns. * This function mallocs the returned value of fields in *header[0..n-1] */ int -read_header(FILE *f, char ***header) { - char **headerp = *header; +read_header(FILE *f, char **header) { + char **headerp = header; int c; int ncols = 0; char *n = malloc(MAX_LINE); @@ -20,7 +59,7 @@ read_header(FILE *f, char ***header) { while ((c = fgetc(f)) != EOF) { if (c == ',' || c == '\n') { *np++ = '\0'; - *headerp = malloc(sizeof n * sizeof *n); + *headerp = malloc(strlen(n)); strcpy(*headerp, n); headerp++; np = n; @@ -112,7 +151,6 @@ cleanup: free(n); for (int i = 0; i < nrows; y++) free(data[i]); - free(data); return -1; } @@ -132,8 +170,7 @@ main(int argc, char **argv) { if (argc - optind > 1) { usage: fprintf(stderr, - "usage: %s [-H] [file]\n if no filename given, data is \ -read from stdin\n" + "usage: %s [-H] [file]\n if no filename given, data is read from stdin\n" " -H\tread data headers from first line\n", argv[0]); return 1; } @@ -150,16 +187,15 @@ read from stdin\n" int ncols = 0; + struct csv *csv = csv_create(); + if (flag_H) { /* read header */ - char **header = malloc(sizeof (char *) * MAX_LINE); - ncols = read_header(f, &header); + ncols = read_header(f, csv->headers); for (int i = 0; i < ncols; i++) { - printf("%s\t", header[i]); - free(header[i]); + printf("%s\t", csv->headers[i]); } printf("\n"); - free(header); } else { /* scan the first line to get the value of ncols */ while ((c = fgetc(f)) != EOF) { @@ -172,29 +208,24 @@ read from stdin\n" /* ensure we can properly scan the first line when we come to it */ rewind(f); } + csv->cols = ncols; /* read data */ - float **data = malloc(sizeof (float *) * 1); - if (data == NULL) { - perror("malloc"); - return 1; - } - int nrows = read_data(f, &data, ncols); + int nrows = read_data(f, &csv->data, ncols); + fclose(f); if (nrows == -1) { - free(data); - fclose(f); + csv_destroy(csv); return 1; } for (int i = 0; i < nrows; i++) { for (int j = 0; j < ncols; j++) - printf("%g\t", data[i][j]); + printf("%g\t", csv->data[i][j]); printf("\n"); } - fprintf(stderr, "table has %d rows of %d columns\n", nrows, ncols); + csv->rows = nrows; + fprintf(stderr, "table has %d rows of %d columns\n", csv->rows, csv->cols); + + csv_destroy(csv); - for (int i = 0; i < nrows; i++) - free(data[i]); - free(data); - fclose(f); return 0; }