9511_project03

Command line program that parses a bank .csv file and generates and output file in format .csv or .xml containing the debits and credits of every user.
Index Commits Files Refs README LICENSE
commit 2d69a1ac6e1ea828c60759db91c4ce26308d45b1
parent 419878b94389b7edad5478e9e639bc86d24eabde
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Wed, 28 Jul 2021 18:54:16 -0300

Update: fusionated ADT_Vector_t with ADT_user_t

Diffstat:
MMakefile | 12+++++++++---
Mexamples/input_gen.py | 2+-
Minclude/cla.h | 2+-
Minclude/status.h | 1+
Minclude/user.h | 21+++++++++++++++++----
Minclude/vector.h | 12++++++++----
Msource/io.c | 40++++++++++++++++++++--------------------
Msource/main.c | 160++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Asource/main.c_orig | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msource/sort.c | 8++++----
Msource/user.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msource/vector.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
12 files changed, 522 insertions(+), 96 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,13 +1,13 @@
 CC=gcc
-CFLAGS=-pedantic -Wall
+CFLAGS=-pedantic -Wall -g
 SRCFOLDER=source
 HFOLDER=include
 PROGNAME=main
 
 all: main clean
 
-main: cla.o status.o sort.o io.o main.o user.o 
-    $(CC) $(CFLAGS) main.o cla.o status.o io.o sort.o user.o -o $(PROGNAME)
+main: cla.o status.o sort.o io.o main.o user.o vector.o
+    $(CC) $(CFLAGS) main.o cla.o status.o io.o sort.o user.o vector.o -o $(PROGNAME)
 
 main.o: $(HFOLDER)/cla.h $(HFOLDER)/status.h $(HFOLDER)/user.h
     $(CC) $(CFLAGS) -c $(SRCFOLDER)/main.c
@@ -15,6 +15,9 @@ main.o: $(HFOLDER)/cla.h $(HFOLDER)/status.h $(HFOLDER)/user.h
 cla.o: $(HFOLDER)/cla.h $(HFOLDER)/status.h
     $(CC) $(CFLAGS) -c $(SRCFOLDER)/cla.c
 
+vector.o: $(HFOLDER)/vector.h $(HFOLDER)/status.h
+    $(CC) $(CFLAGS) -c $(SRCFOLDER)/vector.c
+
 status.o: $(HFOLDER)/status.h
     $(CC) $(CFLAGS) -c $(SRCFOLDER)/status.c
 
@@ -30,6 +33,9 @@ user.o: $(HFOLDER)/status.h $(HFOLDER)/user.h
 clean:
     rm *.o
 
+run5:
+    ./main -fmt csv -out output.csv -in examples/test_file_5.csv -ti 1320498000 -tf 1320498046
+
 run20:
     ./main -fmt csv -out output.csv -in examples/test_file_20.csv -ti 1320498000 -tf 1320498046
 
diff --git a/examples/input_gen.py b/examples/input_gen.py
@@ -2,7 +2,7 @@ from string import digits
 from time import strftime, gmtime
 from random import randint, choice
 
-LINES = 50000000
+LINES = 5
 
 # OUTPUT:
 #     ID_TRANSACCION, ID_USUARIO, FECHA, MONTO, NUMERO DE TRAJETA, DESCRIPCION
