Add base for csv-data-manipulation.
This commit is contained in:
parent
bb3bf1fe53
commit
e217d1b9fd
4 changed files with 194 additions and 6 deletions
14
Makefile
14
Makefile
|
@ -1,20 +1,22 @@
|
|||
|
||||
SRC = $(wildcard src/*.c)
|
||||
DEPS = $(wildcard deps/**/*.c)
|
||||
OBJS = $(DEPS:.c=.o)
|
||||
OBJS = $(patsubst %.c,%.o,$(DEPS))
|
||||
BINS = $(notdir $(patsubst %.c,%,$(SRC)))
|
||||
|
||||
CFLAGS = -std=c99 -Ideps -Wall -Wno-unused-function -U__STRICT_ANSI__
|
||||
BINS = exercice
|
||||
# CFLAGS = -std=c99 -Ideps -Wall -Wno-unused-function -U__STRICT_ANSI__
|
||||
CFLAGS = -ggdb -std=c99 -Ideps -Wall -Wno-unused-function -pedantic
|
||||
|
||||
|
||||
all: $(BINS)
|
||||
echo "BINS=$(BINS)"
|
||||
|
||||
$(BINS): $(SRC) $(OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ src/$(@:.exe=).c $(OBJS) $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -o $@ src/$@.c $(OBJS) $(LDFLAGS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $< -c -o $@ $(CFLAGS)
|
||||
|
||||
clean:
|
||||
$(foreach c, $(BINS), rm $(c);)
|
||||
rm $(OBJS) src/*.o
|
||||
$(foreach c, $(BINS), rm -f $(c);)
|
||||
rm -f $(OBJS)
|
||||
|
|
BIN
exercice
BIN
exercice
Binary file not shown.
5
fixtures/csv-data-manipulation.csv
Normal file
5
fixtures/csv-data-manipulation.csv
Normal file
|
@ -0,0 +1,5 @@
|
|||
C1,C2,C3,C4,C5
|
||||
1,5,9,13,17
|
||||
2,6,10,14,18
|
||||
3,7,11,15,19
|
||||
4,8,12,16,20
|
|
181
src/csv-data-manipulation.c
Normal file
181
src/csv-data-manipulation.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
|
||||
#define TITLE "CSV data manipulation"
|
||||
#define URL "http://rosettacode.org/wiki/CSV_data_manipulation"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define bool int
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc...*/
|
||||
#include <string.h> /* strtok...*/
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/**
|
||||
* How to read a CSV file ?
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
char delim;
|
||||
unsigned int rows;
|
||||
unsigned int cols;
|
||||
char ** table;
|
||||
} CSV;
|
||||
|
||||
/* trim whitespaces from left & right of a string */
|
||||
int trim(char ** str) {
|
||||
int trimmed;
|
||||
int n;
|
||||
int len;
|
||||
|
||||
len = strlen(*str);
|
||||
n = len - 1;
|
||||
/* from right */
|
||||
while((n>=0) && isspace((*str)[n])) {
|
||||
(*str)[n] = '\0';
|
||||
trimmed += 1;
|
||||
n--;
|
||||
}
|
||||
|
||||
/* from left */
|
||||
n = 0;
|
||||
while((n < len) && (isspace((*str)[0]))) {
|
||||
(*str)[0] = '\0';
|
||||
*str = (*str)+1;
|
||||
trimmed += 1;
|
||||
n++;
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
CSV * csv_create() {
|
||||
CSV * csv;
|
||||
|
||||
csv = malloc(sizeof(CSV));
|
||||
csv->rows = 0;
|
||||
csv->cols = 0;
|
||||
csv->table = NULL;
|
||||
|
||||
return csv;
|
||||
}
|
||||
|
||||
int csv_destroy(CSV * csv) {
|
||||
free(csv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Resize CSV table
|
||||
* - grow columns: on each row, add missing columns cells
|
||||
* - grow rows: add now rows, with all columns count
|
||||
* - reduce columns: remove columns from right
|
||||
* - reduce lines: remove columns from the end
|
||||
*/
|
||||
int csv_resize(CSV * csv, unsigned int new_cols, unsigned int new_rows) {
|
||||
char ** new_table;
|
||||
unsigned int cur_col,
|
||||
cur_row,
|
||||
idx,
|
||||
new_idx,
|
||||
max_cols,
|
||||
max_rows;
|
||||
bool in_old, in_new;
|
||||
|
||||
/* add missing column cells */
|
||||
new_table = malloc(sizeof(char *) * new_cols * new_rows);
|
||||
|
||||
max_cols = (new_cols > csv->cols)? new_cols : csv->cols;
|
||||
max_rows = (new_rows > csv->rows)? new_rows : csv->rows;
|
||||
|
||||
for (cur_col=0; cur_col<max_cols; cur_col++) {
|
||||
for (cur_row=0; cur_row<max_rows; cur_row++) {
|
||||
idx = cur_col + (cur_row * csv->cols);
|
||||
new_idx = cur_col + (cur_row * new_cols);
|
||||
|
||||
in_old = (cur_col < csv->cols) && (cur_row < csv->rows);
|
||||
in_new = (cur_col < new_cols) && (cur_row < new_rows);
|
||||
|
||||
if (in_old && in_new) {
|
||||
/* re-link data */
|
||||
new_table[new_idx] = csv->table[idx];
|
||||
} else if (in_old) {
|
||||
/* destroy data */
|
||||
free(csv->table[idx]);
|
||||
} else {
|
||||
/* set to NULL */
|
||||
new_table[new_idx] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* on rows */
|
||||
free(csv->table);
|
||||
csv->table = new_table;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* , char delim='\t' */
|
||||
int csv_open(CSV * csv, char * filename) {
|
||||
FILE * fp;
|
||||
unsigned int m_rows;
|
||||
unsigned int m_cols, cols;
|
||||
char line[2048];
|
||||
char * lineptr;
|
||||
char * token;
|
||||
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) { exit(EXIT_FAILURE); }
|
||||
|
||||
m_rows = 0;
|
||||
m_cols = 0;
|
||||
while(fgets(line, sizeof(line), fp) != NULL) {
|
||||
/* printf("Got line: %s", line); */
|
||||
m_rows += 1;
|
||||
cols = 0;
|
||||
lineptr = line;
|
||||
while ((token = strtok(lineptr, ",")) != NULL) {
|
||||
lineptr = NULL;
|
||||
trim(&token);
|
||||
printf("%s\t|", token);
|
||||
cols += 1;
|
||||
if (cols > m_cols) { m_cols = cols; }
|
||||
csv_resize(csv, m_cols, m_rows);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
csv->delim = '\t';
|
||||
csv->rows = m_rows;
|
||||
csv->cols = m_cols;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csv_save(CSV * csv, char * filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csv_set(CSV * csv, unsigned int col, unsigned int row, char * value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
CSV * csv;
|
||||
|
||||
printf("%s\n%s\n\n",TITLE, URL);
|
||||
|
||||
|
||||
csv = csv_create();
|
||||
csv_open(csv, "fixtures/csv-data-manipulation.csv");
|
||||
|
||||
csv_set(csv, 0, 0, "Column0");
|
||||
csv_set(csv, 1, 1, "100");
|
||||
csv_set(csv, 2, 2, "200");
|
||||
csv_set(csv, 3, 3, "300");
|
||||
csv_set(csv, 4, 4, "400");
|
||||
|
||||
csv_save(csv, "fixtures/csv-data-manupulation.out.csv");
|
||||
csv_destroy(csv);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue