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 6a255581fa73bc0f5a12ea53a0b26e3b9c0a8c73
parent 037c246f134873305f86d3ccc3a38ec29308ff66
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Fri,  6 Aug 2021 20:38:23 -0300

Getting ready to deliver 'entrega_3'

Diffstat:
Mexamples/input_gen.py | 6+++---
Minclude/load.h | 2++
Minclude/user.h | 2+-
Minclude/vector.h | 5++---
Msource/load.c | 90++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msource/user.c | 31++++++++++++++-----------------
Msource/utils.c | 2+-
Msource/vector.c | 57+++++++++++++++++++++++++--------------------------------
8 files changed, 98 insertions(+), 97 deletions(-)
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 = 10000
+LINES = 15
 
 # OUTPUT:
 #     ID_TRANSACCION, ID_USUARIO, FECHA, MONTO, NUMERO DE TRAJETA, DESCRIPCION
@@ -92,9 +92,9 @@ def generate_card(type):
 def generate_file(max_lines):
     id_transaction_base = 123400
     id_user_base = 1
-    id_user_max = 30000
+    id_user_max = 10
     amount_base = 1
-    amount_max = 10000
+    amount_max = 100
     for i in range(max_lines):
         id_transaction = (i + id_transaction_base)
         id_user = randint(id_user_base, id_user_max)
diff --git a/include/load.h b/include/load.h
@@ -7,6 +7,8 @@
 #include "../include/vector.h"
 #include "../include/status.h"
 
+#define STR_MSG_END_PROCSS    "End processing input file\nLines processed: "
+
 status_t load_users_to_vector(ADT_Vector_t **, ADT_cla_t *);
 
 #endif
diff --git a/include/user.h b/include/user.h
@@ -14,9 +14,9 @@ typedef struct {
 } ADT_user_t;
 
 status_t user_create(ADT_user_t **);
+status_t user_dup(ADT_user_t *, ADT_user_t *);
 status_t user_destroy(ADT_user_t **);
 
-status_t user_set_data_from_str(ADT_user_t *, char **);
 status_t user_set_data(ADT_user_t *, ulong, ulong, ulong);
 
 status_t user_add_amount(ADT_user_t *, long);
diff --git a/include/vector.h b/include/vector.h
@@ -28,12 +28,11 @@ 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_set_elem(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 *, void *);
-
+status_t ADT_Vector_set_elem(ADT_Vector_t **, void *, size_t);
+status_t ADT_Vector_get_elem(const ADT_Vector_t *, void **, size_t);
 status_t ADT_Vector_get_elem_pos(const ADT_Vector_t *, void *, size_t *);
 
 status_t ADT_Vector_set_printer(ADT_Vector_t *, printer_t);