diff --git a/include/cla.h b/include/cla.h
@@ -22,7 +22,7 @@ typedef enum {
 
 typedef struct {
     char *fmt, *fi, *fo;
-    unsigned long ti, tf, parsed_lines;
+    unsigned long ti, tf;
 } ADT_cla_t, *cla_t;
 
 status_t validate_arguments(int argc, char **argv);
diff --git a/include/status.h b/include/status.h
@@ -17,6 +17,7 @@ typedef enum {
     ERROR_MEMORY,
     ERROR_WRONG_FLAGS,
     ERROR_WRONG_TIME,
+    ERROR_INVALID_POS,
     ERROR_MISSING_ARGS,
     ERROR_OPENING_FILE,
     ERROR_CORRUPT_DATA,
diff --git a/include/user.h b/include/user.h
@@ -3,20 +3,33 @@
 
 #include "status.h"
 
+typedef unsigned long ulong;
+
 typedef struct {
-    size_t id;
-    long credit, debt;
+    /* id: user id / c: user credits / d: user debits */
+    ulong id, c, d;
 } ADT_user_t, *user_t;
 
 user_t user_find(const user_t *users, int id, size_t size);
 user_t user_dup(user_t src);
 
-status_t user_create(user_t *usr);
-status_t user_set_data(user_t *user, char **data);
+status_t user_create(ADT_user_t **);
+status_t user_set_data(ADT_user_t *, char **data);
+status_t user_add_amount(ADT_user_t *, long amount);
+
+int user_id_equal(const void *, const void *);
 
 void user_clean(user_t usr);
 
 status_t sort_users(user_t *users, size_t size, char *order);
 status_t destroy_users(user_t *users, size_t size);
 
+status_t user_printer(const void *, FILE *);
+
+int user_comparator(const void *, FILE *);
+
+int user_comparator_credits_minmax(const void *, const void *);
+int user_comparator_credits_maxmin(const void *, const void *);
+
+
 #endif
diff --git a/include/vector.h b/include/vector.h
@@ -9,11 +9,9 @@
 
 #include <stdlib.h>
 
-#include "types.h"
+#include "status.h"
 
 typedef status_t (*printer_t)(const void *, FILE *);
-/* typedef int (*comparator_t)(void *, void *); */
-
 typedef int (*comparator_t)(const void *, const void *);
 
 typedef struct {
@@ -21,6 +19,7 @@ typedef struct {
     size_t size, alloc;
 
     printer_t printer;
+    comparator_t comparator;
 
 } ADT_Vector_t;
 
@@ -29,10 +28,15 @@ 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_print(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 *);
 status_t ADT_Vector_sort(ADT_Vector_t *, comparator_t);
 
+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);
diff --git a/source/io.c b/source/io.c
@@ -1,6 +1,8 @@
 #include "../include/io.h"
 
-/* Lee los datos del archivo de entrada linea por linea mientras los procesa y asigna a un arreglo de usuarios */
+
+/*
+//Lee los datos del archivo de entrada linea por linea mientras los procesa y asigna a un arreglo de usuarios
 status_t process_file(cla_t cla, user_t **users, size_t *size)
 {
     FILE *fpi;
@@ -10,7 +12,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
     user_t user, user_found, *tmp;
     status_t st;
 
-    *size = cla->parsed_lines = 0;
+    *size = 0;
     alloc_size = INIT_SIZE;
     user = user_found = NULL;
 
@@ -36,7 +38,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
         fclose(fpi);
     }
 
-    /* En caso de haber algun error users no es liberado, se libera luego en main */
+    //En caso de haber algun error users no es liberado, se libera luego en main
     if(((*users) = (user_t *)malloc(sizeof(user_t) * INIT_SIZE)) == NULL) {
         free(buffer);
         free(user);
@@ -44,9 +46,9 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
         fclose(fpi);
     }
 
-    /* Lee los datos de el archivo de entrada linea por linea */ 
+    //Lee los datos de el archivo de entrada linea por linea 
     while(fgets(buffer, BUFFER_SIZE, fpi) != NULL) {
-        /* Extiende el arreglo de usuarios en caso de que haya poca memoria */
+    //    Extiende el arreglo de usuarios en caso de que haya poca memoria
         if(*size == alloc_size) {
             alloc_size *= GROWTH_FACTOR;
             if((tmp = realloc((*users), alloc_size * sizeof(user_t))) == NULL) {
@@ -58,7 +60,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
             (*users) = tmp;
         }
 
-        /* Divide el buffer en subarreglos segun un caracter delimitador */
+    //    Divide el buffer en subarreglos segun un caracter delimitador
         if((st = string_split(buffer, data, INPUT_FILE_DELIM)) != OK) {
             fclose(fpi);
             free(buffer);
@@ -66,7 +68,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
             return st;
         }
 
-        /* Asigna a 'user' id, creditos y debitos cargados en data */
+    //    Asigna a 'user' id, creditos y debitos cargados en data
         if((st = user_set_data(&user, data)) != OK) {
             destroy_data(data);
             free(buffer);
@@ -74,7 +76,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
             return st;
         }
 
-        /* Transforma la fecha leida a tiempo UNIX en segundos */
+    //    Transforma la fecha leida a tiempo UNIX en segundos
         if((st = get_date(&epoch, data)) != OK) {
             destroy_data(data);
             free(buffer);
@@ -82,7 +84,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
             return st;
         }
 
-        /* Comprueba que la fecha leida este dentro del rango de fechas ingresadas en CLA */
+    //    Comprueba que la fecha leida este dentro del rango de fechas ingresadas en CLA
         if(epoch < cla->ti) continue;
         else if(epoch > cla->tf) {
             free(user);
@@ -92,20 +94,18 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
             return OK;
         }
 
-        /* Busca el numero de id en los usuarios ya ingresados, si no lo encuentra agrega un usuario nuevo al arreglo de usuarios */
+    //    Busca el numero de id en los usuarios ya ingresados, si no lo encuentra agrega un usuario nuevo al arreglo de usuarios
         if((user_found = user_find(*users, user->id, *size)) != NULL) {
-            user_found->credit += user->credit;
-            user_found->debt += user->debt;
+            user_found->c += user->c;
+            user_found->d += user->d;
         } else {
             (*users)[(*size)++] = user_dup(user);
         }
 
-        cla->parsed_lines++;
-
         user_clean(user);
         clean_data(data);
         clean_buffer(buffer);
-    } /* End while */
+    } // End while 
 
     free(user);
     destroy_data(data);
@@ -113,7 +113,7 @@ status_t process_file(cla_t cla, user_t **users, size_t *size)
     fclose(fpi);
     return OK;
 }
-
+*/
 
 status_t string_split(char *s, char **data, char *delim)
 {
@@ -121,7 +121,7 @@ status_t string_split(char *s, char **data, char *delim)
     size_t fields = 0;
 
     for(p = s; (tmp = strtok(p, delim)); p = NULL)
-        data[fields++] = strdup(tmp);
+        strcpy(data[fields++], tmp);
 
     if(fields != INPUT_FILE_FIELDS)
         return ERROR_CORRUPT_DATA;
@@ -172,7 +172,7 @@ status_t export_data_as_csv(FILE *fo, const user_t *users, size_t size)
 
     for(i = 0; i < size; i++)
         fprintf(fo, "%ld%s%ld%s%ld\n", users[i]->id, CSV_OUTPUT_DELIM,\
-                users[i]->credit, CSV_OUTPUT_DELIM, users[i]->debt);
+                users[i]->c, CSV_OUTPUT_DELIM, users[i]->d);
 
     return OK;
 }
