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:
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;