9511_workbook

solved exercises from algorithms & programming I (9511) prof. Cardozo
Index Commits Files Refs README
guia08/ex12.c (3758B)
   1 /* guia08/ej12.c + CLA
   2  * por Martin J. Klöckner
   3  * github.com/klewer-martin
   4  */
   5 
   6 #include <stdio.h>
   7 #include <stdlib.h>
   8 #include <string.h>
   9 
  10 #define FILE_NAME_POS    1
  11 #define ARGS            2
  12 
  13 #define MSG_USAGE        "Usage: ./a.out <file name>"
  14 
  15 #define GROWTH_FACTOR    2
  16 
  17 #define ARR_INIT_SIZE    1000
  18 #define STR_INIT_SIZE    2
  19 
  20 #define LOAD_FILE_BUFFER_SIZE 100
  21 
  22 typedef enum {
  23     OK,
  24     ERROR_PROGRAM_INVOCATION,
  25     ERROR_OPENING_FILE,
  26     ERROR_ALLOC_MEMORY,
  27     ERROR_NULL_POINTER
  28 } status_t;
  29 
  30 status_t validate_arguments(int argc, char *argv[]);
  31 
  32 status_t load_file(const char *file_name, char **array);
  33 status_t split(const char *s, char ***array, char delim, size_t *fields);
  34 
  35 int main (int argc, char *argv[])
  36 {
  37     char **arr, *input;
  38     size_t i, len;
  39     status_t st;
  40 
  41     if((st = validate_arguments(argc, argv))) {
  42         fprintf(stderr, "%s\n", MSG_USAGE);
  43         return ERROR_PROGRAM_INVOCATION;
  44     } 
  45 
  46     if((st = load_file(argv[FILE_NAME_POS], &input))) return st;
  47 
  48     if((st = split(input, &arr, ',', &len))) return st;
  49 
  50     free(input);
  51 
  52     for(i = 0; i <= len; i++)
  53         printf("%s\n", arr[i]);
  54 
  55     while(len + 1) free(arr[len--]);
  56 
  57     free(arr);
  58 
  59     return 0;
  60 }
  61 
  62 status_t validate_arguments(int argc, char *argv[])
  63 {
  64     if(!argv) return ERROR_NULL_POINTER;
  65     if(argc != ARGS) return ERROR_PROGRAM_INVOCATION;
  66 
  67     return OK;
  68 }
  69 
  70 status_t load_file(const char *file_name, char **array)
  71 {
  72     FILE *fp;
  73     size_t alloc_size;
  74 
  75     if(!(fp = fopen(file_name, "rt"))) return ERROR_OPENING_FILE;
  76 
  77     alloc_size = LOAD_FILE_BUFFER_SIZE;
  78     if(!(*array = calloc(sizeof(char), alloc_size))) return ERROR_ALLOC_MEMORY;
  79 
  80     for(size_t i = 0; ((*array)[i] = fgetc(fp)) != EOF; i++) {
  81         if(i == (alloc_size - 2)) {
  82             alloc_size *= 2;
  83             if(!(*array = realloc(*array, alloc_size))) {
  84                 free(*array);
  85                 array = NULL;
  86                 fclose(fp);
  87                 return ERROR_ALLOC_MEMORY;
  88             }
  89         }
  90     }
  91 
  92     fclose(fp);
  93     return OK;
  94 }
  95 
  96 /* Recibe una cadena de caracteres de longitud desconocida, con valores separados por un caracter delimitador y los separa en cadenas de caracteres de longitud dinamica */
  97 status_t split(const char *s, char ***array, char delim, size_t *fields)
  98 {
  99     if(!s || !fields) return ERROR_NULL_POINTER;
 100 
 101     size_t i, arr_size, str_size;
 102 
 103     arr_size = ARR_INIT_SIZE;
 104     str_size = STR_INIT_SIZE;
 105 
 106     if(!(*array = (char **)calloc(sizeof(char *), arr_size))) return ERROR_ALLOC_MEMORY;
 107 
 108     if(!(**array = (char *)calloc(sizeof(char), str_size))) { free(*array); return ERROR_ALLOC_MEMORY; }
 109 
 110     for(*fields = i = 0; *s; i++, s++) {
 111         /* If the array doesn't have any memory left then it gets more memory */
 112         if(*fields == (arr_size - 1)) {
 113             /* Exponential growth of the array */
 114             arr_size *= GROWTH_FACTOR;
 115             if(!(*array = (char **)realloc(*array, arr_size * sizeof(char *)))) {
 116                 /* If it can't get more memory then all the previous allocations gets freed */
 117                 while((*fields) + 1) free((*array)[(*fields)--]);
 118                 free(*array);
 119                 return ERROR_ALLOC_MEMORY;
 120             }
 121         }
 122         if((*s == delim) || (*s == '\n')) {
 123             str_size = STR_INIT_SIZE;
 124             if(!((*array)[++(*fields)] = (char *)calloc(sizeof(char), str_size))) {
 125                 /* If it can't get more memory then all the previous allocations gets freed */
 126                 while(*fields)
 127                     free((*array)[(*fields)--]);
 128 
 129                 free(*array);
 130                 return ERROR_ALLOC_MEMORY;
 131             }
 132             s++; i = 0;
 133         }
 134         /* This makes sure that the current string has available memory, if not then it gets more */
 135         if(i == (str_size - 2)) {
 136             str_size *= GROWTH_FACTOR;
 137             if(!((*array)[*fields] = (char *)realloc((*array)[*fields], str_size))) {
 138                 /* If it can't get more memory all the previous used memmory gets freed */
 139                 while((*fields) + 1)
 140                     free((*array)[(*fields)--]);
 141 
 142                 free(*array);
 143                 return ERROR_ALLOC_MEMORY;
 144             }
 145         }
 146         (*array)[*fields][i] = (*s);
 147     } /* End for loop */
 148 
 149     free((*array)[(*fields)--]);
 150     return OK;
 151 }