@@ -189,8 +189,8 @@ status_t export_data_as_xml(FILE *fo, const user_t *users, size_t size)
     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]->credit, XML_CREDIT_CLOSE);
-        fprintf(fo, "\t\t%s%ld%s\n", XML_DEBT_OPEN, users[i]->debt, XML_DEBT_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);
     }
 
diff --git a/source/main.c b/source/main.c
@@ -3,18 +3,25 @@
 #include "../include/user.h"
 #include "../include/sort.h"
 #include "../include/status.h"
+#include "../include/vector.h"
 
-/* "ca" - creditos ascendentes | "cd" - creditos descendentes
- * "da" - debitos ascendentes  | "dd" - debitos descendentes */
-#define SORTING_ORDER    "cd"
-#define PRINT_EXIT_SUCCESS_MSG
+#define BUFFER_INIT_SIZE    100
+#define INPUT_FILE_DELIM    ","
+#define INPUT_FILE_FIELDS    6    
 
 int main (int argc, char *argv[])
 {
     status_t st;
     cla_t cla;
-    user_t *users;
-    size_t size;
+    ADT_Vector_t *v;
+    ADT_user_t *user, *user_tmp;
+    char *b, *endptr;
+    char **data;
+    size_t i, j;
+    FILE *fi;
+    long amount;
+
+    user = NULL;
 
     /* Valida que los argumentos sean correctos */
     if((st = validate_arguments(argc, argv)) != OK) {
@@ -28,48 +35,151 @@ int main (int argc, char *argv[])
         return st;
     }
 
-    /* Asigna a la estructura 'cla' los argumentos ingresados */
-    if((st = cla_setup(argc, argv, &cla)) != OK) {
+    /* Crea un vector */
+    if((st = ADT_Vector_create(&v)) != OK) {
         show_status(st);
+        cla_destroy(&cla);
         return st;
     }
 
-    /* Carga en users los usuarios desde el archivo de entrada */
-    if((st = process_file(cla, &users, &size)) != OK) {
+    if((st = ADT_Vector_set_printer(v, user_printer)) != OK) {
         show_status(st);
         cla_destroy(&cla);
-        destroy_users(users, size);
+        ADT_Vector_destroy(&v);
         return st;
     }
 
-    /* Ordena los usuarios con orden SORTING_ORDER */
-    if((st = sort_users(users, size, SORTING_ORDER)) != OK) {
+    /* Asigna a la estructura 'cla' los argumentos ingresados */
+    if((st = cla_setup(argc, argv, &cla)) != OK) {
         show_status(st);
         cla_destroy(&cla);
-        destroy_users(users, size);
+        ADT_Vector_destroy(&v);
         return st;
     }
 
-    /* Imprime los datos cargados en users a un archivo de salida */
-    if((st = export_data(cla, users, size)) != OK) {
-        show_status(st);
+
+    b = calloc(sizeof(char), BUFFER_INIT_SIZE);
+    data = malloc(sizeof(char *) * INPUT_FILE_FIELDS);
+
+    if(b == NULL || data == NULL) {
+        free(b);
+        show_status(ERROR_MEMORY);
         cla_destroy(&cla);
-        destroy_users(users, size);
-        return st;
+        ADT_Vector_destroy(&v);
+        return ERROR_MEMORY;
+    }
+
+    /* Asigna memoria cada puntero dentro de data */
+    for(i = 0; i < INPUT_FILE_FIELDS; i++) {
+        if((data[i] = calloc(sizeof(char), BUFFER_INIT_SIZE)) == NULL) {
+            show_status(ERROR_MEMORY);
+            for(j = 0; j < i; j++)
+                free(data[j]);
+
+            free(b);
+            cla_destroy(&cla);
+            ADT_Vector_destroy(&v);
+            return ERROR_MEMORY;
+        }
+    }
+        
+    /* Abre el archivo de entrada */
+    if((fi = fopen(cla->fi, "rt")) == NULL) {
+        show_status(ERROR_OPENING_FILE);
+        for(j = 0; j < INPUT_FILE_FIELDS; j++)
+            free(data[j]);
+
+        free(b);
+        cla_destroy(&cla);
+        ADT_Vector_destroy(&v);
+        return ERROR_OPENING_FILE;
+    }
+
+    ADT_Vector_set_comparator(v, user_id_equal);
+
+    user_tmp = NULL;
+    user_create(&user_tmp);
+
+    while(fgets(b, BUFFER_INIT_SIZE, fi)) {
+        string_split(b, data, INPUT_FILE_DELIM);
+        user_set_data(user_tmp, data);
+
+        amount = strtol(data[POS_AMOUNT], &endptr, 10);
+        if(*endptr != '\0') return ERROR_CORRUPT_DATA;
+
+        if((user = ADT_Vector_get_elem(v, user_tmp)) != NULL) {
+            /* El usuario ya existe */
+            user_add_amount(user, amount);
+        }
+        else { 
+            /* El usuario no existe */
+            user_create(&user);
+            user_set_data(user, data);
+            ADT_Vector_add(&v, user);
+        }
     }
 
+    ADT_Vector_sort(v, user_comparator_credits_maxmin);
+
+    ADT_Vector_print(v, stdout);
+
+    for(j = 0; j < INPUT_FILE_FIELDS; j++)
+        free(data[j]);
+
+    free(data);
+    free(b);
+    free(user_tmp);
+    fclose(fi);
+    cla_destroy(&cla);
+    ADT_Vector_destroy(&v);
+    return OK;
+}
+
+
+
+
+
+
+/*
+
+// "ca" - creditos ascendentes | "cd" - creditos descendentes
+// "da" - debitos ascendentes  | "dd" - debitos descendentes
+#define SORTING_ORDER    "cd"
+#define PRINT_EXIT_SUCCESS_MSG
+
+
 
 #ifdef PRINT_EXIT_SUCCESS_MSG
 
-    /* Imprime un mensaje para darle a conocer al usuario
-     * que todo se ejecuto correctamente    */
+    // Imprime un mensaje para darle a conocer al usuario
+    // que todo se ejecuto correctamente
     printf("\n%s\n%s%ld\n%s%ld\n", EXIT_SUCCESS_MSG, USERS_REGISTERED_MSG,\
             size, PROCESED_LINES_MSG, cla->parsed_lines);
 
 #endif
+*/
 
-    cla_destroy(&cla);
-    destroy_users(users, size);
 
-    return OK;
-}
+    /* Carga en users los usuarios desde el archivo de entrada */
+    /* if((st = process_file(cla, &users, &size)) != OK) { */
+    /*     show_status(st); */
+    /*     cla_destroy(&cla); */
+    /*     destroy_users(users, size); */
+    /*     return st; */
+    /* } */
+
+    /* Ordena los usuarios con orden SORTING_ORDER */
+    /* if((st = sort_users(users, size, SORTING_ORDER)) != OK) { */
+    /*     show_status(st); */
+    /*     cla_destroy(&cla); */
+    /*     destroy_users(users, size); */
+    /*     return st; */
+    /* } */
+
+    /* Imprime los datos cargados en users a un archivo de salida */
+    /* if((st = export_data(cla, users, size)) != OK) { */
+    /*     show_status(st); */
+    /*     cla_destroy(&cla); */
+    /*     destroy_users(users, size); */
+    /*     return st; */
+    /* } */
diff --git a/source/main.c_orig b/source/main.c_orig
@@ -0,0 +1,182 @@
+#include "../include/io.h"
+#include "../include/cla.h"
+#include "../include/user.h"
+#include "../include/sort.h"
+#include "../include/status.h"
+#include "../include/vector.h"
+
+#define BUFFER_INIT_SIZE    100
+#define INPUT_FILE_DELIM    ","
+#define INPUT_FILE_FIELDS    6    
+
+int main (int argc, char *argv[])
+{
+    status_t st;
+    cla_t cla;
+    ADT_Vector_t *v;
+    user_t user;
+    char *b, *endptr;
+    char **data;
+    size_t i, j;
+    FILE *fi;
+    long id, amount;
+    void *up;
+
+    user = NULL;
+
+    /* Valida que los argumentos sean correctos */
+    if((st = validate_arguments(argc, argv)) != OK) {
+        show_status(st);
+        return st;
+    }
+
+    ADT_Vector_set_comparator(v, user_id_equal);
+
+    /* Asigna memoria a cla */
+    if((st = cla_create(&cla)) != OK) {
+        show_status(st);
+        return st;
+    }
+
+    /* Crea un vector */
+    if((st = ADT_Vector_create(&v)) != OK) {
+        show_status(st);
+        cla_destroy(&cla);
+        return st;
+    }
+
+    if((st = ADT_Vector_set_printer(v, user_printer)) != OK) {
+        show_status(st);
+        cla_destroy(&cla);
+        ADT_Vector_destroy(&v);
+        return st;
+    }
+
+    /* Asigna a la estructura 'cla' los argumentos ingresados */
+    if((st = cla_setup(argc, argv, &cla)) != OK) {
+        show_status(st);
+        cla_destroy(&cla);
+        ADT_Vector_destroy(&v);
+        return st;
+    }
+
+
+    b = calloc(sizeof(char), BUFFER_INIT_SIZE);
+    data = malloc(sizeof(char *) * INPUT_FILE_FIELDS);
+
+    if(b == NULL || data == NULL) {
+        free(b);
+        show_status(ERROR_MEMORY);
+        cla_destroy(&cla);
+        ADT_Vector_destroy(&v);
+        return ERROR_MEMORY;
+    }
+
+    /* Asigna memoria cada puntero dentro de data */
+    for(i = 0; i < INPUT_FILE_FIELDS; i++) {
+        if((data[i] = calloc(sizeof(char), BUFFER_INIT_SIZE)) == NULL) {
+            show_status(ERROR_MEMORY);
+            for(j = 0; j < i; j++)
+                free(data[j]);
+
+            free(b);
+            cla_destroy(&cla);
+            ADT_Vector_destroy(&v);
+            return ERROR_MEMORY;
+        }
+    }
+        
+    /* Abre el archivo de entrada */
+    if((fi = fopen(cla->fi, "rt")) == NULL) {
+        show_status(ERROR_OPENING_FILE);
+        for(j = 0; j < INPUT_FILE_FIELDS; j++)
+            free(data[j]);
+
+        free(b);
+        cla_destroy(&cla);
+        ADT_Vector_destroy(&v);
+        return ERROR_OPENING_FILE;
+    }
+
+    while(fgets(b, BUFFER_INIT_SIZE, fi)) {
+        string_split(b, data, INPUT_FILE_DELIM);
+
+        id = strtol(data[POS_USER_ID], &endptr, 10);
+        if(*endptr != '\0') return ERROR_CORRUPT_DATA;
+
+        amount = strtol(data[POS_AMOUNT], &endptr, 10);
+        if(*endptr != '\0') return ERROR_CORRUPT_DATA;
+
+        if((user = (user_t)ADT_Vector_get_elem(v, user)) != NULL) {
+            /* El usuario ya existe */
+            user_add_amount(&user, amount);
+            printf("el usuario ya existe: %ld\n", user->id);
+        }
+        else { 
+            /* El usuario no existe */
+            user_create(&user);
+            user_set_data(&user, data);
+            /* user->id = id; */
+            /* user_add_amount(&user, amount); */
+        }
+
+        up = user;
+
+        ADT_Vector_add(&v, up);
+        /* printf("%ld\n", user->id); */
+    }
+
+    /* ADT_Vector_print(v, stdout); */
+    /* cla_destroy(&cla); */
+    /* ADT_Vector_destroy(&v); */
+    return OK;
+}
+
+
+
+
+
+
+/*
+
+// "ca" - creditos ascendentes | "cd" - creditos descendentes
+// "da" - debitos ascendentes  | "dd" - debitos descendentes
+#define SORTING_ORDER    "cd"
+#define PRINT_EXIT_SUCCESS_MSG
+
+
+
+#ifdef PRINT_EXIT_SUCCESS_MSG
+
+    // Imprime un mensaje para darle a conocer al usuario
+    // que todo se ejecuto correctamente
+    printf("\n%s\n%s%ld\n%s%ld\n", EXIT_SUCCESS_MSG, USERS_REGISTERED_MSG,\
+            size, PROCESED_LINES_MSG, cla->parsed_lines);
+
+#endif
+*/
+
+
+    /* Carga en users los usuarios desde el archivo de entrada */
+    /* if((st = process_file(cla, &users, &size)) != OK) { */
+    /*     show_status(st); */
+    /*     cla_destroy(&cla); */
+    /*     destroy_users(users, size); */
+    /*     return st; */
+    /* } */
+
+    /* Ordena los usuarios con orden SORTING_ORDER */
+    /* if((st = sort_users(users, size, SORTING_ORDER)) != OK) { */
+    /*     show_status(st); */
+    /*     cla_destroy(&cla); */
+    /*     destroy_users(users, size); */
+    /*     return st; */
+    /* } */
+
+    /* Imprime los datos cargados en users a un archivo de salida */
+    /* if((st = export_data(cla, users, size)) != OK) { */
+    /*     show_status(st); */
+    /*     cla_destroy(&cla); */
+    /*     destroy_users(users, size); */
+    /*     return st; */
+    /* } */
diff --git a/source/sort.c b/source/sort.c
@@ -5,7 +5,7 @@ int credit_minmax(const void *a, const void *b)
     user_t *A = (user_t *)a;
     user_t *B = (user_t *)b;
 
-    return ((*A)->credit > (*B)->credit) ? 1 : 0;
+    return ((*A)->c > (*B)->c) ? 1 : 0;
 }
 
 int credit_maxmin(const void *a, const void *b)
@@ -13,7 +13,7 @@ int credit_maxmin(const void *a, const void *b)
     user_t *A = (user_t *)a;
     user_t *B = (user_t *)b;
 
-    return ((*A)->credit > (*B)->credit) ? 0 : 1;
+    return ((*A)->c > (*B)->c) ? 0 : 1;
 }
 
 int debt_minmax(const void *a, const void *b)
@@ -21,7 +21,7 @@ int debt_minmax(const void *a, const void *b)
     user_t *A = (user_t *)a;
     user_t *B = (user_t *)b;
 
-    return ((*A)->debt > (*B)->debt) ? 1 : 0;
+    return ((*A)->d > (*B)->d) ? 1 : 0;
 }
 
 int debt_maxmin(const void *a, const void *b)