diff --git a/source/load.c b/source/load.c
@@ -4,10 +4,11 @@ status_t load_users_to_vector(ADT_Vector_t **v, ADT_cla_t *cla)
 {
     status_t st;
     char buffer[IN_FILE_MAX_LEN];
-    char *endptr, **data;
-    ADT_user_t *user, *user_tmp;
+    char *endptr1, *endptr2, **data;
+    ADT_user_t *u1, *u2, *u3;
     time_t epoch;
     long long amount;
+    size_t user_pos, parsed_lines;
     ulong id, c, d;
 
     if(v == NULL || cla == NULL) return ERROR_NULL_POINTER;
@@ -15,29 +16,24 @@ status_t load_users_to_vector(ADT_Vector_t **v, ADT_cla_t *cla)
     if((st = create_2darray(&data, IN_FILE_FIELDS, IN_FILE_FIELDS_MAX_LEN)) != OK)
         return st;
 
-    /* Crea un usuario temporal */
-    if((st = user_create(&user_tmp)) != OK) {
-        destroy_2darray(data, IN_FILE_FIELDS);
-        return st;
-    }
-
+    parsed_lines = 0;
     while(fgets(buffer, IN_FILE_MAX_LEN, cla->fi)) {
-        if((st = string_split(buffer, data, IN_FILE_DELIM)) != OK) {
-            free(user_tmp);
+        if((st = user_create(&u1)) != OK) {
             destroy_2darray(data, IN_FILE_FIELDS);
             return st;
         }
 
-        id = strtol(data[POS_USER_ID], &endptr, 10);
-        if(*endptr != '\0') {
-            free(user_tmp);
+        if((st = string_split(buffer, data, IN_FILE_DELIM)) != OK) {
+            free(u1);
             destroy_2darray(data, IN_FILE_FIELDS);
-            return ERROR_CORRUPT_DATA;
+            return st;
         }
 
-        amount = strtol(data[POS_AMOUNT], &endptr, 10);
-        if(*endptr != '\0') {
-            free(user_tmp);
+        id = strtol(data[POS_USER_ID], &endptr1, 10);
+        amount = strtol(data[POS_AMOUNT], &endptr2, 10);
+
+        if(*endptr1 || *endptr2) {
+            free(u1);
             destroy_2darray(data, IN_FILE_FIELDS);
             return ERROR_CORRUPT_DATA;
         }
@@ -45,14 +41,14 @@ status_t load_users_to_vector(ADT_Vector_t **v, ADT_cla_t *cla)
         if(amount > 0) { c = amount; d = 0; }
         else if(amount < 0) { c = 0; d = -amount; }
 
-        if((st = user_set_data(user_tmp, id, c, d)) != OK) {
-            free(user_tmp);
+        if((st = user_set_data(u1, id, c, d)) != OK) {
+            free(u1);
             destroy_2darray(data, IN_FILE_FIELDS);
             return ERROR_CORRUPT_DATA;
         }
 
         if((st = get_date(&epoch, data[POS_TXN_DATE])) != OK){
-            free(user_tmp);
+            free(u1);
             destroy_2darray(data, IN_FILE_FIELDS);
             return ERROR_CORRUPT_DATA;
         }
@@ -63,48 +59,62 @@ status_t load_users_to_vector(ADT_Vector_t **v, ADT_cla_t *cla)
 
         /* Comprueba que la tarjeta usada en la transaccion sea la correcta */
         if(!is_valid_card(data[POS_CARD_NUMBER])) {
-            fprintf(stderr, "%s: %s\n",STR_INVALID_CARD_NUMBER, data[POS_CARD_NUMBER]);
+            fprintf(stderr, "%s: %s\n", STR_INVALID_CARD_NUMBER, data[POS_CARD_NUMBER]);
             continue;
         }
 
         /* Busca el id del usuario en el vector */
-        if((user = ADT_Vector_get_elem(*v, user_tmp)) != NULL) {
-            /* Si lo encuentra le suma el monto correspondiente */
-            if((st = user_add_amount(user, amount)) != OK) {
+        if((st = ADT_Vector_get_elem_pos(*v, u1, &user_pos)) == OK) {
+            /* Si llega aca lo encontrĂ³, entonces se lo asigna a un usuario temporal */
+            if((st = ADT_Vector_get_elem(*v, (void **)&u2, user_pos) != OK)) {
                 destroy_2darray(data, IN_FILE_FIELDS);
-                free(user_tmp);
+                free(u1);
                 return st;
             }
-        }
 
-        /* Si no lo encuentra crea un usuario nuevo */
-        else { 
-            if((st = user_create(&user)) != OK) {
+            /* Crea un usuario nuevo para almacenar la copia */
+            if((st = user_create(&u3)) != OK) {
                 destroy_2darray(data, IN_FILE_FIELDS);
-                free(user_tmp);
+                free(u1);
                 return st;
             }
 
-            if((st = user_set_data(user, id, c, d))) {
+            /* Copia el contenido del usuario */
+            *u3 = *u2;
+
+            /* Asigna a la copia el nuevo monto */
+            if(amount > 0) u3->c += amount;
+            else if(amount < 0) u2->d -= amount;
+
+            /* Asigna la copia al vector en el lugar que estaba el usuario original */
+            if((st = ADT_Vector_set_elem(v, u3, user_pos)) != OK) {
                 destroy_2darray(data, IN_FILE_FIELDS);
-                free(user_tmp);
-                return st;
+                free(u1);
             }
 
-            /* Y lo agrega al vector */
-            if((st = ADT_Vector_add(v, user)) != OK){
+            free(u1);
+            free(u2);
+        }
+
+        /* Hubo un error distinto a no encontrar el usuario */
+        else if(st != ELEM_NOT_FOUND) {
+                destroy_2darray(data, IN_FILE_FIELDS);
+                return st;
+        }
+
+        else { 
+            /* Si no lo encuentra entonces lo agrega al vector */
+            if((st = ADT_Vector_add(v, u1)) != OK){
                 destroy_2darray(data, IN_FILE_FIELDS);
-                free(user_tmp);
                 return st;
             }
         }
-        clean_buffer(buffer);
-        clean_array(data);
+        clean_buffer(buffer); clean_array(data);
+        parsed_lines++;
     } /* End while */
 
-        
     destroy_2darray(data, IN_FILE_FIELDS);
-    free(user_tmp);
+    printf("%s%8ld\n", STR_MSG_END_PROCSS, parsed_lines);
 
     return OK;
 }
diff --git a/source/user.c b/source/user.c
@@ -12,31 +12,28 @@ status_t user_create(ADT_user_t **user)
     return OK;
 }
 
-status_t user_destroy(ADT_user_t **user)
+status_t user_dup(ADT_user_t *src, ADT_user_t *dst)
 {
-    if(user == NULL) return ERROR_NULL_POINTER;
+    status_t st;
 
-    free(*user);
-    *user = NULL;
+    if(src == NULL || dst == NULL) return ERROR_NULL_POINTER;
+
+    if((st = user_create(&dst)) != OK)
+        return st;
+
+    dst->id = src->id;
+    dst->c = src->c;
+    dst->d = src->d;
 
     return OK;
 }
 
-status_t user_set_data_from_str(ADT_user_t *user, char **data) 
+status_t user_destroy(ADT_user_t **user)
 {
-    char *endptr;
-    long amount;
-
-    if(data == NULL || user == NULL) return ERROR_NULL_POINTER;
-
-    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(user == NULL) return ERROR_NULL_POINTER;
 
-    if(amount > 0) user->c = amount;
-    else if(amount < 0) user->d = -amount; /* '-=' Para eliminar el menos    */
+    free(*user);
+    *user = NULL;
 
     return OK;
 }
diff --git a/source/utils.c b/source/utils.c
@@ -73,7 +73,7 @@ bool is_valid_card(char *card_no)
     if(card_no == NULL) return false;
     if(strlen(card_no) != CARD_NO_VALID_LEN) return false;
 
-    for(i = 0, k = 0; i < 4; i++) {
+    for(i = 0, k = 0, sum = 0; i < 4; i++) {
         for(j = 0; j < 4; j++) {
             arr[i][j] = (card_no[k++] - '0');
             if(j % 2) {
diff --git a/source/vector.c b/source/vector.c
@@ -57,55 +57,48 @@ status_t ADT_Vector_destroy(ADT_Vector_t **v)
 
 status_t ADT_Vector_set_elem(ADT_Vector_t **v, void *e, size_t pos)
 {
-    void ** aux;
-    size_t i, alloc_size;
+    /* 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;
+    /* 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;
-    }
+    /* /1* Cuenta cuanto tiene que alargar el arreglo p/ que entre el nuevo elemento *1/ */
+    /* 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;
-    }
+    /* 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);
-    }
+    /* if(pos >= (*v)->size) { */
+    /*     (*v)->size = (pos + 1); */
+    /* } */
 
     return OK;
 }
 
-void *ADT_Vector_get_elem(const ADT_Vector_t *v, void *e)
+status_t ADT_Vector_get_elem(const ADT_Vector_t *v, void **e, size_t pos)
 {
-    size_t i;
-
-    if(v == NULL || e == NULL) return NULL;
+    if(v == NULL || e == NULL) return ERROR_NULL_POINTER;
 
-    for(i = 0; i < v->size; i++) { 
-        if(v->comparator(e, v->a[i])) {
-            return v->a[i];
-        }
-    }
+    *e = v->a[pos];
 
-    return NULL;
+    return OK;
 }
 
 status_t ADT_Vector_get_elem_pos(const ADT_Vector_t *v, void *e, size_t *pos)