Debuggin de mes fonctions write() et read() d'un struct

Fermé
BaGamman Messages postés 65 Date d'inscription mardi 4 janvier 2011 Statut Membre Dernière intervention 11 mars 2017 - Modifié par cptpingu le 27/03/2016 à 17:56
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 - 27 mars 2016 à 17:55
Bonjour,
je débute en C au niveau des primitives unix et je souhaiterais écrire un programme qui soit écrit dans un fichier (nom passé en paramettre) une structure composé de d'une chaine de caractères et de deux integers soit lit et affiche ces structures. Mon programme compile sans erreur ni warning mais de toute evidence, quelque chose ne fonctionne pas au niveau de write() ou de read car la sortie de l'affichage est illisible.

Voici le code que j'ai fait (ne vous ettonnez pas des retour d'erreur, ça fait également partie du TP):

#define _POSIX_C_SOURCE 1
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define LONG_MAX_NOM 20
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#define EXIT_OPEN_FAILURE 2
#define EXIT_READ_FAILURE 3
#define EXIT_CLOSE_FAILURE 4
#define EXIT_ALLOC_FAILURE 5
#define EXIT_WRITE_FAILURE 6

typedef struct
{
   char Nom[LONG_MAX_NOM+1];
   int Age;
   int NbEnfants;
}Infos;


int Creation(char nomFichier[]){
   int retour;
   int fichier;
   char Nom[LONG_MAX_NOM+1]; 
   Infos *fiche=malloc(sizeof(fiche));
   if (fiche==NULL){
      return EXIT_ALLOC_FAILURE;
   }
   fichier=open(nomFichier,O_WRONLY|O_CREAT|O_APPEND,S_IRWXU|S_IRWXG|S_IRWXO);
   if (fichier<0){
      return EXIT_OPEN_FAILURE;
   }
   printf("Saisir le nom: ");
   scanf("%s",Nom);
   strcpy(fiche->Nom,Nom);
   printf("Saisir l'age: ");
   scanf("%d",&fiche->Age);
   printf("Saisir le nombre d'enfants: ");
   scanf("%d",&fiche->NbEnfants);  
   if (write(fichier,&fiche->Nom,sizeof(fiche->Nom))!=sizeof(fiche->Nom)){
      return EXIT_WRITE_FAILURE;
   }
   if (write(fichier,&fiche->Age,sizeof(fiche->Age))!=sizeof(fiche->Age)){
      return EXIT_WRITE_FAILURE;
   }
   if (write(fichier,&fiche->NbEnfants,sizeof(fiche->NbEnfants))!=sizeof(fiche->NbEnfants)){
      return EXIT_WRITE_FAILURE;
   }
   retour=close(fichier);
   if (retour==-1){
      return EXIT_CLOSE_FAILURE;
   }
   return EXIT_SUCCESS;
}

int Consultation(char nomFichier[]){
   int fichier=0;
   char buffer[100];

   if((fichier=open(nomFichier,O_RDONLY))< -1) return EXIT_OPEN_FAILURE;
   if(lseek(fichier,10,SEEK_SET) <0) return EXIT_READ_FAILURE;
   printf("%s\n",buffer);
   if(read(fichier,buffer,100) != 100) return EXIT_READ_FAILURE ;
   printf("%s\n",buffer);
   if(close(fichier)==-1) return EXIT_CLOSE_FAILURE;
   return EXIT_SUCCESS;
}



int main(int argc, char * argv[]){
   int retour;
   int choix=-1;
   if (argc != 2){
      perror("Ex2 nom_fichier");
      return EXIT_FAILURE;
   }
   printf("Veuillez faire votre choix:\n1: Ecriture\n2: Lecture\n3: Quitter\n");
   scanf("%d",&choix);
   switch(choix){
      case(1):
         retour=Creation(argv[1]);
         break;
      case(2):
         retour=Consultation(argv[1]);
         break;
      case (3):
         retour=0;
         break;
      default:
         printf("Erreur");
         return EXIT_FAILURE;
   }
   if (retour==0) {
      printf("Fin\n");
      return EXIT_SUCCESS;
   }
   else if (retour==2){
      perror("Erreur: ouverture");
      return EXIT_FAILURE;
   }
   else if (retour==3){
      perror("Erreur: ecriture");
      return EXIT_FAILURE;
   }
   else if (retour==4){
      perror("Erreur: fermeture");
      return EXIT_FAILURE;
   }
   else if (retour==5){
      perror("Erreur: allocation");
      return EXIT_FAILURE;
   }
}


Si quelqu'un arrive a trouver l'erreur, merci de partager, j'essaye également d'aider un ami qui n'y 'est pas arrivé non plus.
Merci de vos futures réponses :)


1 réponse

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 2
Modifié par cptpingu le 27/03/2016 à 18:28
Bonjour.