@@ -29,7 +29,7 @@ int debt_maxmin(const void *a, const void *b)
     user_t *A = (user_t *)a;
     user_t *B = (user_t *)b;
 
-    return ((*A)->debt > (*B)->debt) ? 0 : 1;
+    return ((*A)->d > (*B)->d) ? 0 : 1;
 }
 
 status_t sort_users(user_t *users, size_t l, char *order)
diff --git a/source/user.c b/source/user.c
@@ -1,13 +1,13 @@
 #include "../include/user.h"
 
-status_t user_create(user_t *usr)
+status_t user_create(ADT_user_t **user)
 {
-    if(((*usr) = (user_t)malloc(sizeof(ADT_user_t))) == NULL)
+    if((*user = (ADT_user_t *)malloc(sizeof(ADT_user_t))) == NULL)
         return ERROR_MEMORY;
 
-    (*usr)->id = 0;
-    (*usr)->credit = 0;
-    (*usr)->debt = 0;
+    (*user)->id = 0;
+    (*user)->c = 0;
+    (*user)->d = 0;
 
     return OK;
 }
@@ -15,38 +15,48 @@ status_t user_create(user_t *usr)
 void user_clean(user_t usr)
 {
     usr->id = 0;
-    usr->credit = 0;
-    usr->debt = 0;
+    usr->c = 0;
+    usr->d = 0;
 }
 
