commit 3ae4b956f9251c372ff86f743afb905df7ef47ae
parent 7de7356a1b085cf76c9818d475f1145e44a62a16
Author: klewer-martin <martin.cachari@gmail.com>
Date: Wed, 28 Jul 2021 23:24:08 -0300
Update:
Diffstat:
12 files changed, 195 insertions(+), 302 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,8 +6,8 @@ PROGNAME=main
all: main clean
-main: cla.o status.o io.o main.o user.o vector.o
- $(CC) $(CFLAGS) main.o cla.o status.o io.o user.o vector.o -o $(PROGNAME)
+main: cla.o status.o utils.o main.o user.o vector.o
+ $(CC) $(CFLAGS) main.o cla.o status.o utils.o user.o vector.o -o $(PROGNAME)
main.o: $(HFOLDER)/cla.h $(HFOLDER)/status.h $(HFOLDER)/user.h
$(CC) $(CFLAGS) -c $(SRCFOLDER)/main.c
@@ -21,8 +21,8 @@ vector.o: $(HFOLDER)/vector.h $(HFOLDER)/status.h
status.o: $(HFOLDER)/status.h
$(CC) $(CFLAGS) -c $(SRCFOLDER)/status.c
-io.o: $(HFOLDER)/status.h $(HFOLDER)/user.h
- $(CC) $(CFLAGS) -c $(SRCFOLDER)/io.c
+utils.o: $(HFOLDER)/status.h $(HFOLDER)/user.h
+ $(CC) $(CFLAGS) -c $(SRCFOLDER)/utils.c
user.o: $(HFOLDER)/status.h $(HFOLDER)/user.h
$(CC) $(CFLAGS) -c $(SRCFOLDER)/user.c
diff --git a/include/io.h b/include/io.h
@@ -1,66 +0,0 @@
-#ifndef IO__H
-#define IO__H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "cla.h"
-#include "user.h"
-#include "status.h"
-
-#define _XOPEN_SOURCE
-#define __USE_XOPEN
-#include <time.h>
-
-#define INIT_SIZE 1000
-#define INPUT_FILE_FIELDS 6
-
-#define BUFFER_SIZE 1000
-#define GROWTH_FACTOR 2
-
-#define INPUT_FILE_DELIM ","
-#define CSV_OUTPUT_DELIM ","
-
-#define XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-#define XML_ROOT_OPEN "<root>"
-#define XML_ROOT_CLOSE "</root>"
-
-#define XML_ROW_OPEN "<row>"
-#define XML_ROW_CLOSE "</row>"
-
-#define XML_ID_OPEN "<user>"
-#define XML_ID_CLOSE "</user>"
-
-#define XML_CREDIT_OPEN "<credits>"
-#define XML_CREDIT_CLOSE "</credits>"
-
-#define XML_DEBT_OPEN "<debits>"
-#define XML_DEBT_CLOSE "</debits>"
-
-/* typedef enum { */
-/* POS_ID_TXN, */
-/* POS_USER_ID, */
-/* POS_TXN_DATE, */
-/* POS_AMOUNT, */
-/* POS_CARD_NUMBER, */
-/* POS_DESC */
-/* } csv_pos_t; */
-
-status_t string_split(char *s, char **data, char *delim);
-
-status_t load_values(FILE *, cla_t *data);
-
-void clean_data(char **data);
-
-/*
-status_t export_data_as_csv(FILE *fo, const user_t *users, size_t size);
-status_t export_data_as_xml(FILE *fo, const user_t *users, size_t size);
-*/
-
-status_t destroy_data(char **, size_t);
-status_t get_date(time_t *e, char **data);
-
-void clean_buffer(char *buf);
-
-#endif
diff --git a/include/sort.h b/include/sort.h
@@ -1,18 +0,0 @@
-#ifndef SORT__H
-#define SORT__H
-
-#include "cla.h"
-#include "user.h"
-#include "status.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int credit_minmax(const void *, const void *);
-int credit_maxmix(const void *, const void *);
-
-int debt_minmax(const void *, const void *);
-int debt_maxmin(const void *, const void *);
-
-
-#endif
diff --git a/include/user.h b/include/user.h
@@ -2,6 +2,7 @@
#define USER__H
#include "status.h"
+#include "utils.h"
#define OUT_FILE_DELIM ","
diff --git a/include/utils.h b/include/utils.h
@@ -0,0 +1,36 @@
+#ifndef UTILS__H
+#define UTILS__H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cla.h"
+#include "user.h"
+#include "status.h"
+
+#define _XOPEN_SOURCE
+#define __USE_XOPEN
+#include <time.h>
+
+#define IN_FILE_MAX_LEN 100
+#define IN_FILE_DELIM ","
+#define IN_FILE_FIELDS 6
+#define IN_FILE_FIELDS_MAX_LEN 50
+
+#define XML_STR_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+#define XML_STR_ROOT "root"
+#define XML_STR_ROW "row"
+#define XML_STR_ID "user"
+#define XML_STR_CREDIT "credits"
+#define XML_STR_DEBIT "debits"
+
+status_t get_date(time_t *, char **);
+status_t array_destroy(char **, size_t);
+status_t string_split(char *, char **, char *);
+
+void clean_array(char **);
+void clean_buffer(char *);
+
+
+#endif
diff --git a/include/vector.h b/include/vector.h
@@ -4,11 +4,9 @@
#define VECTOR_INIT_SIZE 10
#define VECTOR_GROWTH_FACTOR 2
-#define STR_XML_ROOT "root"
-#define STR_XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-
#include <stdlib.h>
+#include "utils.h"
#include "status.h"
typedef status_t (*printer_t)(const void *, FILE *);
@@ -27,8 +25,6 @@ status_t ADT_Vector_create(ADT_Vector_t **);
status_t ADT_Vector_add(ADT_Vector_t **, void *);
status_t ADT_Vector_destroy(ADT_Vector_t **);
-status_t ADT_Vector_load(ADT_Vector_t *, FILE *);
-
status_t ADT_Vector_set(ADT_Vector_t **, void *, size_t);
status_t ADT_Vector_print(const ADT_Vector_t *, FILE *, printer_t);
status_t ADT_Vector_sort(ADT_Vector_t *, comparator_t);
@@ -38,7 +34,7 @@ void *ADT_Vector_get_elem(const ADT_Vector_t *v, void *e);
status_t ADT_Vector_set_printer(ADT_Vector_t *, printer_t);
status_t ADT_Vector_set_comparator(ADT_Vector_t *, comparator_t);
-status_t ADT_Vector_export_as_xml(ADT_Vector_t *, FILE *, printer_t);
-status_t ADT_Vector_export_as_csv(ADT_Vector_t *, FILE *, printer_t);
+status_t ADT_Vector_export_as_xml(const ADT_Vector_t *, FILE *, printer_t);
+status_t ADT_Vector_export_as_csv(const ADT_Vector_t *, FILE *, printer_t);
#endif
diff --git a/source/io.c b/source/io.c
@@ -1,112 +0,0 @@
-#include "../include/io.h"
-
-status_t string_split(char *s, char **data, char *delim)
-{
- char *p, *tmp;
- size_t fields = 0;
-
- for(p = s; (tmp = strtok(p, delim)); p = NULL)
- strcpy(data[fields++], tmp);
-
- if(fields != INPUT_FILE_FIELDS)
- return ERROR_CORRUPT_DATA;
-
- return OK;
-}
-
-status_t destroy_data(char **data, size_t fields)
-{
- size_t i;
-
- if(data == NULL) return ERROR_NULL_POINTER;
-
- for(i = 0; i < fields; i++) {
- free(data[i]);
- data[i] = NULL;
- }
-
- free(data);
- return OK;
-}
-/*
-status_t export_data_as_csv(FILE *fo, const user_t *users, size_t size)
-{
- size_t i;
-
- if(fo == NULL || users == NULL)
- return ERROR_NULL_POINTER;
-
- for(i = 0; i < size; i++)
- fprintf(fo, "%ld%s%ld%s%ld\n", users[i]->id, CSV_OUTPUT_DELIM,\
- users[i]->c, CSV_OUTPUT_DELIM, users[i]->d);
-
- return OK;
-}
-
-status_t export_data_as_xml(FILE *fo, const user_t *users, size_t size)
-{
- size_t i;
-
- if(fo == NULL || users == NULL)
- return ERROR_NULL_POINTER;
-
- fprintf(fo, "%s\n%s\n", XML_HEADER, XML_ROOT_OPEN);
-
- for(i = 0; i < size; i++) {
- fprintf(fo, "\t%s\n", XML_ROW_OPEN);
- fprintf(fo, "\t\t%s%ld%s\n", XML_ID_OPEN, users[i]->id, XML_ID_CLOSE);
- fprintf(fo, "\t\t%s%ld%s\n", XML_CREDIT_OPEN, users[i]->c, XML_CREDIT_CLOSE);
- fprintf(fo, "\t\t%s%ld%s\n", XML_DEBT_OPEN, users[i]->d, XML_DEBT_CLOSE);
- fprintf(fo, "\t%s\n", XML_ROW_CLOSE);
- }
-
- fprintf(fo, "%s\n", XML_ROOT_CLOSE);
- return OK;
-}
-*/
-void clean_buffer(char *buf)
-{
- size_t i;
-
- for(i = 0; i < BUFFER_SIZE; i++)
- buf[i] = '\0';
-}
-
-void clean_data(char **data)
-{
- size_t i;
-
- for(i = 0; i < INPUT_FILE_FIELDS; i++) {
- free(data[i]);
- data[i] = NULL;
- }
-}
-
-status_t get_date(time_t *e, char **data)
-{
- struct tm tm;
-
- if(e == NULL || data == NULL) return ERROR_NULL_POINTER;
-
- /* Desactiva el horario de verano */
- tm.tm_isdst = 0;
-
- switch(data[POS_TXN_DATE][2]) {
- case '/':
- strptime(data[2], "%d/%m/%Y %H:%M:%S", &tm);
- *e = mktime(&tm);
- break;
- case '-':
- strptime(data[2], "%d-%m-%Y %H:%M:%S", &tm);
- *e = mktime(&tm);
- break;
- case '.':
- strptime(data[2], "%d.%m.%Y %H:%M:%S", &tm);
- *e = mktime(&tm);
- break;
-
- default: return ERROR_CORRUPT_DATA; break;
- }
-
- return OK;
-}
diff --git a/source/main.c b/source/main.c
@@ -1,12 +1,11 @@
-#include "../include/io.h"
#include "../include/cla.h"
#include "../include/user.h"
+#include "../include/utils.h"
#include "../include/status.h"
#include "../include/vector.h"
#define IN_FILE_MAX_LEN 100
#define IN_FILE_DELIM ","
-#define OUT_FILE_DELIM ","
#define IN_FILE_FIELDS 6
#define IN_FILE_FIELDS_MAX_LEN 50
@@ -17,17 +16,18 @@ int main (int argc, char *argv[])
ADT_Vector_t *v;
ADT_user_t *user, *user_tmp;
char buffer[IN_FILE_MAX_LEN];
- char **data;
- char *endptr;
+ char *endptr, **data;
+ size_t i;
long amount;
+ time_t epoch;
- /* Asigna memoria a cla */
+ /* Asigna memoria a cla (c.l.a.: "command line arguments") */
if((st = cla_create(&cla)) != OK) {
show_status(st);
return st;
}
- /* Valida que los argumentos sean correctos */
+ /* Valida que los argumentos sean correctos y asigna valores a cla */
if((st = validate_arguments(argc, argv, cla)) != OK) {
show_status(st);
return st;
@@ -40,58 +40,108 @@ int main (int argc, char *argv[])
return st;
}
+ /* Crea un arreglo de cadenas de caracteres */
+ if((data = malloc(sizeof(char *) * IN_FILE_FIELDS)) == NULL) {
+ show_status(ERROR_MEMORY);
+ cla_destroy(cla);
+ ADT_Vector_destroy(&v);
+ return ERROR_MEMORY;
+ }
+
+ for(i = 0; i < IN_FILE_FIELDS; i++) {
+ if((data[i] = calloc(sizeof(char), IN_FILE_FIELDS_MAX_LEN)) == NULL) {
+ show_status(ERROR_MEMORY);
+ cla_destroy(cla);
+ ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
+ return ERROR_MEMORY;
+ }
+ }
+
/* Setea el comparador a ADT_Vector */
if((st = ADT_Vector_set_comparator(v, user_equals)) != OK) {
show_status(st);
cla_destroy(cla);
ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
return st;
}
+ /* Crea un usuario temporal */
if((st = user_create(&user_tmp)) != OK) {
show_status(st);
cla_destroy(cla);
ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
return st;
}
+ /* Lee linea por linea del archivo de entrada */
while(fgets(buffer, IN_FILE_MAX_LEN, cla->fi)) {
+
+ /* Separa la linea leida segun un caracter delimitador */
string_split(buffer, data, IN_FILE_DELIM);
+
+ /* Setea el usuario temporal con los datos obtenidos de la linea */
user_set_data(user_tmp, data);
amount = strtol(data[POS_AMOUNT], &endptr, 10);
if(*endptr != '\0') return ERROR_CORRUPT_DATA;
+ /* Transforma el tiempo de la linea leida a formato UNIX */
+ get_date(&epoch, data);
+
+ /* Comprueba que el tiempo de la linea leida no supere los argumentos ingresados */
+ if(epoch < cla->ti) continue;
+ else if(epoch > cla->tf) break;
+
+ /* Busca el id del usuario en el vector */
if((user = ADT_Vector_get_elem(v, user_tmp)) != NULL) {
- /* El usuario ya existe */
+ /* Si lo encuentra le suma el monto correspondiente */
user_add_amount(user, amount);
}
else {
- /* El usuario no existe */
+ /* Si no lo encuentra crea un usuario nuevo */
user_create(&user);
user_set_data(user, data);
- ADT_Vector_add(&v, user);
+
+ /* Y lo agrega al vector */
+ if((st = ADT_Vector_add(&v, user)) != OK){
+ show_status(st);
+ free(user_tmp);
+ cla_destroy(cla);
+ ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
+ return st;
+ }
}
+ clean_buffer(buffer);
+ clean_array(data);
}
+ /* Ordena el vector con los usuarios */
if((st = ADT_Vector_sort(v, user_comparator_credits_maxmin)) != OK) {
show_status(st);
free(user_tmp);
cla_destroy(cla);
ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
return st;
}
- if((st = ADT_Vector_print(v, stdout, user_print_as_csv)) != OK) {
+ /* Imprime el vector con los usuarios */
+ if((st = ADT_Vector_export_as_xml(v, stdout, user_print_as_xml)) != OK) {
show_status(st);
free(user_tmp);
cla_destroy(cla);
ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
return st;
}
free(user_tmp);
cla_destroy(cla);
ADT_Vector_destroy(&v);
+ array_destroy(data, IN_FILE_FIELDS);
return OK;
}
diff --git a/source/sort.c b/source/sort.c
@@ -1,53 +0,0 @@
-#include "../include/sort.h"
-
-int credit_minmax(const void *a, const void *b)
-{
- user_t *A = (user_t *)a;
- user_t *B = (user_t *)b;
-
- return ((*A)->c > (*B)->c) ? 1 : 0;
-}
-
-int credit_maxmin(const void *a, const void *b)
-{
- user_t *A = (user_t *)a;
- user_t *B = (user_t *)b;
-
- return ((*A)->c > (*B)->c) ? 0 : 1;
-}
-
-int debt_minmax(const void *a, const void *b)
-{
- user_t *A = (user_t *)a;
- user_t *B = (user_t *)b;
-
- return ((*A)->d > (*B)->d) ? 1 : 0;
-}
-
-int debt_maxmin(const void *a, const void *b)
-{
- user_t *A = (user_t *)a;
- user_t *B = (user_t *)b;
-
- return ((*A)->d > (*B)->d) ? 0 : 1;
-}
-
-status_t sort_users(user_t *users, size_t l, char *order)
-{
- if(users == NULL || order == NULL)
- return ERROR_NULL_POINTER;
-
- if(!strcmp(order, "ca"))
- qsort(users, l, sizeof(user_t), credit_minmax);
-
- if(!strcmp(order, "cd"))
- qsort(users, l, sizeof(user_t), credit_maxmin);
-
- if(!strcmp(order, "da"))
- qsort(users, l, sizeof(user_t), debt_minmax);
-
- if(!strcmp(order, "dd"))
- qsort(users, l, sizeof(user_t), debt_maxmin);
-
- return OK;
-}
diff --git a/source/user.c b/source/user.c
@@ -72,7 +72,9 @@ status_t user_print_as_xml(const void *u, FILE *fp)
ADT_user_t *user = (ADT_user_t *)u;
- fprintf(fp, "id: %6ld| credits: %6ld| debits: %6ld\n", user->id, user->c, user->d);
+ fprintf(fp, "\t\t<%s>%ld</%s>\n", XML_STR_ID, user->id, XML_STR_ID);
+ fprintf(fp, "\t\t<%s>%ld</%s>\n", XML_STR_CREDIT, user->c, XML_STR_CREDIT);
+ fprintf(fp, "\t\t<%s>%ld</%s>\n", XML_STR_DEBIT, user->d, XML_STR_DEBIT);
return OK;
}
diff --git a/source/utils.c b/source/utils.c
@@ -0,0 +1,77 @@
+#include "../include/utils.h"
+
+status_t string_split(char *s, char **data, char *delim)
+{
+ char *p, *tmp;
+ size_t fields = 0;
+
+ for(p = s; (tmp = strtok(p, delim)); p = NULL)
+ strcpy(data[fields++], tmp);
+
+ if(fields != IN_FILE_FIELDS)
+ return ERROR_CORRUPT_DATA;
+
+ return OK;
+}
+
+
+void clean_buffer(char *buf)
+{
+ size_t i;
+
+ for(i = 0; i < IN_FILE_MAX_LEN; i++)
+ buf[i] = '\0';
+}
+
+void clean_array(char **data)
+{
+ size_t i, j;
+
+ for(i = 0; i < IN_FILE_FIELDS; i++) {
+ for(j = 0; j < IN_FILE_FIELDS_MAX_LEN; j++)
+ data[i][j] = '\0';
+ }
+}
+
+status_t array_destroy(char **data, size_t fields)
+{
+ size_t i;
+
+ if(data == NULL) return ERROR_NULL_POINTER;
+
+ for(i = 0; i < fields; i++) {
+ free(data[i]);
+ data[i] = NULL;
+ }
+
+ free(data);
+ return OK;
+}
+
+status_t get_date(time_t *e, char **data)
+{
+ struct tm tm;
+
+ if(e == NULL || data == NULL) return ERROR_NULL_POINTER;
+
+ /* Desactiva el horario de verano */
+ tm.tm_isdst = 0;
+
+ switch(data[POS_TXN_DATE][2]) {
+ case '/':
+ strptime(data[2], "%d/%m/%Y %H:%M:%S", &tm);
+ *e = mktime(&tm);
+ break;
+ case '-':
+ strptime(data[2], "%d-%m-%Y %H:%M:%S", &tm);
+ *e = mktime(&tm);
+ break;
+ case '.':
+ strptime(data[2], "%d.%m.%Y %H:%M:%S", &tm);
+ *e = mktime(&tm);
+ break;
+
+ default: return ERROR_CORRUPT_DATA; break;
+ }
+ return OK;
+}
diff --git a/source/vector.c b/source/vector.c
@@ -55,30 +55,6 @@ status_t ADT_Vector_destroy(ADT_Vector_t **v)
return OK;
}
-#define BUFFER_SIZE 100
-status_t ADT_Vector_load(ADT_Vector_t *v, FILE *fi)
-{
- char *b, *endptr;
- int *tmp;
-
- if(v == NULL || fi == NULL) return ERROR_NULL_POINTER;
-
- if((b = calloc(sizeof(char), BUFFER_SIZE)) == NULL)
- return ERROR_MEMORY;
-
- while(fgets(b, BUFFER_SIZE, fi))
- {
- tmp = (int *)malloc(sizeof(int));
-
- *tmp = (int)strtol(b, &endptr, 10);
- if(*endptr != '\n') return ERROR_CORRUPT_DATA;
-
- ADT_Vector_add(&v, tmp);
- }
-
- return OK;
-}
-
status_t ADT_Vector_set(ADT_Vector_t **v, void *e, size_t pos)
{
void ** aux;
@@ -173,7 +149,7 @@ status_t ADT_Vector_set_comparator(ADT_Vector_t *v, comparator_t pf)
return OK;
}
-status_t ADT_Vector_export_as_csv(ADT_Vector_t *v, FILE *fp, printer_t pf)
+status_t ADT_Vector_export_as_csv(const ADT_Vector_t *v, FILE *fp, printer_t pf)
{
status_t st;
size_t i;
@@ -187,20 +163,24 @@ status_t ADT_Vector_export_as_csv(ADT_Vector_t *v, FILE *fp, printer_t pf)
return OK;
}
-status_t ADT_Vector_export_as_xml(ADT_Vector_t *v, FILE *fp, printer_t pf)
+status_t ADT_Vector_export_as_xml(const ADT_Vector_t *v, FILE *fp, printer_t pf)
{
status_t st;
size_t i;
if(v == NULL) return ERROR_NULL_POINTER;
- fprintf(fp, "%s\n", STR_XML_HEADER);
- fprintf(fp, "<%s>\n", STR_XML_ROOT);
+ fprintf(fp, "%s\n", XML_STR_HEADER);
+ fprintf(fp, "<%s>\n", XML_STR_ROOT);
- for(i = 0; i < v->size; i++)
- if((st = (*pf)(v->a[i], fp)) != OK)
+ for(i = 0; i < v->size; i++){
+ fprintf(fp, "\t<%s>\n", XML_STR_ROW);
+ if((st = (*pf)(v->a[i], fp)) != OK)
return st;
- fprintf(fp, "</%s>\n", STR_XML_ROOT);
+ fprintf(fp, "\t</%s>\n", XML_STR_ROW);
+ }
+
+ fprintf(fp, "</%s>\n", XML_STR_ROOT);
return OK;
}