commit c7f4f5e1cbe021b3f04e1ed0aadb66b94da3b4d1
parent 101f996c7fd0f88c903398b0c236bb4e69f8e69e
Author: Martin Klöckner <mjkloeckner@gmail.com>
Date: Tue, 30 Apr 2024 20:49:39 -0300
merge branch 'tp1'
Diffstat:
18 files changed, 1044 insertions(+), 0 deletions(-)
diff --git a/tps/1/Makefile b/tps/1/Makefile
@@ -0,0 +1,61 @@
+CC = gcc
+CFLAGS = -std=c99 -Wall -pedantic -g
+
+all: main clean
+
+main: main.o arguments.o print_error.o load_country_codes.o read_file.o print_file.o
+ $(CC) $(CFLAGS) main.o arguments.o print_error.o load_country_codes.o read_file.o print_file.o -o analisis_covid
+
+main.o: main.c main.h arguments.h macros.h
+ $(CC) $(CFLAGS) -c main.c
+
+arguments.o: arguments.c arguments.h macros.h
+ $(CC) $(CFLAGS) -c arguments.c
+
+load_country_codes.o: load_country_codes.h main.h
+ $(CC) $(CFLAGS) -c load_country_codes.c
+
+print_error.o: main.c main.h
+ $(CC) $(CFLAGS) -c print_error.c
+
+read_file.o: read_file.h main.h
+ $(CC) $(CFLAGS) -c read_file.c
+
+print_file.o: print_file.h main.h
+ $(CC) $(CFLAGS) -c print_file.c
+
+
+clean:
+ rm -f *.o
+
+clear:
+ rm -f analisis_covid
+
+
+# Para probar la invocacion de el programa;
+run:
+ ./analisis_covid -in input.csv -out output.txt
+
+run2:
+ ./analisis_covid -out output.txt -in input.csv
+
+run3:
+ ./analisis_covid -in -out
+
+run4:
+ ./analisis_covid -out output.txt -in
+
+run5:
+ ./analisis_covid -in input.csv -out
+
+run6:
+ ./analisis_covid -out -in input.csv
+
+run7:
+ ./analisis_covid -in -out output.txt
+
+run8:
+ ./analisis_covid -in input.csv
+
+run9:
+ ./analisis_covid output.txt -out input.csv -in
diff --git a/tps/1/README.md b/tps/1/README.md
@@ -0,0 +1,28 @@
+NAME
+
+analisis_covid - analyze RAW data and export it with a human
+readable format.
+
+SYNOPSIS:
+
+ analisis_covid -in SOURCE -out DEST
+ analisis_covid -out DEST -in SOURCE
+
+DESCRIPTION
+
+Process RAW data from a .csv(comma separated values) file,
+and export it to a plain text if the output file doesn't
+exist then it creates one with the specified name.
+When you invoke analisis_covid, expects as input a .csv
+file with three columns separated by a comma (','), otherwise
+it's considered corrupt.
+
+
+AUTHOR
+
+Written by Martin J. Klöckner - Argentina - Dec 2020 / Jan 2021
+
+
+
+
+
diff --git a/tps/1/arguments.c b/tps/1/arguments.c
@@ -0,0 +1,63 @@
+#include "arguments.h"
+
+// Valida que los argumentos esten correctos y guarda los nombres de los
+// archivos de entrada y salida en src y dest respectivamente;
+status_t validate_arguments(int argc, char * argv[], char * src, char * dest)
+{
+ if(argc < EXPECTED_CMD_ARGUMENTS || argc > EXPECTED_CMD_ARGUMENTS)
+ return ERROR_INVOCATING_PROGRAM;
+ else if(argv == NULL)
+ return ERROR_NULL_POINTER;
+
+ if((strcmp(argv[1], INPUT_ARGUMENT)) && (strcmp(argv[3], OUTPUT_ARGUMENT)))
+ if((strcmp(argv[1], OUTPUT_ARGUMENT)) && (strcmp(argv[3], INPUT_ARGUMENT)))
+ return ERROR_INVOCATING_PROGRAM;
+
+ status_t inputFile, outputFile;
+ inputFile = outputFile = IO_FILE_NOT_FOUND;
+
+ size_t i;
+ for(i = 1; i < argc; i++) {
+// Comprueba que el primer argumento sea INPUT_ARGUMENT ('-in');
+ if(!strcmp(argv[i], INPUT_ARGUMENT)) {
+
+// Si el argumento que sigue es OUTPUT_ARGUMENT entonces hay un error
+// en la invocacion de el programa, y si el que le sigue a ese no es
+// OUTPUT_ARGUMENT estamos ante un problema de orden de argumentos;
+ if(!strcmp(argv[i + 1], OUTPUT_ARGUMENT))
+ return ERROR_INVOCATING_PROGRAM;
+
+// Si el primer argumento esta bien y el siguiente es una cadena entonces
+// guarda en src la cadena e imprime dicha cadena;
+ strcpy(src, argv[++i]);
+
+ printf(INPUT_ARGUMENT_FOUND_MSG);
+ printf(INPUT_FILE_NAME_MSG"'%s'\n", src);
+
+// Marca el archivo de entrada como encontrado;
+ inputFile = OK;
+
+// Procede de la misma forma pero para OUTPUT_ARGUMENT ('-out');
+ } else if(!strcmp(argv[i], OUTPUT_ARGUMENT)) {
+
+ if(!strcmp(argv[i + 1], INPUT_ARGUMENT))
+ return ERROR_INVOCATING_PROGRAM;
+
+ strcpy(dest, argv[++i]);
+
+ printf(OUTPUT_ARGUMENT_FOUND_MSG);
+ printf(OUTPUT_FILE_NAME_MSG"'%s'\n", dest);
+
+ outputFile = OK;
+ }
+ }
+
+// Si uno o ambos de los argumentos no se encontro entonces imprime un codigo
+// de error;
+ if((inputFile && outputFile) != OK)
+ return ERROR_INVOCATING_PROGRAM;
+
+ return OK;
+}
+
+
diff --git a/tps/1/arguments.h b/tps/1/arguments.h
@@ -0,0 +1,14 @@
+#ifndef ARGUMENTS_H
+#define ARGUMENTS_H
+
+#include "main.h"
+
+#define INPUT_ARGUMENT_FOUND_MSG "Encontre un '-in'\n"
+#define OUTPUT_ARGUMENT_FOUND_MSG "Encontre un '-out'\n"
+
+#define INPUT_FILE_NAME_MSG "\t -> Archivo de entrada: "
+#define OUTPUT_FILE_NAME_MSG "\t -> Archivo de salida: "
+
+status_t validate_arguments(int argc, char * argv[], char * src, char * dest);
+
+#endif
diff --git a/tps/1/input.csv b/tps/1/input.csv
@@ -0,0 +1,23 @@
+PAIS, FECHA, INFECTADOS
+32,1577880000,2342
+32,1578657600,4923
+32,1579089600,9324
+32,1581223358,9324
+32,1581741758,7324
+32,1582864958,4324
+170,1577880000,8234
+170,1578657600,9234
+170,1579089600,9423
+170,1579089600,9423
+276,1577880000,8432
+276,1579089600,9129
+276,1579521600,4214
+276,1581223358,9324
+276,1581741758,7324
+276,1582864958,4324
+36,1577880000,3
+36,1579089600,7
+36,1579521600,16
+36,1581223358,33
+36,1581741758,88
+36,1582864958,162
diff --git a/tps/1/iso3166-1.csv b/tps/1/iso3166-1.csv
@@ -0,0 +1,249 @@
+4,Afghanistan
+248,Åland Islands
+8,Albania
+12,Algeria
+16,American Samoa
+20,Andorra
+24,Angola
+660,Anguilla
+10,Antarctica
+28,Antigua and Barbuda
+32,Argentina
+51,Armenia
+533,Aruba
+36,Australia
+40,Austria
+31,Azerbaijan
+44,Bahamas
+48,Bahrain
+50,Bangladesh
+52,Barbados
+112,Belarus
+56,Belgium
+84,Belize
+204,Benin
+60,Bermuda
+64,Bhutan
+68,Bolivia (Plurinational State of)
+535,"Bonaire, Sint Eustatius and Saba"
+70,Bosnia and Herzegovina
+72,Botswana
+74,Bouvet Island
+76,Brazil
+86,British Indian Ocean Territory
+96,Brunei Darussalam
+100,Bulgaria
+854,Burkina Faso
+108,Burundi
+132,Cabo Verde
+116,Cambodia
+120,Cameroon
+124,Canada
+136,Cayman Islands
+140,Central African Republic
+148,Chad
+152,Chile
+156,China
+162,Christmas Island
+166,Cocos (Keeling) Islands
+170,Colombia
+174,Comoros
+178,Congo
+180,"Congo, Democratic Republic of the"
+184,Cook Islands
+188,Costa Rica
+384,Côte d'Ivoire
+191,Croatia
+192,Cuba
+531,Curaçao
+196,Cyprus
+203,Czechia
+208,Denmark
+262,Djibouti
+212,Dominica
+214,Dominican Republic
+218,Ecuador
+818,Egypt
+222,El Salvador
+226,Equatorial Guinea
+232,Eritrea
+233,Estonia
+748,Eswatini
+231,Ethiopia
+238,Falkland Islands (Malvinas)
+234,Faroe Islands
+242,Fiji
+246,Finland
+250,France
+254,French Guiana
+258,French Polynesia
+260,French Southern Territories
+266,Gabon
+270,Gambia
+268,Georgia
+276,Germany
+288,Ghana
+292,Gibraltar
+300,Greece
+304,Greenland
+308,Grenada
+312,Guadeloupe
+316,Guam
+320,Guatemala
+831,Guernsey
+324,Guinea
+624,Guinea-Bissau
+328,Guyana
+332,Haiti
+334,Heard Island and McDonald Islands
+336,Holy See
+340,Honduras
+344,Hong Kong
+348,Hungary
+352,Iceland
+356,India
+360,Indonesia
+364,Iran (Islamic Republic of)
+368,Iraq
+372,Ireland
+833,Isle of Man
+376,Israel
+380,Italy
+388,Jamaica
+392,Japan
+832,Jersey
+400,Jordan
+398,Kazakhstan
+404,Kenya
+296,Kiribati
+408,Korea (Democratic People's Republic of)
+410,"Korea, Republic of"
+414,Kuwait
+417,Kyrgyzstan
+418,Lao People's Democratic Republic
+428,Latvia
+422,Lebanon
+426,Lesotho
+430,Liberia
+434,Libya
+438,Liechtenstein
+440,Lithuania
+442,Luxembourg
+446,Macao
+450,Madagascar
+454,Malawi
+458,Malaysia
+462,Maldives
+466,Mali
+470,Malta
+584,Marshall Islands
+474,Martinique
+478,Mauritania
+480,Mauritius
+175,Mayotte
+484,Mexico
+583,Micronesia (Federated States of)
+498,"Moldova, Republic of"
+492,Monaco
+496,Mongolia
+499,Montenegro
+500,Montserrat
+504,Morocco
+508,Mozambique
+104,Myanmar
+516,Namibia
+520,Nauru
+524,Nepal
+528,Netherlands
+540,New Caledonia
+554,New Zealand
+558,Nicaragua
+562,Niger
+566,Nigeria
+570,Niue
+574,Norfolk Island
+807,North Macedonia
+580,Northern Mariana Islands
+578,Norway
+512,Oman
+586,Pakistan
+585,Palau
+275,"Palestine, State of"
+591,Panama
+598,Papua New Guinea
+600,Paraguay
+604,Peru
+608,Philippines
+612,Pitcairn
+616,Poland
+620,Portugal
+630,Puerto Rico
+634,Qatar
+638,Réunion
+642,Romania
+643,Russian Federation
+646,Rwanda
+652,Saint Barthélemy
+654,"Saint Helena, Ascension and Tristan da Cunha"
+659,Saint Kitts and Nevis
+662,Saint Lucia
+663,Saint Martin (French part)
+666,Saint Pierre and Miquelon
+670,Saint Vincent and the Grenadines
+882,Samoa
+674,San Marino
+678,Sao Tome and Principe
+682,Saudi Arabia
+686,Senegal
+688,Serbia
+690,Seychelles
+694,Sierra Leone
+702,Singapore
+534,Sint Maarten (Dutch part)
+703,Slovakia
+705,Slovenia
+90,Solomon Islands
+706,Somalia
+710,South Africa
+239,South Georgia and the South Sandwich Islands
+728,South Sudan
+724,Spain
+144,Sri Lanka
+729,Sudan
+740,Suriname
+744,Svalbard and Jan Mayen
+752,Sweden
+756,Switzerland
+760,Syrian Arab Republic
+158,"Taiwan, Province of China"
+762,Tajikistan
+834,"Tanzania, United Republic of"
+764,Thailand
+626,Timor-Leste
+768,Togo
+772,Tokelau
+776,Tonga
+780,Trinidad and Tobago
+788,Tunisia
+792,Turkey
+795,Turkmenistan
+796,Turks and Caicos Islands
+798,Tuvalu
+800,Uganda
+804,Ukraine
+784,United Arab Emirates
+826,United Kingdom of Great Britain and Northern Ireland
+840,United States of America
+581,United States Minor Outlying Islands
+858,Uruguay
+860,Uzbekistan
+548,Vanuatu
+862,Venezuela (Bolivarian Republic of)
+704,Viet Nam
+92,Virgin Islands (British)
+850,Virgin Islands (U.S.)
+876,Wallis and Futuna
+732,Western Sahara
+887,Yemen
+894,Zambia
+716,Zimbabwe
diff --git a/tps/1/load_country_codes.c b/tps/1/load_country_codes.c
@@ -0,0 +1,91 @@
+// Carga en el arreglo 'country_codes' los codigos de los paises de el archivo
+// de nombre "COUNTRY_CODES_FILE_NAME" (definido en macros.h) ubicado en el
+// directorio desde el que se ejecuta el programa;
+
+
+#include "load_country_codes.h"
+
+
+status_t load_country_codes(char **country_codes)
+{
+ FILE *fp;
+
+ empty_country_codes(country_codes);
+
+ char *buff;
+ char buff2[INITIAL_SIZE];
+ buff2[INITIAL_SIZE] = '\0';
+
+ clean(buff2, INITIAL_SIZE);
+
+ int country_code = 0;
+ char country_name[INITIAL_SIZE];
+ country_name[INITIAL_SIZE - 1] = '\0';
+
+ size_t i, j;
+ part_t part;
+
+ buff = (char *)malloc(INITIAL_SIZE * sizeof(char));
+
+ if((fp = fopen(COUNTRY_CODES_FILE_NAME, "r")) == NULL) {
+ free(buff);
+ return ERROR_LOADING_COUNTRY_CODES;
+ }
+
+ while(fgets(buff, INITIAL_SIZE, fp) != NULL) {
+ clean(country_name, INITIAL_SIZE);
+ for(i = 0, j = 0, part = CODE; buff[i] != '\0'; i++) {
+ if(buff[i] == ',') {
+ part = NAME;
+ i++;
+ } else if (buff[i] == '\n') {
+ part = CODE;
+ j = 0;
+ }
+
+ switch(part)
+ {
+ case CODE: buff2[i] = *(buff + i); break;
+ case NAME: country_name[j] = *(buff + i); j++; break;
+ }
+ }
+ country_code = atoi(buff2);
+ clean(buff2, INITIAL_SIZE);
+ strcpy(country_codes[country_code], country_name);
+ }
+
+// Cierra el archivo que contiene el codigo de los paises de acuerdo al estandar;
+ fclose(fp);
+ free(buff);
+ return OK;
+}
+
+
+status_t clean (char *buffer, size_t size)
+{
+ size_t i;
+ i = 0;
+
+ if(buffer == NULL)
+ return ERROR_NULL_POINTER;
+
+ while(i < size) {
+ buffer[i] = '\0';
+ i++;
+ }
+ return OK;
+}
+
+// Inicializa el arreglo alocando el caracter '\0' en todas las posiciones;
+status_t empty_country_codes(char **country_codes)
+{
+ size_t i, j;
+ for(i = 0; i < COUNTRIES_NUMBER; i++)
+ for(j = 0; j < (ARRAYS_LENGTH - 1); j++) {
+ country_codes[i][j] = 'a';
+
+ country_codes[i][ARRAYS_LENGTH - 1] = '\n';
+ }
+
+ return OK;
+}
diff --git a/tps/1/load_country_codes.h b/tps/1/load_country_codes.h
@@ -0,0 +1,18 @@
+#ifndef LOAD_COUNTRY_CODES
+#define LOAD_COUNTRY_CODES
+
+#include "main.h"
+
+
+typedef enum {
+ CODE,
+ NAME
+} part_t;
+
+status_t clean (char *buffer, size_t size);
+//status_t empty_country_codes(char country_codes[COUNTRIES_NUMBER][ARRAYS_LENGTH]);
+status_t empty_country_codes(char **country_codes);
+//status_t load_country_codes(char country_codes[][ARRAYS_LENGTH]);
+status_t load_country_codes(char **country_codes);
+
+#endif
diff --git a/tps/1/macros.h b/tps/1/macros.h
@@ -0,0 +1,16 @@
+#ifndef MACROS_H
+#define MACROS_H
+
+#define NO_CMD_ARGUMENTS 1
+#define ONE_CMD_ARGUMENT 2
+#define EXPECTED_CMD_ARGUMENTS 5
+
+#define INPUT_ARGUMENT "-in"
+#define OUTPUT_ARGUMENT "-out"
+
+#define INITIAL_SIZE 1000
+#define MAX_NAME_LENGTH 32
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#endif
diff --git a/tps/1/main.c b/tps/1/main.c
@@ -0,0 +1,115 @@
+//
+// Programa escrito por Martin J. Klӧckner
+// martin.cachari@gmail.com
+// github.com/klewer-martin
+//
+// Repositorio de github del proyecto:
+// https://github.com/klewer-martin/9511_project01.git
+// (Disponible a partir de la fecha de correccion)
+
+
+// Lee texto de un archivo con extension .csv cuyo nombre recibe
+// como argumento; el cual contiene solo numeros que representan
+// un pais, una fecha y una cantidad de infectados y lo guarda en
+// un archivo de texto cuyo nombre tambien recibe como argumento
+// con un formato humanamente entendible.
+
+
+#include "main.h"
+#include "macros.h"
+#include "arguments.h"
+#include "load_country_codes.h"
+#include "read_file.h"
+#include "print_file.h"
+#include "print_error.h"
+
+void free_array(char **arr)
+{
+ for (size_t i = 0; i < COUNTRIES_NUMBER; i++)
+ free(arr[i]);
+
+ free(arr);
+}
+
+int main(int argc, char * argv[])
+{
+ status_t st;
+
+// Las siguientes variables son para guardar los nombres de los archivos de
+// entrada y salida luego de validar los argumentos
+ char src[MAX_NAME_LENGTH];
+ char dest[MAX_NAME_LENGTH];
+
+ FILE *fpi, *fpo;
+ uint country, date, infected;
+
+ country = date = infected = 0;
+
+ prev_month = prev_country = -1;
+ infected_monthly = 0;
+
+// Arreglo de arreglos de caracteres para guardar los codigos de los paises
+ char **country_codes = (char **)malloc(COUNTRIES_NUMBER * sizeof(char *));
+ for (size_t i = 0; i < COUNTRIES_NUMBER; i++)
+ country_codes[i] = (char *)malloc(ARRAYS_LENGTH * sizeof(double));
+
+// Valida de que los argumentos sean correctos y guarda los nombres de los
+// archivos de entrada y salida en src y dest respectivamente
+ if((st = validate_arguments(argc, argv, src, dest)) != OK) {
+ free_array(country_codes);
+ 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'
+ if((st = load_country_codes(country_codes)) != OK) {
+ free_array(country_codes);
+ print_error(st);
+ return ERROR_LOADING_COUNTRY_CODES;
+ }
+
+// Abre el archivo de entrada en modo lectura
+ if((fpi = fopen(src, "r")) == NULL) {
+ fclose(fpi);
+ print_error(ERROR_READING_FILE);
+ free_array(country_codes);
+ return ERROR_READING_FILE;
+ }
+
+// Abre el archivo de salida en modo escritura
+ if((fpo = fopen(dest, "w")) == NULL) {
+ fclose(fpi);
+ fclose(fpo);
+ free_array(country_codes);
+ print_error(ERROR_READING_FILE);
+ return ERROR_READING_FILE;
+ }
+
+// Lee el archivo de entrada y va imprimiendo linea por linea en el de salida
+ 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);
+ }
+ }
+
+
+// Si hubo algun error al leer o escribir el archivo va a imprimir un error
+ if((st != OK) && (st != END_OF_INPUT_FILE)) {
+ free_array(country_codes);
+ fclose(fpi);
+ fclose(fpo);
+ print_error(st);
+ return st;
+ }
+
+// El la ultima linea de 'infectados por mes'
+ fprintf_infected_monthly(fpo);
+
+ fclose(fpi);
+ fclose(fpo);
+ free_array(country_codes);
+ printf(MSG_OK);
+ return OK;
+}
diff --git a/tps/1/main.h b/tps/1/main.h
@@ -0,0 +1,49 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdbool.h>
+
+#include "macros.h"
+
+
+#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 16
+
+
+extern const char formato_de_la_fecha[];
+
+extern uint country, date, infected;
+
+extern ulong infected_monthly;
+
+extern int prev_month, prev_country;
+
+
+typedef enum {
+ OK,
+ IO_FILE_NOT_FOUND,
+ ERROR_INVOCATING_PROGRAM,
+ ERROR_NULL_POINTER,
+ ERROR_LOADING_COUNTRY_CODES,
+ ERROR_PRINTING,
+ ERROR_READING_FILE,
+ ERROR_ALLOCATING_TIME,
+ ERROR_DATA_ON_FILE_MISSING,
+ END_OF_INPUT_FILE,
+} status_t;
+
+#endif
diff --git a/tps/1/make.bat b/tps/1/make.bat
@@ -0,0 +1,15 @@
+:: Compile and build 'analisis_covid' on windows using cmd or PowerShell
+
+SET CC=gcc
+SET CFLAGS=-std=c99 -Wall -pedantic
+
+%CC% %CFLAGS% -c print_file.c
+%CC% %CFLAGS% -c read_file.c
+%CC% %CFLAGS% -c load_country_codes.c
+%CC% %CFLAGS% -c perrors.c
+%CC% %CFLAGS% -c arguments.c
+%CC% %CFLAGS% -c main.c
+%CC% %CFLAGS% main.o arguments.o perrors.o load_country_codes.o read_file.o print_file.o -o analisis_covid
+
+:: Deletes unnecessary .o files after the compile ends;
+del .\*.o
diff --git a/tps/1/print_error.c b/tps/1/print_error.c
@@ -0,0 +1,37 @@
+#include "print_error.h"
+#include "main.h"
+
+// The switch below the order of the error must be in the same as "main.h"
+// status_t structure, in order to print the correct errors;
+void print_error(status_t error)
+{
+ switch (error) {
+ case IO_FILE_NOT_FOUND:
+ fprintf(stderr, MSG_IO_FILE_NOT_FOUND"\n");
+ break;
+ case ERROR_INVOCATING_PROGRAM:
+ fprintf(stderr, MSG_ERROR_INVOCATING_PROGRAM"\n");
+ break;
+ case ERROR_NULL_POINTER:
+ fprintf(stderr, MSG_ERROR_NULL_POINTER"\n");
+ break;
+ case ERROR_LOADING_COUNTRY_CODES:
+ fprintf(stderr, MSG_ERROR_LOADING_COUNTRY_CODES"\n");
+ break;
+ case ERROR_PRINTING:
+ fprintf(stderr, MSG_ERROR_PRINTING"\n");
+ break;
+ case ERROR_READING_FILE:
+ fprintf(stderr, MSG_ERROR_READING_FILE"\n");
+ break;
+ case ERROR_ALLOCATING_TIME:
+ fprintf(stderr, MSG_ERROR_ALLOCATING_TIME"\n");
+ break;
+ case ERROR_DATA_ON_FILE_MISSING:
+ fprintf(stderr, MSG_ERROR_DATA_ON_FILE_MISSING"\n");
+ break;
+ default:
+ fprintf(stdin, MSG_OK"\n");
+ }
+}
+
diff --git a/tps/1/print_error.h b/tps/1/print_error.h
@@ -0,0 +1,46 @@
+#ifndef PRINT_ERROR_H
+#define PRINT_ERROR_H
+
+#include "main.h"
+
+#define MSG_ERROR_NULL_POINTER "ERROR_NULL_POINTER (3)\n"\
+ "Un error inesperado ha ocurrido durante la ejecucion de\n"\
+ "el programa"
+
+#define MSG_ERROR_INVOCATING_PROGRAM "\nERROR_INVOCATING_PROGRAM (2)\n"\
+ "Uso:\t$ ./main -in <input file> -out <outputfile>\n"\
+ "\t $ ./main -out <output file -in <input file>\n\n"\
+ "Lee el archivo README.md para saber mas"
+
+#define MSG_IO_FILE_NOT_FOUND "\nIO_FILE_NOT_FOUND (1)\n"\
+ "Un de los archivos de entrada o salida no se ha especificado"\
+
+#define MSG_ERROR_LOADING_COUNTRY_CODES "\nERROR_LOADING_COUNTRY_CODES (4)\n"\
+ "Ha ocurrido un error al cargar los codigos de los paises.\n"\
+ "compruebe que el archivo \""COUNTRY_CODES_FILE_NAME"\" se encuentre\n"\
+ "disponible en el directorio de el programa ejecutado y que\n"\
+ "el nombre coincida con el de \"COUNTRY_CODES_FILE_NAME\" dentro\n"\
+ "de el archivo main.h"
+
+#define MSG_ERROR_PRINTING
+
+#define MSG_ERROR_READING_FILE "\nERROR_READING_FILE (6)\n"\
+ "El archivo de entrada no pudo ser leido, compruebe que el nombre este\n"\
+ "escrito correctamente y la existencia de el mismo"
+
+#define MSG_ERROR_ALLOCATING_TIME "\nERROR_ALOCATING_TIME (7)\n"\
+ "Hubo un problema inesperado durante la traduccion de la fecha al formato\n"\
+ "especificado."
+
+#define MSG_ERROR_DATA_ON_FILE_MISSING "\nERROR_DATA_ON_FILE_MISSING (8)\n"\
+ "En alguna linea de el archivo de entrada falta un dato,\n"\
+ "compruebe que dicho archivo no esta corrupto y ejecute\n"\
+ "el programa nuevamente"
+
+#define MSG_OK "\nOperacion realizada exitosamente!\n"
+
+
+void print_error(status_t error);
+
+
+#endif
diff --git a/tps/1/print_file.c b/tps/1/print_file.c
@@ -0,0 +1,111 @@
+#include "print_file.h"
+
+const char formato_de_la_fecha[] = "%d %b %Y";
+
+int prev_month, prev_country;
+ulong infected_monthly;
+
+status_t print_file(FILE *dest, char **country_codes, uint *country, uint *date, uint *infected) {
+
+ int month;
+ char time_s[TIME_MAX_DIGITS];
+ time_translator(*(date), time_s, sizeof(time_s), "%m");
+
+ month = atoi(time_s);
+ if((prev_month == -1) || (prev_country == -1)) {
+ prev_month = month;
+ prev_country = *country;
+ }
+
+// 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_infected_monthly(dest);
+ infected_monthly = *(infected);
+
+ prev_country = *(country);
+ prev_month = month;
+ }
+ else if(month != prev_month) {
+ prev_month = month;
+
+ fprintf_infected_monthly(dest);
+ infected_monthly = *(infected);
+ }
+
+// 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)
+{
+ 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, uint infected, char newline)
+{
+ if(dest == NULL)
+ return ERROR_NULL_POINTER;
+
+ fprintf(dest, "Infectados: %u\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)
+ return ERROR_ALLOCATING_TIME;
+
+ return OK;
+}
+
+void fprintf_infected_monthly(FILE *dest)
+{
+ char guion_medio[] = "-----------";
+
+ int length = snprintf( NULL, 0, "%lu", infected_monthly );
+ char* str_infected_monthly = (char *)malloc(length + 1 * sizeof(char));
+ snprintf( str_infected_monthly, length + 1, "%lu", infected_monthly );
+
+
+ fprintf(dest, "Infectados por mes: %lu\n", infected_monthly);
+ sprintf(str_infected_monthly, "%u", 10);
+ fprintf(dest, "-------------------%.*s\n", (length + 1), guion_medio);
+
+ free(str_infected_monthly);
+}
diff --git a/tps/1/print_file.h b/tps/1/print_file.h
@@ -0,0 +1,18 @@
+#ifndef PRINT_FILE_H
+#define PRINT_FILE_H
+
+#include "main.h"
+
+status_t print_file(FILE *dest, char **country_codes, uint *country, uint *date, uint *infected);
+
+status_t fprintf_country(FILE *dest, size_t country_code, char **country_codes);
+status_t fprintf_date(FILE *dest, size_t date);
+status_t fprintf_infected(FILE *dest, uint infected, char newline);
+
+void fprintf_infected_monthly(FILE *dest);
+
+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/tps/1/read_file.c b/tps/1/read_file.c
@@ -0,0 +1,73 @@
+
+#include "read_file.h"
+
+
+status_t read_file(FILE *src, uint *country, uint *date, uint *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 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++;
+ if(data == PAIS)
+ *(country) = atoi(buff2);
+
+ else if (data == DATE)
+ *(date) = atoi(buff2);
+
+ 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) = atoi(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;
+}
diff --git a/tps/1/read_file.h b/tps/1/read_file.h
@@ -0,0 +1,17 @@
+#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, uint *country, uint *date, uint *infected);
+
+status_t clean_buffer(char *buffer, size_t size);
+
+#endif