Liste chainée

Liste chainée - C - Programmation

Marsh Posté le 22-06-2006 à 22:34:37    

Bonjour,
 
J'ai besoin de conseils pour les listes chainées.
Mon programme fait ce que je veux, c'est à dire sauvegarde dans un fichier du login, pass et shell entré (option a) et liste (option l) ou efface (option d) (avec cryptage du mot de passe).
 
Mais voilà, je souhaiterai qu'il ne sauvegarde pas dans un fichier mais dans une liste chainée (donc en mémoire dynamique).
 
J'ai tenté de remplacer la structure ci dessous par quelque chose comme :
typedef struct Element{
               int val;
               struct Element *next;
}Element;  
Mais j'ai trop d'erreurs.
 
Des idées ?
 

Code :
  1. struct my_passwd
  2. {
  3.        char          pw_name[255];   /* user name */
  4.        char          pw_passwd[255]; /* password */
  5.        char          pw_shell[64];   /* default shell */
  6. } ;
  7. int woptions(int ac,char ***av)
  8. {
  9. int option2return;
  10. option2return=getopt(ac, *av,"adl" );
  11. if(getopt(ac,*av,"adl" ) != -1)
  12.        {
  13.               printf("my_passwd: usage -[adl] [file]\n" );
  14.        exit(EXIT_FAILURE);
  15.         }
  16. else
  17.  return option2return;
  18. }
  19. int ajoututilisateur(char *fichier)
  20. {
  21.        struct my_passwd      pwd;
  22. int                   fd;
  23. MD5_CTX ctx;
  24. memset(&pwd, 0,sizeof(pwd));
  25. printf("Username: " );
  26. scanf("%s",pwd.pw_name);
  27. printf("Password: " );
  28. scanf("%s",pwd.pw_passwd);
  29. MD5Init(&ctx);
  30. MD5Update(&ctx,pwd.pw_passwd,strlen(pwd.pw_passwd));
  31. MD5End(&ctx,pwd.pw_passwd);
  32. printf("Shell: " );
  33.     scanf("%s",pwd.pw_shell);
  34. if((fd = open(fichier, O_RDWR|O_APPEND)) == -1)
  35. {
  36.  perror("my_passwd" );
  37.  exit(EXIT_FAILURE);
  38. }
  39.    if((write(fd, &pwd, sizeof(pwd))) == -1)
  40. {
  41.   perror("my_passwd" );
  42.   exit(EXIT_FAILURE);
  43. }
  44. close(fd);
  45. return 1;  
  46. }
  47. int effaceutilisateur(char *fichier)
  48. {
  49.  struct my_passwd      pwd;
  50.      int                    fd;
  51.  int   userexist=0;
  52.  char   *nom;
  53.  int   taille;
  54.  int   totalsize=0;
  55.  nom=malloc(sizeof(char *));
  56.  memset(&pwd, 0,sizeof(pwd));
  57.  printf("Username: " );
  58.  scanf("%s",nom);
  59.  if((fd = open(fichier, O_RDWR)) == -1)
  60.          {
  61.                 perror("my_passwd" );
  62.                 exit(EXIT_FAILURE);
  63.          }
  64. while((taille=read(fd,&pwd,sizeof(pwd))) != 0)
  65. {
  66.  totalsize += taille;
  67.  if(strcmp(nom,pwd.pw_name) == 0)
  68.  {
  69.   while((taille=read(fd,&pwd,sizeof(pwd))) != 0)
  70.   {
  71.    lseek(fd,(totalsize-sizeof(pwd)),SEEK_SET);
  72.    if((write(fd, &pwd, sizeof(pwd))) == -1)
  73.           {
  74.            perror("my_passwd" );
  75.            exit(EXIT_FAILURE);
  76.            }
  77.    totalsize += taille;
  78.    lseek(fd,totalsize,SEEK_SET);
  79.   }
  80.   userexist=1;
  81.  }
  82. }
  83. close(fd);
  84. if(userexist==0)
  85. {
  86.  printf("my_passwd: unknown user %s\n",nom);
  87. }
  88. else
  89.  truncate(fichier,totalsize-sizeof(pwd));
  90. return 1;
  91. }
  92. int listeutilisateur(char *fichier)
  93. {
  94. struct my_passwd      pwd;
  95. int                   fd;
  96. char                   *nom;
  97. memset(&pwd, 0,sizeof(pwd));
  98.         if((fd = open(fichier, O_RDWR)) == -1)
  99.         {
  100.                       perror("my_passwd" );
  101.                       exit(EXIT_FAILURE);
  102.         }
  103.         while((read(fd,&pwd,sizeof(pwd))) != 0)
  104.         {
  105.           printf("Username: %s\n",pwd.pw_name);
  106.       printf("Password: %s\n",pwd.pw_passwd);
  107.       printf("Shell: %s\n\n",pwd.pw_shell);
  108.         }
  109.         close(fd);
  110.  return 1;
  111. }
  112. int nbrconf(int ac)
  113. {
  114. if(ac!=3)
  115. {
  116.  printf("my_passwd: usage -[adl] [file]\n" );
  117.  exit(EXIT_FAILURE);
  118. }
  119. else
  120.   return 1;
  121. }
  122. int fichierlu(char *fichier)
  123. {
  124. struct stat s_sb;
  125. if(lstat(fichier,&s_sb) != 0)
  126. {
  127.  perror("my_passwd" );
  128.  exit(EXIT_FAILURE);
  129. }
  130. else
  131. {
  132.  if(!S_ISREG(s_sb.st_mode))
  133.  {
  134.   printf("my_passwd: need a file\n" );
  135.   printf("my_passwd: usage -[adl] [file]\n" );
  136.  }
  137.  else
  138.   return 1;
  139. }
  140. }
  141. void priseoption(int choixoption, char *fichier)
  142. {
  143.   switch (choixoption)
  144.          {
  145.              case 'a':
  146.                 ajoututilisateur(fichier);
  147.                  break;
  148.              case 'd':
  149.                 effaceutilisateur(fichier);
  150.           break;
  151.          case 'l':
  152.                 listeutilisateur(fichier);
  153.           break;
  154.          }
  155. }
  156. int main(int ac, char **av)
  157. {
  158. int choixoption;
  159. extern int opterr;
  160. opterr=0;
  161.     nbrconf(ac);
  162. choixoption=woptions(ac,&av);
  163. fichierlu(av[2]);
  164. priseoption(choixoption,av[2]);
  165. }


 
