9511_project01

project 1 for algorithms & programming I (9511) prof. Cardozo
Index Commits Files Refs README
commit 8c88c53d19e5c5edf43867eb69867e4c9170816d
parent 079b0ef6c40e936f61d157c988f5ab9aa56f4e43
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Mon,  8 Feb 2021 02:10:04 -0300

Update: now 'readlines' its divided into two separeted functions
called from main, read_file & print_file;

Diffstat:
MMakefile | 11+++++++----
Mload_country_codes.h | 2--
Mmacros.h | 2++
Mmain.c | 46+++++++++++++++++++++++++++++++++++-----------
Mmain.h | 18+++++++++++++++++-
Moutput.txt | 4----
Aprint_file.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aprint_file.h | 17+++++++++++++++++
Aread_file.c | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aread_file.h | 21+++++++++++++++++++++
Aread_file2.c | 3+++
Aread_file2.h | 21+++++++++++++++++++++
Mreadlines.c | 7++++++-
13 files changed, 369 insertions(+), 23 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,8 +4,8 @@ CFLAGS = -std=c99 -Wall -pedantic
 all: main clean
 
 
-main: main.o arguments.o perrors.o load_country_codes.o readlines.o
-    $(CC) $(CFLAGS) main.o arguments.o perrors.o load_country_codes.o readlines.o -o main 
+main: main.o arguments.o perrors.o load_country_codes.o read_file.o print_file.o
+    $(CC) $(CFLAGS) main.o arguments.o perrors.o load_country_codes.o read_file.o print_file.o -o main 
 
 main.o: main.c main.h arguments.h macros.h
     $(CC) -c main.c
@@ -19,8 +19,11 @@ perrors.o: main.c main.h
 load_country_codes.o: load_country_codes.h main.h
     $(CC) -c load_country_codes.c 
 
-readlines.o: readlines.h main.h
-    $(CC) -c readlines.c
+read_file.o: read_file.h main.h
+    $(CC) -c read_file.c
+
+print_file.o: print_file.h main.h
+    $(CC) -c print_file.c
 
 
 clean:
diff --git a/load_country_codes.h b/load_country_codes.h
@@ -3,8 +3,6 @@
 
 #include "main.h"
 
-#define COUNTRIES_NUMBER    1000
-#define ARRAYS_LENGTH        100
 
 typedef enum {
     CODE,
diff --git a/macros.h b/macros.h
@@ -10,4 +10,6 @@
 
 #define INITIAL_SIZE        1000
 
+typedef unsigned long ulong;
+
 #endif
diff --git a/main.c b/main.c
@@ -1,5 +1,5 @@
 //    
-//    Programa escrito por Martin J. Klockner
+//    Programa escrito por Martin J. KlÓ§ckner
 //        martin.cachari@gmail.com
 //        github.com/klewer-martin
 //
@@ -18,7 +18,8 @@
 #include "macros.h"
 #include "arguments.h"
 #include "load_country_codes.h"
-#include "readlines.h"
+#include "read_file.h"
+#include "print_file.h"
 #include "perrors.h"
 
 
@@ -32,31 +33,54 @@ int main(int argc, char * argv[])
 //    entrada y salida luego de validar que los argumentos recibidos sean correctos;
     char src[32], dest[32];
 
-//    El siguiente arreglo de dos dimensiones es donde se van a guardar los codigos
-//    de los paises;
+    FILE *fpi, *fpo;
+    ulong country, date, infected;
+    country = date = infected = 0;
+
+//    El siguiente arreglo de dos dimensiones es donde se van a guardar los
+//    codigos    de los paises;
     char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH];
 
 //    Valida de que los argumentos sean correctos y guarda los nombres de los
 //    archivos de entrada y salida en src y dest respectivamente, de haber algun
-//    error en el proceso devuelve un codigo de error de tipo status_t (definido 
+//    error en el proceso devuelve un codigo de error de tipo status_t (definido
 //    en main.h);
     if((st = validate_arguments(argc, argv, src, dest)) != OK) {
         print_error(st);
         return st;
     }
     
-//    Carga los codigos de error de los paises de acuerdo al standard iso3166 en el
-//    arreglo mencionado previamente 'country_codes', en caso de haber algun error 
-//    en el proceso devuelve dicho codigo e impreme por stderr un mensaje de error; 
+//    Carga los codigos de error de los paises de acuerdo al standard iso3166 en
+//    el arreglo mencionado previamente 'country_codes', en caso de haber algun
+//    error en el proceso devuelve dicho codigo e impreme por stderr un mensaje
+//    de error; 
     if((st = load_country_codes(country_codes)) != OK) {
         print_error(st);
         return ERROR_LOADING_COUNTRY_CODES;    
     }
 
