9511_project03

project 3 for algorithms & programming I (9511) prof. Cardozo
Index Commits Files Refs README LICENSE
commit 3ae4b956f9251c372ff86f743afb905df7ef47ae
parent 7de7356a1b085cf76c9818d475f1145e44a62a16
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Wed, 28 Jul 2021 23:24:08 -0300

Update:

Diffstat:
MMakefile | 8++++----
Dinclude/io.h | 66------------------------------------------------------------------
Dinclude/sort.h | 18------------------
Minclude/user.h | 1+
Ainclude/utils.h | 36++++++++++++++++++++++++++++++++++++
Minclude/vector.h | 10+++-------
Dsource/io.c | 112-------------------------------------------------------------------------------
Msource/main.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Dsource/sort.c | 53-----------------------------------------------------
Msource/user.c | 4+++-
Asource/utils.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msource/vector.c | 42+++++++++++-------------------------------
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;
 }