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:
M | csv.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;
}