[C] Programme pour manipuler ses fichiers

Fly_it Messages postés 1 Date d'inscription   Statut Membre Dernière intervention   -  
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour,

J'aimerais obtenir votre avis sur ce code, qui est censé permettre à l'utilisateur la lecture, l'écriture et la création de fichiers.

/* main.c */ 

#include <stdio.h> 
#include <stdlib.h> 

static void purger(void); 
/*@null@*/static char * get_text(FILE *, int); 
/*@null@*/static char * get_filename(void); 
/*@null@*/static char * get_contents(FILE *); 
/*@null@*/static char * get_input(void); 
static int get_choice(void); 
static int read_file(void); 
static int create_file(void); 
static int write_file(void); 

int main(void) { 
  int ret = -1; 
  int choice = get_choice(); 
   
  switch (choice) { 
  case 1: 
    ret = read_file(); 
    break; 
  case 2: 
    ret = create_file(); 
    break; 
  case 3: 
    ret = write_file(); 
    break; 
  default: 
    break; 
  } 
  if (ret == -1) { 
    return EXIT_FAILURE; 
  }  
  return EXIT_SUCCESS; 
} 

void purger(void) { 
  int c; 

  do { 
    c = getchar(); 
  } while (c != (int)'\n' && c != EOF); 
} 

char * get_text(FILE * f, int end_caracter) { 
  size_t n = 8; 
  char * s = malloc(n * sizeof *s); 

  if(s != NULL) { 
    size_t i = 0; 
    unsigned int e = 1; 

    do { 
      if (i + 2 > n) { 
        s = realloc(s, n + e); 
        if (s == NULL) { 
          perror("realloc"); 
          return NULL; 
        } 
        n += e; 
        e *= 2; 
      } 
      s[i++] = (char)fgetc(f); 
    } while(s[i - 1] != (char)end_caracter); 
    s[i - 1] = '\0';  
    return s; 
  } 
  perror("malloc"); 
  return NULL; 
} 

char * get_filename(void) { 
  (void)fprintf(stdout, "Nom du fichier : "); 
  return get_text(stdin, (int)'\n'); 
} 

char * get_contents(FILE * f) { 
  (void)fputs("Contenu du fichier : ", stdout); 
  return get_text(f, EOF); 
} 

char * get_input(void) { 
  (void)fputs("Contenu du fichier : ", stdout); 
  return get_text(stdin, EOF); 
} 

int get_choice(void) { 
  int choice; 
  int ret; 

  (void)fputs("1. Lire un fichier\n" 
              "2. Créer un fichier\n" 
              "3. Ecrire dans un fichier\n\n", stdout); 
  do { 
    (void)fprintf(stdout, "Votre choix ? "); 
    ret = scanf("%d", &choice); 
    purger(); 
  } while (ret == EOF || choice < 1 || choice > 3); 
  return choice; 
} 

int read_file(void) { 
  char * s_filename = get_filename(); 

  if (s_filename == NULL) { 
    return -1; 
  } else { 
    FILE * f = fopen(s_filename, "w"); 

    free(s_filename);  
    if (f == NULL) { 
      perror("fopen"); 
      return -1; 
    } else { 
      char * s_contents = get_contents(f); 
       
      if (s_contents == NULL) { 
        return -1; 
      } 
      (void)fputs(s_contents, stdout); 
      free(s_contents); 
      if (fclose(f) == EOF) { 
        perror ("fclose"); 
        return -1; 
      } 
    }  
  } 
  return 0; 
} 

int create_file(void) { 
  char * s_filename = get_filename(); 

  if (s_filename == NULL) { 
    return -1; 
  } else { 
    FILE * f = fopen(s_filename, "w"); 

    free(s_filename);  
    if (f == NULL) { 
      perror("fopen"); 
      return -1; 
    } 
    if (fclose(f) == EOF) { 
      perror("fclose"); 
      return -1; 
    } 
  } 
  return 0; 
} 

int write_file(void) { 
  char * s_filename = get_filename(); 

  if (s_filename == NULL) { 
    return -1; 
  } else { 
    FILE * f = fopen(s_filename, "w"); 
    free(s_filename);  

    if (f == NULL) { 
      perror("fopen"); 
      return -1; 
    } else { 
      char * s_input = get_input(); 
         
      if (s_input == NULL) { 
         return -1; 
      } 
      (void)fputs(s_input, f); 
      free(s_input); 
      if (fclose(f) == EOF) { 
        perror ("fclose"); 
        return -1; 
      } 
    } 
  } 
  return 0; 
} 



1 réponse

fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Pas besoin de caster '\n' en int. ('\n' est déjà un int).
Par exemple : while (c != '\n' && c != EOF);


size_t n = 8;
char * s = malloc(n * sizeof *s);

Pourquoi ne pas allouer statiquement si la valeur est connue à l'avance ?

Sinon, j'ai pas tout épluché, mais ton code est propre.
Il ne reste plus qu'à documenter ;-))).

Cordialement,
0
Fly-It
 
Pour le /n c'est simplement que l'outil splint m'offre quelques Warnings.
Sinon, je ne l'ai pas alloué statiquement afin de pouvoir le reallouer par la suite avec realloc.
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Bizarre pour le \n. Bonne réponse pour le malloc, j'ai pas fait attention
0