MERCI par avance


Message édité par mayapour le 23-06-2006 à 16:17:58
Reply

Marsh Posté le 22-06-2006 à 22:34:37   

Reply

Marsh Posté le 23-06-2006 à 00:59:48    

Hum... un peu compliqué.
Bon, avant toute chose, il faut savoir qu'une liste chaînée n'est utile que si tu dois insérer des éléments au-milieu d'autres. Avec une liste chaînée, tu crées un nouvel élément puis tu mets à jour les liens.
Si ton élément vient s'insérer après les autres, une liste chaînée marchera mais n'est vraiment pas utile et peut avantageusement être remplacée par un tableau que tu alloues et réalloue avec realloc dès que tu l'as remplis...
 
Remarque annexe: c'est pas très propre de mettre des "exit" dans des fonctions autre que "main"


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 23-06-2006 à 15:42:59    

Sve@r a écrit :

Bon, avant toute chose, il faut savoir qu'une liste chaînée n'est utile que si tu dois insérer des éléments au-milieu d'autres. Avec une liste chaînée, tu crées un nouvel élément puis tu mets à jour les liens.
Si ton élément vient s'insérer après les autres, une liste chaînée marchera mais n'est vraiment pas utile et peut avantageusement être remplacée par un tableau que tu alloues et réalloue avec realloc dès que tu l'as remplis...


Effectivement, mais je pense que dans ce cas, la liste chaînée se justifie pour les suppressions d'éléments (fonction effaceutilisateur).
 
mayapour> Ta définition de la structure Element me paraît pas mal, mais je ne comprends pas pourquoi val est un int et pas un my_passwd.
Tu devrais maintenant te construire une petite bibliothèque de fonctions permettant de manipuler tes listes chaînées (ajout, suppression, recherche). On t'aidera si tu as des problèmes pour ça.
Ensuite, il sera simple de reprendre tes fonctions existantes et les primitives de manipulation de listes pour faire ce que tu veux.
 
PS: utilise des balises code pour poster tes programmes stp.
 
 
EDIT: j'avais pas vu le topic doublon :spamafote:

Message cité 1 fois
Message édité par franceso le 23-06-2006 à 15:46:50

---------------
TriScale innov
Reply

Marsh Posté le 23-06-2006 à 16:53:00    

franceso a écrit :

Effectivement, mais je pense que dans ce cas, la liste chaînée se justifie pour les suppressions d'éléments (fonction effaceutilisateur).


Exact. J'avais juste survolé le code sans fait gaffe à cette fonction. Effectivement, s'il y a insertion ou suppression d'un élément intermédiaire, la liste chaînée se justifie.
 

franceso a écrit :

mayapour> Ta définition de la structure Element me paraît pas mal, mais je ne comprends pas pourquoi val est un int et pas un my_passwd.
Tu devrais maintenant te construire une petite bibliothèque de fonctions permettant de manipuler tes listes chaînées (ajout, suppression, recherche). On t'aidera si tu as des problèmes pour ça.
Ensuite, il sera simple de reprendre tes fonctions existantes et les primitives de manipulation de listes pour faire ce que tu veux.


Très bonnes remarques. Je vais rajouter les miennes
1) en général, une structure se nomme conventionnellement "s_qqchose" => struct s_passwd" au lieu de "struct passwd"
 
2) utiliser "typedef" permet de ne plus être obligé de mettre "struct" chaque fois que tu veux avoir une variable de type "struct s_passwd"

typedef struct {
       char          pw_name[255];   /* user name */
       char          pw_passwd[255]; /* password */
       char          pw_shell[64];   /* default shell */
} t_passwd;


Ensuite, au-lieu de créer des variables de type "struct s_passwd", tu crées des variables de type "t_passwd" mais qui s'emploient de la même manière
 
3) après avoir défini ton type "t_elem" te permettant de manipuler un élément de ta liste, il est souvent judicieux de créer un type "t_liste" te permettant de manipuler toute ta liste entière.
Ce type (pouvant être vu comme "poignée de ta liste" ) contiendra évidemment un pointeur sur le premier élément, éventuellement un pointeur sur le dernier, un pointeur sur l'élément en cours de traitement, etc (tout ce qu'il peut te paraître utile d'avoir).
Ensuite, dans ton main, tu définis un "t_liste liste" et tu initialises tous ses pointeurs à NULL (autant créer une fonction "void ListeInit" pour faire cela) puis, dès que tu veux passer ta liste à une fonction quelconque, tu lui passes "&liste" et ta fonction recevant un pointeur de type "t_liste *" pourra, à partir de ce pointeur, manipuler à son grès chacun des éléments de ta liste.
 
En faisant comme Francesco le dit, en créant toute une foule de fonctions te permettant de manipuler un élément, ou une liste complète, tu te rapproches de la philosophie "objet" (un type + des fonctions pour le manipuler). Une fois que tes fonctions sont bien solides, la finalisation devient très simple.


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed