9511_workbook

solved exercises from algorithms & programming I (9511) prof. Cardozo
Index Commits Files Refs README
guia08/ex11.c (3694B)
   1 /* guia08/ej11.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 ARGS    2    /* Program name and file to read name */
  11 #define FILE_NAME_POS    1
  12 
  13 #define MSG_USAGE    "Usage: ./a.out <file name>"
  14 
  15 #define ARR_INIT_SIZE    3
  16 #define STR_INIT_SIZE    10
  17 
  18 #define GROWTH_FACTOR    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 char **split(const char *s, 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(!(arr = split(input, ',', &len))) return 1;
  49 
  50     for(i = 0; i <= len; i++)
  51         printf("%s\n", arr[i]);
  52 
  53     while(len + 1) free(arr[len--]);
  54 
  55     free(arr);
  56     free(input);
  57 
  58     return 0;
  59 }
  60 
  61 status_t validate_arguments(int argc, char *argv[])
  62 {
  63     if(!argv) return ERROR_NULL_POINTER;
  64     if(argc != ARGS) return ERROR_PROGRAM_INVOCATION;
  65 
  66     return OK;
  67 }
  68 
  69 status_t load_file(const char *file_name, char **array)
  70 {
  71     FILE *fp;
  72     size_t alloc_size;
  73 
  74     if(!(fp = fopen(file_name, "rt"))) return ERROR_OPENING_FILE;
  75 
  76     alloc_size = LOAD_FILE_BUFFER_SIZE;
  77     if(!(*array = calloc(sizeof(char), alloc_size))) return ERROR_ALLOC_MEMORY;
  78 
  79     for(size_t i = 0; ((*array)[i] = fgetc(fp)) != EOF; i++) {
  80         if(i == (alloc_size - 2)) {
  81             alloc_size *= 2;
  82             if(!(*array = realloc(*array, alloc_size))) {
  83                 free(*array);
  84                 array = NULL;
  85                 fclose(fp);
  86                 return ERROR_ALLOC_MEMORY;
  87             }
  88         }
  89     }
  90 
  91     fclose(fp);
  92     return OK;
  93 }
  94 
  95 /* 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 */
  96 char **split(const char *s, char delim, size_t *fields)
  97 {
  98     if(!s || !fields) return NULL;
  99 
 100     char **arr;
 101     size_t i, arr_size, str_size;
 102 
 103     arr_size = ARR_INIT_SIZE;
 104     str_size = STR_INIT_SIZE;
 105 
 106     if(!(arr = (char **)calloc(sizeof(char *), arr_size))) return NULL;
 107 
 108     if(!(*arr = (char *)calloc(sizeof(char), str_size))) {
 109         free(arr);
 110         return NULL;
 111     }
 112 
 113     for(*fields = i = 0; *s; i++, s++) {
 114         /* If the array doesn't have any memory left then it gets more memory */
 115         if(*fields == (arr_size - 1)) {
 116             /* Exponential growth of the array */
 117             arr_size *= GROWTH_FACTOR;
 118 
 119             if(!(arr = (char **)realloc(arr, arr_size * sizeof(char *)))) {
 120                 /* If it can't get more memory then all the previous allocations gets freed */
 121                 while((*fields) + 1) free(arr[(*fields)--]);
 122                 free(arr);
 123                 return NULL;
 124             }
 125         }
 126         if((*s == delim) || (*s == '\n')) {    
 127             if(!(arr[++(*fields)] = (char *)calloc(sizeof(char), str_size))) {
 128                 /* If it can't get more memory then all the previous allocations gets freed */
 129                 while(*fields)
 130                     free(arr[(*fields)--]);
 131 
 132                 free(arr);
 133                 return NULL;
 134             }
 135             i = 0;
 136             s++;
 137         }
 138         /* This makes sure that the current string has available memory, if not then it gets more */
 139         if(i == (str_size - 2)) {
 140             str_size *= GROWTH_FACTOR;
 141             if(!(arr[*fields] = (char *)realloc(arr[*fields], str_size))) {
 142                 /* If it can't get more memory all the previous used memmory gets freed */
 143                 while((*fields) + 1)
 144                     free(arr[(*fields)--]);
 145 
 146                 free(arr);
 147                 return NULL;
 148             }
 149             /* Sets all the new memory to the null character */
 150             for(size_t j = i; j < str_size; j++) (*arr)[j] = '\0';
 151         }
 152         arr[*fields][i] = (*s);
 153     }
 154     free(arr[(*fields)--]);
 155     return arr;
 156 }