-status_t user_set_data(user_t *user, char **data) 
+status_t user_set_data(ADT_user_t *user, char **data) 
 {
     char *endptr;
     long amount;
 
     if(data == NULL || user == NULL) return ERROR_NULL_POINTER;
 
-    (*user)->id = strtol(data[POS_USER_ID], &endptr, 10);
+    user->id = strtol(data[POS_USER_ID], &endptr, 10);
     if(*endptr != '\0') return ERROR_CORRUPT_DATA;
 
     amount = strtol(data[POS_AMOUNT], &endptr, 10);
     if(*endptr != '\0') return ERROR_CORRUPT_DATA;
 
-    if(amount > 0) (*user)->credit = amount;
-    else if(amount < 0) (*user)->debt = -amount; /* '-=' Para eliminar el menos    */
+    if(amount > 0) user->c = amount;
+    else if(amount < 0) user->d = -amount; /* '-=' Para eliminar el menos    */
 
     return OK;
 }
 
-user_t user_dup(user_t src)
+status_t user_add_amount(ADT_user_t *user, long amount)
 {
-    user_t dst = NULL;
+    if(user == NULL) return ERROR_NULL_POINTER;
+
+    if(amount > 0) user->c += amount;
+    else if(amount < 0) user->d -= amount; /* '-=' Para eliminar el menos    */
+
+    return OK;
+}
+
+ADT_user_t *user_dup(user_t src)
+{
+    ADT_user_t *dst = NULL;
 
     user_create(&dst);
 
     dst->id = src->id;
-    dst->credit = src->credit;
-    dst->debt = src->debt;
+    dst->c = src->c;
+    dst->d = src->d;
 
     return dst;
 }