-    if((st = readlines(src, dest, country_codes)) != OK) {
-        print_error(st);
+//    Abre el archivo de entrada en modo lectura, y el de salida en modo 
+//    escritura, si por algun motivo falla imprime un codigo de error;
+    if((fpi = fopen(src, "r")) == NULL)
+            return ERROR_READING_FILE;
+
+    if((fpo = fopen(dest, "w")) == NULL)
+            return ERROR_READING_FILE;
+
+
+    size_t line;
+    for(line = 0; (st = read_file(fpi, &country, &date, &infected)) == OK; line++) {
+        if(line != 0)
+            print_file(fpo, country_codes, &country, &date, &infected);
+
+        st = OK;
+    }
+
+    if(st != OK && st != END_OF_INPUT_FILE)
         return st;
-    }    
+
+    fclose(fpi);
+    fclose(fpo);
 
     printf(MSG_OK);
     return OK;
diff --git a/main.h b/main.h
@@ -10,6 +10,21 @@
 
 #define COUNTRY_CODES_FILE_NAME "iso3166-1.csv"
 
+#define COUNTRIES_NUMBER    1000
+#define ARRAYS_LENGTH        100
+
+#define COUNTRY_PROMPT "Pais"
+
+#define SIZE_OF_BUFF1    32
+#define SIZE_OF_BUFF2    32    
+
+#define INITIAL_SIZE 1000
+#define TIME_MAX_DIGITS 1000
+
+extern const char formato_de_la_fecha[];
+
+extern ulong country, date, infected;
+
 typedef enum {
     OK,
     IO_FILE_NOT_FOUND,
@@ -19,7 +34,8 @@ typedef enum {
     ERROR_PRINTING,
     ERROR_READING_FILE,
     ERROR_ALLOCATING_TIME,
-    ERROR_DATA_ON_FILE_MISSING    
+    ERROR_DATA_ON_FILE_MISSING,
+    END_OF_INPUT_FILE
 } status_t;
 
 
diff --git a/output.txt b/output.txt
@@ -10,8 +10,6 @@ Pais: Argentina
 Fecha: 15 Jan 2020
 Infectados: 9324
 
-Infectados por mes: 16589
-
 Pais: Colombia
 Fecha: 01 Jan 2020
 Infectados: 8234
@@ -24,8 +22,6 @@ Pais: Colombia
 Fecha: 15 Jan 2020
 Infectados: 9423
 
-Infectados por mes: 35246
-
 Pais: Germany
 Fecha: 01 Jan 2020
 Infectados: 8432
diff --git a/print_file.c b/print_file.c
@@ -0,0 +1,90 @@
+#include "print_file.h"
+
+const char formato_de_la_fecha[] = "%d %b %Y";
+
+status_t print_file(FILE *dest, char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH], ulong *country, ulong *date, ulong *infected) {
+
+            
+    char time_s[TIME_MAX_DIGITS];
+    time_translator(*(date), time_s, sizeof(time_s), "%m");
+//    month = atoi(time_s);
+//    printf("%d\n", month);
+//
+//    if(prev_country == 0 && prev_month == -1) {
+//        prev_country = country;
+//        prev_month = month;
+//    }
+//
+//    Imprime la suma de infectados por mes cada vez que cambia el pais;
+//    if(country == prev_country && month == prev_month) {
+//        infected_monthly += infected;
+//    }    
+//    else if(country != prev_country) {
+//        fprintf(fpo, "Infectados por mes: %lu\n\n", infected_monthly);    
+//        prev_country = country;
+//    }
+
+//    Imprime datos segun el archivo de entrada;
+    fprintf_country(dest, *(country), country_codes);
+    fprintf_date(dest, *(date));
+    fprintf_infected(dest, *(infected), '\n');
+
+    return OK;
+}
+
+
+status_t fprintf_country(FILE *dest, size_t country_code, char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH])
+{
+    if((country_codes == NULL) || (dest == NULL))
+        return ERROR_NULL_POINTER;
+
+    fprintf(dest, COUNTRY_PROMPT": %s\n", country_codes[country_code]);
+    return OK;
+}
+
+status_t fprintf_date(FILE *dest, size_t date)
+{
+    char time_c[TIME_MAX_DIGITS];
+    status_t st;
+
+    if(dest == NULL)
+        return ERROR_NULL_POINTER;
+
+    if((st = time_translator(date, time_c, sizeof(time_c), formato_de_la_fecha)) != OK)
+        return st;
+
+    fprintf(dest, "Fecha: %s\n", time_c);
+    return OK;
+}
+
+status_t fprintf_infected(FILE *dest, size_t infected, char newline)
+{
+    if(dest == NULL)
+        return ERROR_NULL_POINTER;
+
+    fprintf(dest, "Infectados: %lu\n%c", infected, newline);
+    return OK;
+}
+
+
+//    Traduce de la fecha de formato unix a format y lo guarda en res como
+//    como una cadena de caracteres;
+status_t time_translator(time_t unix_time, char *res, size_t size, const char *format) 
+{
+    if(res == NULL || format == NULL)
+        return ERROR_NULL_POINTER;
+
+    
+    struct tm *tmp = gmtime(&unix_time);
+
+    if (strftime(res, size, format, tmp) == 0) {
+        (void) fprintf(stderr,  "strftime(3): cannot format supplied "
+                                "date/time into buffer of size %u "
+                                "using: '%s'\n",
+                                (unsigned int)sizeof(res), format);
+        return ERROR_ALLOCATING_TIME;
+    }
+    return OK;
+}
+
+
diff --git a/print_file.h b/print_file.h
@@ -0,0 +1,17 @@
+#ifndef PRINT_FILE_H
+#define PRINT_FILE_H
+
+#include "main.h"
+
+//extern const char formato_de_la_fecha[];
+
+status_t print_file(FILE *dest, char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH], ulong *country, ulong *date, ulong *infected);
+
+status_t fprintf_country(FILE *dest, size_t country_code, char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH]);
+status_t fprintf_date(FILE *dest, size_t date);
+status_t fprintf_infected(FILE *dest, size_t infected, char newline);
+status_t clean_buffer(char *buffer, size_t size);
+status_t time_translator(time_t unix_time, char *res, size_t size, const char *format);
+
+
+#endif
diff --git a/read_file.c b/read_file.c
@@ -0,0 +1,150 @@
+
+#include "read_file.h"
+
+
+status_t read_file(FILE *src, u_long *country, u_long *date, u_long *infected)
+{
+
+//    Esta variable es para saber de que tipo de dato estamos hablando, si es un
+//    codigo de pais, una fecha o el numero de infectados;
+    data_t data;
+
+    size_t line, i, j;
+    status_t st;
+
+    char buff1[SIZE_OF_BUFF1];
+    char buff2[SIZE_OF_BUFF2];
+
+    clean_buffer(buff1, SIZE_OF_BUFF1);
+    clean_buffer(buff2, SIZE_OF_BUFF2);
+
+    char time_s[TIME_MAX_DIGITS];
+
+//    Lee de el archivo de entrada linea por linea y va guardando las 
+//    lineas en buff1 hasta que se terminen;
+    if(fgets(buff1, sizeof(buff1), src) == NULL)
+        return END_OF_INPUT_FILE;
+    
+//    Este 'if' es para evitar la primer linea que no contiene ningun
+//    tipo de dato;
+    for(i = 0, j = 0, data = PAIS; buff1[i] != '\0'; i++)
+    {
+        if((buff1[i] == ','))
+        {
+            i++;
+            switch(data) 
+            {
+                case PAIS: *(country) = atoi(buff2); break;
+                case DATE: *(date) = atol(buff2); j++; break;
+            }
+
+            data++;
+            j = 0;
+            clean_buffer(buff2, SIZE_OF_BUFF2);
+
+        } else if (buff1[i] == '\n') {
+            if(data != INFECTED) 
+                return ERROR_DATA_ON_FILE_MISSING;
+
+            data = PAIS;
+            *(infected) = atol(buff2);
+            clean_buffer(buff2, SIZE_OF_BUFF2);
+        }
+            switch(data) 
+            {
+                case PAIS: buff2[i] = buff1[i];    break;
+                case DATE: buff2[j] = buff1[i]; j++; break;
+                case INFECTED: buff2[j] = buff1[i]; j++; break;
+            }
+    }
+    return OK;
+}
+
+status_t clean_buffer(char *buffer, size_t size)
+{
+    if(buffer == NULL)
+        return ERROR_NULL_POINTER;
+
+    size_t i;
+    for(i = 0; i < size; i++)
+        buffer[i] = '\0';
+    
+    return OK;
+}
+
+
+
+/*
+//    Lee de el archivo de entrada linea por linea y va guardando las 
+//    lineas en buff1 hasta que se terminen;
+    for(line = 0; fgets(buff1, sizeof(buff1), src) != NULL; line++)
+    {
+//    Este 'if' es para evitar la primer linea que no contiene ningun tipo de dato;
+        if(line != 0) {
+//            Recorre el buff1 separando los datos de acuerdo a si es el codigo de
+//            un pais, una fecha o el numero de infectados;
+            for(i = 0, j = 0, data = PAIS; buff1[i] != '\0'; i++)
+            {
+//                Si encuentra una coma cambia el tipo de dato;
+                if((buff1[i] == ','))
+                {
+//                    Saltea la coma;                    
+                    i++;
+
+//                    De acuerdo al tipo de dato que se guardo hasta llegar a la
+//                    coma va a guardarlo de distinta manera, ej: si el dato que
+//                    se guardo en buff2 era el codigo de un PAIS, entonces lo 
+//                    guarda en la variable country, si el tipo de dato que se 
+//                    guardo en buff2 era una fecha entonces lo guarda en date, etc.
+//                    Solo puede ser PAIS o DATE, ya que INFECTADOS seria cuando
+//                    ecuentra un caracter de nueva linea;
+                    switch(data) 
+                    {
+                        case PAIS: *(country) = atoi(buff2); break;
+                        case DATE: *(date) = atol(buff2); j++; break;
+                    }
+
+
+//                    Como encontro una coma entonces el tipo de dato cambia;
+                    data++;
+
+//                    j vale cero porque es el indice de el buffer en el que se van
+//                    guardando los datos;
+                    j = 0;
+
+//                    Se limpia el buffer ya que se va a volver a utilizar;
+                    clean_buffer(buff2, SIZE_OF_BUFF2);
+
+
+//                Si en lugar de una coma se encuentra un caracter de nueva line 
+//                entonces significa que esta parado en el ultimo dato
+                } else if (buff1[i] == '\n') {
+
+//                    Si estamos parados en el ultimo dato y no es INFECTED,
+//                    entonces la variable datos no se incremento tres veces, por
+//                    lo cual se supone que falta un dato, devolviendo un codigo de
+//                    error;
+                    if(data != INFECTED) 
+                        return ERROR_DATA_ON_FILE_MISSING;
+
+//                    Si esta todo bien entonces el dato vuelve a ser PAIS que es 
+//                    el primer dato de el archivo de entrada
+                    data = PAIS;
+                    *(infected) = atol(buff2);
+                    clean_buffer(buff2, SIZE_OF_BUFF2);
+                }
+
+                switch(data) 
+                {
+                    case PAIS: buff2[i] = buff1[i];    break;
+                    case DATE: buff2[j] = buff1[i]; j++; break;
+                    case INFECTED: buff2[j] = buff1[i]; j++; break;
+                }
+            }
+
+        }
+    }
+
+    return OK;
+
+*/
diff --git a/read_file.h b/read_file.h
@@ -0,0 +1,21 @@
+#ifndef READLINES_H
+#define READLINES_H
+
+#include "main.h"
+#include "load_country_codes.h"
+
+typedef enum {
+    PAIS,
+    DATE,
+    INFECTED
+} data_t;
+
+status_t read_file(FILE *src, u_long *country, u_long *date, u_long *infected);
+
+status_t fprintf_date(FILE *dest, size_t data);
+status_t fprintf_infected(FILE *dest, size_t data, char newline);
+status_t clean_buffer(char *buffer, size_t size);
+status_t time_translator(time_t unix_time, char *res, size_t size, const char *format); 
+status_t fprintf_country(FILE *dest, size_t country_code, char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH]);
+
+#endif
diff --git a/read_file2.c b/read_file2.c
@@ -0,0 +1,3 @@
+#include "read_file2.h"
+
+
diff --git a/read_file2.h b/read_file2.h
@@ -0,0 +1,21 @@
+#ifndef READLINES_H
+#define READLINES_H
+
+#include "main.h"
+#include "load_country_codes.h"
+
+typedef enum {
+    PAIS,
+    DATE,
+    INFECTED
+} data_t;
+
+status_t read_file(FILE *src, u_long *country, u_long *date, u_long *infected);
+
+status_t fprintf_date(FILE *dest, size_t data);
+status_t fprintf_infected(FILE *dest, size_t data, char newline);
+status_t clean_buffer(char *buffer, size_t size);
+status_t time_translator(time_t unix_time, char *res, size_t size, const char *format); 
+status_t fprintf_country(FILE *dest, size_t country_code, char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH]);
+
+#endif
diff --git a/readlines.c b/readlines.c
@@ -115,6 +115,11 @@ status_t readlines(char *src, char *dest, char country_codes[COUNTRIES_NUMBER][A
                 }
             }
 
+
+//            Imprime en el archivo de salida de acuerdo a un formato especifico,
+//            los valores obtenidos de el archivo de entrada;
+//            print_to_file(country, date, infected);
+
             time_translator(date, time_s, sizeof(time_s), "%m");
             month = atoi(time_s);
             printf("%d\n", month);
@@ -123,7 +128,7 @@ status_t readlines(char *src, char *dest, char country_codes[COUNTRIES_NUMBER][A
                 prev_country = country;
                 prev_month = month;
             }
-
+            
 //            Imprime la suma de infectados por mes cada vez que cambia el pais;
             if(country == prev_country && month == prev_month) {
                 infected_monthly += infected;