Sur le principe, c'est pas trop mal, c'est sur l'exécution que ça pêche un petit peu ^^.
Voici ce que j'ai relevé:
  • Pourquoi faire lseek ?
  • Pourquoi écrire chacune des données de la structure dans le fichier, et pas la structure d'un coup ?
  • Pourquoi chercher à mettre la structure lue dans le fichier dans un buffer de char*, au lieu d'une structure Info directement ?
  • Pourquoi vouloir faire un malloc d'une structure info (en oubliant au passage de la détruire, "coucou la fuite mémoire" :p), au lieu de simplement déclarer une structure Info localement ?
  • Pourquoi ne pas faire un switch sur les define en fin de progamme, au lieu de faire plein de if sur des valeurs numériques non nommées ?
  • Pourquoi écrire en "APPEND" (et pas en "TRUNCATE") alors que clairement tu ne liras que la première structure de ton fichier ?
  • Pourquoi faire un scanf du nom suivi d'un scp de "nom", au lieu de directement faire un scanf dans ta fonction d'écriture ?
  • Pourquoi faire des "perror" ? Le perror est là pour donner la raison d'une erreur après un appel *système*, et non après une fonction à toi, ou du code que tu viens d'écrire. Sinon, tu verras apparaître tout le temps "Success", vu que si tu n'appelles pas une fonction système, il n'y a pas d'erreur. Un printf d'erreur est largement plus adapté. Bien évidemment, un perror reste correcte après l'appel d'une fonction système.


Ton code donne un warning, contrairement à ce que tu annonces, car le main n'a pas de return (il existe un cheminement dans ton code qui amène le main à ne pas avoir de valeur de retour).

Au niveau du style:
  • En C, on ne met de majuscule que sur les nom de structure. Le reste étant écrit en "C case" (minuscules séparées par des "underscores").


Je te propose une réécriture plus propre (j'ai viré tous les "include" inutiles en passant):
#define _POSIX_C_SOURCE 1
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#define LONG_MAX_NOM 20
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#define EXIT_OPEN_FAILURE 2
#define EXIT_READ_FAILURE 3
#define EXIT_CLOSE_FAILURE 4
#define EXIT_WRITE_FAILURE 6

typedef struct
{
  char nom[LONG_MAX_NOM + 1];
  int age;
  int nb_enfants;
} Infos;

int creation(const char* nom_fichier)
{
  int fichier = 0;
  Infos fiche;

  // Droit d'un fichier en général 0644, tu mettais 0777 ce
  // qui est bien "crade". Attention 0644 != 644 (octal vs décimal)
  fichier = open(nom_fichier, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  if (fichier < 0)
    return EXIT_OPEN_FAILURE;

  printf("Saisir le nom: ");
  scanf("%s", fiche.nom);
  printf("Saisir l'age: ");
  scanf("%d", &fiche.age);
  printf("Saisir le nombre d'enfants: ");
  scanf("%d", &fiche.nb_enfants);

  if (write(fichier, &fiche, sizeof(fiche)) != sizeof(fiche))
    return EXIT_WRITE_FAILURE;

  if (close(fichier) < 0)
    return EXIT_CLOSE_FAILURE;

  return EXIT_SUCCESS;
}

int consultation(const char* nom_fichier)
{
  int fichier = 0;
  Infos fiche;

  if ((fichier = open(nom_fichier, O_RDONLY)) < 0)
    return EXIT_OPEN_FAILURE;

  if (read(fichier, &fiche, sizeof(fiche)) != sizeof(fiche))
    return EXIT_READ_FAILURE;

  printf("Info: nom = %s, age = %d, nb_enfants=%i\n",
    fiche.nom, fiche.age, fiche.nb_enfants);

  if (close(fichier) < 0)
    return EXIT_CLOSE_FAILURE;
  return EXIT_SUCCESS;
}

int main(int argc, char* argv[])
{
  int retour;
  int choix = -1;
  if (argc != 2)
  {
    printf("Usage: %s nom_fichier\n", argv[0]);
    return EXIT_FAILURE;
  }

  printf("Veuillez faire votre choix:\n1: Ecriture\n2: Lecture\n3: Quitter\n");
  scanf("%d", &choix);
  switch (choix)
  {
    case 1:
      retour = creation(argv[1]);
      break;
    case 2:
      retour = consultation(argv[1]);
      break;
    case 3:
      retour = EXIT_SUCCESS;
      break;
    default:
      printf("Choix inconnu\n");
      return EXIT_FAILURE;
  }

  switch (retour)
  {
    case EXIT_SUCCESS:
      printf("Fin\n");
      break;
    case EXIT_OPEN_FAILURE:
      perror("Erreur: Ouverture");
      break;
    case EXIT_READ_FAILURE:
      perror("Erreur: Lecture");
      break;
    case EXIT_CLOSE_FAILURE:
      perror("Erreur: Fermeture");
      break;
    case EXIT_WRITE_FAILURE:
      perror("Erreur: Ecriture");
      break;
  }

  return retour;
}
0