@@ -74,3 +84,56 @@ status_t destroy_users(user_t *users, size_t size)
     free(users);
     return OK;
 }
+
+status_t user_printer(const void *u, FILE *fp)
+{
+    if(u == NULL || fp == NULL) return ERROR_NULL_POINTER;
+
+    ADT_user_t *user = (ADT_user_t *)u;
+
+    fprintf(fp, "id: %6ld| credits: %6ld| debits: %6ld\n", user->id, user->c, user->d);
+
+    return OK;
+}
+
+int user_id_equal(const void *a, const void *b)
+{
+    ADT_user_t *A, *B;
+
+    if(a == NULL || b == NULL) return ERROR_NULL_POINTER;
+
+    A = (ADT_user_t *)a;
+    B = (ADT_user_t *)b;
+
+    if(A->id == B->id) return 1;
+
+    return 0;
+}
+
+int user_comparator_credits_minmax(const void *a, const void *b)
+{
+    user_t A, B;
+
+    if(a == NULL || b == NULL) return ERROR_NULL_POINTER;
+
+    A = *(user_t *)a;
+    B = *(user_t *)b;
+
+    if(A->c > B->c) return 1;
+    else if(A->c == B->c) return 0;
+    return -1;
+}  
+
+int user_comparator_credits_maxmin(const void *a, const void *b)
+{
+    user_t A, B;
+
+    if(a == NULL || b == NULL) return ERROR_NULL_POINTER;
+
+    A = *(user_t *)a;
+    B = *(user_t *)b;
+
+    if(A->c < B->c) return 1;
+    else if(A->c == B->c) return 0;
+    return -1;
+}  
diff --git a/source/vector.c b/source/vector.c
@@ -1,14 +1,4 @@
-#include "vector.h"
-
-void swap(void *a, void *b)
-{
-    int *A = (int *)a;
-    int *B = (int *)b;
-
-    int tmp = *A;
-    *A = *B;
-    *B = tmp;
-}
+#include "../include/vector.h"
 
 status_t ADT_Vector_create(ADT_Vector_t **v)
 {
@@ -23,6 +13,7 @@ status_t ADT_Vector_create(ADT_Vector_t **v)
     (*v)->size = 0;
     (*v)->alloc = VECTOR_INIT_SIZE;
     (*v)->printer = NULL;
+    (*v)->comparator = NULL;
 
     return OK;
 }
@@ -80,7 +71,7 @@ status_t ADT_Vector_load(ADT_Vector_t *v, FILE *fi)
         tmp = (int *)malloc(sizeof(int));
 
         *tmp = (int)strtol(b, &endptr, 10);
-        if(*endptr != '\n') return ERROR_CORRUPT_FILE;
+        if(*endptr != '\n') return ERROR_CORRUPT_DATA;
 
         ADT_Vector_add(&v, tmp);
 
@@ -90,7 +81,60 @@ status_t ADT_Vector_load(ADT_Vector_t *v, FILE *fi)
     return OK;
 }
 
-status_t ADT_Vector_print(ADT_Vector_t *v, FILE *fp)
+status_t ADT_Vector_set(ADT_Vector_t **v, void *e, size_t pos)
+{
+    void ** aux;
+    size_t i, alloc_size;
+
+    if(v == NULL || e == NULL) return ERROR_NULL_POINTER;
+    else if(pos > (*v)->size) return ERROR_INVALID_POS;
+
+    alloc_size = (*v)->alloc;
+
+    /* Cuenta cuanto tiene que alargar el arreglo p/ que entre el nuevo elemento */
+    while(pos >= alloc_size) {
+        alloc_size *= VECTOR_GROWTH_FACTOR;
+    }
+
+    /* Extiende el arreglo en caso de que no haya memoria suficiente */
+    if(pos > (*v)->alloc) {
+        if((aux = (void **)realloc((*v)->a, sizeof(void *) * alloc_size)) == NULL)
+            return ERROR_MEMORY;
+        else {
+            (*v)->a = aux;
+            (*v)->alloc = alloc_size;
+        }
+    }
+
+    for(i = (*v)->size; i < pos; i++) {
+        (*v)->a[pos] = NULL;
+    }
+
+    (*v)->a[pos] = e;
+
+    if(pos >= (*v)->size) {
+        (*v)->size = (pos + 1);
+    }
+
+    return OK;
+}
+
+void *ADT_Vector_get_elem(const ADT_Vector_t *v, void *e)
+{
+    size_t i;
+
+    if(v == NULL || e == NULL) return NULL;
+
+    for(i = 0; i < v->size; i++) { 
+        if(v->comparator(e, v->a[i])) {
+            return v->a[i];
+        }
+    }
+
+    return NULL;
+}
+
+status_t ADT_Vector_print(const ADT_Vector_t *v, FILE *fp)
 {
     size_t i;
 
@@ -107,12 +151,6 @@ status_t ADT_Vector_sort(ADT_Vector_t *v, comparator_t pf)
 {
     if(v == NULL) return ERROR_NULL_POINTER;
 
-    /* Bubble sort */
-    /* for(size_t i = 0; i < v->size; i++) */
-    /*     for(size_t j = 0; j < (v->size - i - 1); j++) */
-    /*         if(pf(v->a[j], v->a[j + 1]) > 0) */
-    /*             swap(v->a[j], v->a[j + 1]); */
-
     /* Quick sort */
     qsort(v->a, v->size, sizeof(void *), pf);
 
@@ -128,6 +166,15 @@ status_t ADT_Vector_set_printer(ADT_Vector_t *v, printer_t pf)
     return OK;
 }
 
+status_t ADT_Vector_set_comparator(ADT_Vector_t *v, comparator_t pf)
+{
+    if(v == NULL) return ERROR_NULL_POINTER;
+
+    v->comparator = pf;
+
+    return OK;
+}
+
 status_t ADT_Vector_export_as_csv(ADT_Vector_t *v, FILE *fp, printer_t pf)
 {
     status_t st;