probleme d' analyse syntaxique

probleme d' analyse syntaxique - C - Programmation

Marsh Posté le 11-11-2004 à 15:22:13    

Bonjour, je suis en train de travailler sur mon projet de C, et je me heurte depuis un moment a un probleme d'analyse syntaxique.
J'expose le contexte :  
Le programme est une mini base de données. L'utilisateur entre (en console) des commandes de la forme :  
&3irouge //creation d'un objet dont le 3eme champ vaut "rouge"
&1i1 //creation d'un objet dont le premier champ vaut 1
&3mvert //modifier le dernier objet selectioner, son 3eme champ vaut "vert"
save //savegarde la base
 ...etc
Je ne parviens pas a recuperer la valeur du champ =/
 
Je travaille actuellement sous winxp, mais j'utilise le compilateur gcc : ( Rq : le projet est a rendre sous linux, mais comme mon environement linux n'est que peu utilisable, je me force a faire du code standard afin qu'il n'y ai pas de soucis de portage. Si vous voyez des choses non standard qui peuvent poser probleme sous linux, faite m'en part, merci :) )

Citation :


Reading specs from C:/Dev-Cpp/bin/../lib/gcc-lib/mingw32/3.3.1/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=c,c++,f77,objc,ada,java --disable-win32-registry --disable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchronization
Thread model: win32
gcc version 3.3.1 (mingw special 20030804-1)
 
D:\programmation\mbdd>


 
Le resultat de la compilation :  

Citation :

D:\programmation\mbdd>make
gcc.exe -c mbdd.c -o mbdd.o -I"C:/Prgram Files/Dev-Cpp/include"    -ansi -traditional-cpp
gcc.exe -c decode.c -o decode.o -I"C:/Prgram Files/Dev-Cpp/include"    -ansi -traditional-cpp
gcc.exe mbdd.o decode.o  -o "mbdd.exe" -L"C:/Prgram Files/Dev-Cpp/lib"


 
 
Le code :  

Code :
  1. /*! \file decode.c
  2. * \brief module permettant de decoder une fonction entrée par l'utilisateur.  
  3. * \author : Ansel Guillaume && Alexandre Aurelie
  4. * \version : 0.2  
  5. * \bug : ne recupere pas la valeur du critere
  6. * \date : 11 Nov 2004
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "type_objet.h"
  12. #define OK 0 /*!<La commande n'a pas retourné d'erreur*/
  13. #define ERREUR -1 /*!<La commande n'était pas valide*/
  14. /*-------------------------------*/
  15. int decode(char *nom_cde){
  16.   /*! Cette fonction alanyse la commande entrée par l'utilisateur et effectur l'action  
  17.    * correspondante si cette commande est valide (si elle correspond a une commande
  18.    * valide du projet)
  19.    *
  20.    * \param nom_cde : chaine de caractere contenant la commande à analyser
  21.    * \retval <int> retourne une constante OK ou ERREUR (type int). OK : 0, ERREUR : -1. Une erreur est
  22.    * retournée si la commande entrée n'est pas valide (non présente dans le projet).
  23.    */
  24.   char *c, *val_critere;
  25.   int  num_critere=0;
  26.  
  27.   c =(char *)malloc(sizeof(char) * strlen(nom_cde) +1);
  28.   strcpy(c,nom_cde);
  29.   while(c!='\0'){ /* <== traitement recursif? si oui, pas de boucle */
  30.     if(*c == '&'){ /* On doit traiter une commande de selection/creation/maj */
  31.       c++;
  32.       if(isdigit(*c)){
  33. num_critere= *c - '0'; /*Le caractere c est le numero d'un critere.*/
  34. c++;           
  35. switch (*c) {
  36.   /* a implementer : variable / pointeur memorisant la primitive */
  37. case '<' : printf("primitive S : <\n" ); break;
  38. case '=' : printf("primitive S : =\n" ); break;
  39. case '>' : printf("primitive S : >\n" ); break;
  40. case 'i' : printf( "primitive C : creation\n" ); break;
  41. case 'm' :printf("primitive MAJ : modification\n" ); break;     
  42. default : printf("primitive non connue (%c)",*c); return ERREUR; break;
  43. }
  44.       }     
  45.       val_critere = (char *)malloc(sizeof(char));
  46.       strncpy(val_critere,c,1);
  47.       c++;     
  48.       while(isalpha(*c) || *c != '\0' || !isspace(*c)){
  49. /* concatener la valeur du critere caractere par caractere dans la variable val_critere */
  50. if((val_critere = (char *)realloc(val_critere, strlen(val_critere) +1)) == NULL){
  51.   puts("ERREUR lors de l'allocation memoire" );
  52.   return ERREUR;
  53. }
  54. strcat(val_critere, c);
  55. c++;
  56.       }
  57.       printf("val_critere : %s\n", val_critere);
  58.     }else{ /* Si le '&' n'était pas présent en début de ligne */
  59.       if (strncmp(c,"save",4))
  60. puts("primitive save" );
  61.       if (strncmp(c,"load",4))
  62. puts("primitive load" ); 
  63.       if (strncmp(c,"quit",4)){
  64. puts("exit" );
  65. return OK;
  66.       }           
  67.     }
  68.     /* appeler la fonction deduite (pointeur de fonction?) */
  69.     /* traitement recursif ? */
  70.   }   
  71. }


 
le main :  

Code :
  1. /*!\file mbdd.c
  2. * \brief module principal du programme, ne contient que la fonction main(). Saisie de la commande et appelle la fonction decode().
  3. * \author : Ansel Guillaume && Alexandre Aurelie
  4. * \version : 0.2
  5. * \bug : unknown  
  6. * \date : 11 Nov 2004
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "decode.h"
  11. #include "type_objet.h"
  12. #define MAX 10
  13. /*-------------------------------*/
  14. int main(void){
  15. /*! Fonction principale du programme, sert a saisir une commande par l'utilisateur  
  16.   * et appelle la fonction decode() afin de l'analyser et executer l'action en consequence.
  17.   *
  18.   * \param void
  19.   * \retval <int> : Pour compatibilité C ANSI (valeur de retour constante : 1)
  20.   */
  21.   char cmd[MAX];
  22.   puts("MBDD v0.0" );
  23.   fgets(cmd,MAX+1,stdin); 
  24.   if(decode(cmd)==ERREUR)
  25.     puts("impossible d'executer la commande" );
  26.   system("pause" );   
  27.   return EXIT_SUCCESS;
  28. }


 
merci de votre aide  :hello:


Message édité par c0wb0y le 11-11-2004 à 23:03:33
Reply

Marsh Posté le 11-11-2004 à 15:22:13   

Reply

Marsh Posté le 11-11-2004 à 15:26:41    

changement de la constante MAX dans mbdd.c  
#define MAX 255
 
plus de warning a la compilation :  

Citation :

D:\programmation\mbdd>make
gcc.exe -c mbdd.c -o mbdd.o -I"C:/Prgram Files/Dev-Cpp/include"    -ansi -traditional-cpp
gcc.exe mbdd.o decode.o  -o "mbdd.exe" -L"C:/Prgram Files/Dev-Cpp/lib"

Reply

Marsh Posté le 11-11-2004 à 16:15:57    

problème de parenthèsage
 
l'opérateur = a une priorité moindre que ==
 
p = (char *)realloc(val_critere, strlen(val_critere) +1) == NULL)
 
p vaut donc 0 ou 1

Reply

Marsh Posté le 11-11-2004 à 16:30:00    

ha, merci, je n'avais pas fait attention :|
 
J'ai ajouter des parenthèses sur l'expression, ce qui donne :  

Code :
  1. if((val_critere = (char *)realloc(val_critere, strlen(val_critere) +1)) == NULL){


 
Le probleme doit venir de mon affectation :  

Code :
  1. strncpy(val_critere,c,1); (L.52)


j'ai ajouter un puts avant, et un apres, j'ai le premier qui s'affiche pas mais le suivant =/
 
Je n'ai jamais utiliser les concaténations en C, je dois mal m'y prendre =/

Reply

Marsh Posté le 11-11-2004 à 20:16:52    

up  :sleep:

Reply

Marsh Posté le 11-11-2004 à 21:55:17    

Reply

Marsh Posté le 11-11-2004 à 22:58:44    

J'ai lu un peu ce que tu me proposes, mais j'ai un peu de mal a comprendre le tout :/
Mon probleme doit probablement venir de l'utilisation de pointeur.
 
J'ai ajouté une ligne a mon code, car en fait ma variable val_critere était un pointeur non initialisé, donc de comportement inconnu.
J'ai donc ajouter :  

Code :
  1. val_critere = (char *)malloc(sizeof(char));


Maintenant, il execute bien la partie de code se trouvant en dessous (il rentre dans le while)
Mais j'ai une erreur sur le realloc.

Citation :

MBDD v0.0
&3irouge
primitive C : creation
ERREUR lors de l'allocation memoire
impossible d'executer la commande


 
 
je met a jour la source du post de tete.
 
 
Au fait, je ne sais pas si le lien que tu me suggerais était dans le but de me faire utiliser strlcpy() plutot que strncpy, mais dans tous les cas, c'est impossible, je dois faire du code standard pour qu'il puisse etre compilé sous windows, et sur les machines de l'iut (linux red hat 9). Merci quand meme de ton aide ;) (d'ailleur si tu pouvais expliquer en une ligne ou deux l'interet de strlcpy (si ce n'est la rapidité d'execution qui d'apres le tableau de fin est bien meilleure que les autres), merci :)


Message édité par c0wb0y le 11-11-2004 à 23:02:02
Reply

Marsh Posté le 11-11-2004 à 23:21:32    

Ton val_critere il est trop court après ton premier malloc pour y copier la chaîne c avec le caractère nul, c'est moyen.
 
strncmp renvoie 0 si les chaînes sont égales, donc ça va pas.
 
Pour strlcpy, c'est sensé être plus pratique (meilleur comportement et différence dans la valeur de retour), mais dans le document il y a un exemple qui utilise strncpy (exemple 1)b)). Le reste c'est pour la culture générale ;) Les fonctions strl* sont pas encore adoptées sous Linux, elles viennent d'OpenBSD.

Reply

Marsh Posté le 11-11-2004 à 23:28:18    

Ligne 36:

Code :
  1. while(c!='\0'){ /* <== traitement recursif? si oui, pas de boucle */


Tu voulais en fait faire:

Code :
  1. while(*c!='\0'){ /* <== traitement recursif? si oui, pas de boucle */


et

Code :
  1. while(*c){ /* <== traitement recursif? si oui, pas de boucle */

serait encore plus simple
 
A+,


Message édité par gilou le 11-11-2004 à 23:28:56

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-11-2004 à 23:43:42    

blurk a écrit :

Ton val_critere il est trop court après ton premier malloc pour y copier la chaîne c avec le caractère nul, c'est moyen.
 
strncmp renvoie 0 si les chaînes sont égales, donc ça va pas.
 
Pour strlcpy, c'est sensé être plus pratique (meilleur comportement et différence dans la valeur de retour), mais dans le document il y a un exemple qui utilise strncpy (exemple 1)b)). Le reste c'est pour la culture générale ;) Les fonctions strl* sont pas encore adoptées sous Linux, elles viennent d'OpenBSD.


 
Bah en fait, quand j'affecte dans val_critere, je ne veux que le premier caractere, donc je ne compte meme pas le caractere nul normalement =/ (j'veux concatener caractere par caractere jusqu'a ce que je trouve un espace ou le '\0') Par contre, je viens de penser que je devrais l'ajouter moi meme a la fin de caractere nul non ?
 
pour le strncmp qui renvoie 0, j'ai corrigé (j'ai ajouter un test du resultat dans mon if (si c'est == 0 alors ...)
 

gilou a écrit :

Ligne 36:

Code :
  1. while(c!='\0'){ /* <== traitement recursif? si oui, pas de boucle */


Tu voulais en fait faire:

Code :
  1. while(*c!='\0'){ /* <== traitement recursif? si oui, pas de boucle */


et

Code :
  1. while(*c){ /* <== traitement recursif? si oui, pas de boucle */

serait encore plus simple
 
A+,


 
corrigé, merci bien  :jap:  
( par contre, je préfère la 2eme écriture que je trouve plus lisible pour moi ^^" )

Reply

Marsh Posté le 11-11-2004 à 23:43:42   

Reply

Marsh Posté le 12-11-2004 à 20:43:08    

yeah yeah ! :D
j'ai reussi a resoudre le probleme :)
( j'ai revu mes mallocs etc... )
 
Comme quoi, inutile de forcer dans un code si on a pas les idées claires, du repos permet de prendre du recul et apres, on debug bien mieux :)
 
Je vous poste la version actuelle du code (encore des trucs a ajouter pour faire faire a la fonction les choses demandées, mais ca ne devrait pas poser probleme :)
 

Code :
  1. /*! \file decode.c
  2. * \brief module permettant de decoder une fonction entrée par l'utilisateur.  
  3. * \author : Ansel Guillaume && Alexandre Aurelie
  4. * \version : 0.2  
  5. * \bug : ne recupere pas la valeur du critere
  6. * \date : 11 Nov 2004
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "type_objet.h"
  12. #define OK 0 /*!<La commande n'a pas retourné d'erreur*/
  13. #define ERREUR -1 /*!<La commande n'était pas valide*/
  14. /*-------------------------------*/
  15. int decode(char *nom_cde){
  16.   /*! Cette fonction alanyse la commande entrée par l'utilisateur et effectur l'action  
  17.    * correspondante si cette commande est valide (si elle correspond a une commande
  18.    * valide du projet)
  19.    *
  20.    * \param nom_cde : chaine de caractere contenant la commande à analyser
  21.    * \retval <int> retourne une constante OK ou ERREUR (type int). OK : 0, ERREUR : -1. Une erreur est
  22.    * retournée si la commande entrée n'est pas valide (non présente dans le projet).
  23.    */
  24.   char *c, *val_critere;
  25.   int  num_critere=0;
  26.  
  27.   c =(char *)malloc(sizeof(char) * strlen(nom_cde) +1);
  28.   strncpy(c,nom_cde,strlen(nom_cde)+1); 
  29.   while(*c!='\0'){ /* <== traitement recursif? si oui, pas de boucle */
  30.     if(*c == '&'){ /* On doit traiter une commande de selection/creation/maj */
  31.       c++;
  32.       if(isdigit(*c)){
  33. num_critere= *c - '0'; /*Le caractere c est le numero d'un critere.*/
  34. c++;           
  35. switch (*c) {
  36.   /* a implementer : variable / pointeur memorisant la primitive */
  37. case '<' : printf("primitive S : <\n" ); break;
  38. case '=' : printf("primitive S : =\n" ); break;
  39. case '>' : printf("primitive S : >\n" ); break;
  40. case 'i' : printf( "primitive C : creation\n" ); break;
  41. case 'm' :printf("primitive MAJ : modification\n" ); break;     
  42. default : printf("primitive non connue (%c)",*c); return ERREUR; break;
  43. }         
  44. val_critere = (char *)malloc(sizeof(char));
  45. c++;     
  46. while(isalpha(*c) && *c != '\0' && !isspace(*c)){  
  47.   /* concatener la valeur du critere caractere par caractere dans la variable val_critere */
  48.   if((val_critere = (char *)realloc(val_critere, strlen(val_critere) +1)) == NULL){
  49.     puts("ERREUR lors de l'allocation memoire" );
  50.     return ERREUR;
  51.   }
  52.   strncat(val_critere, c,1);
  53.   c++;  
  54. }
  55. c++;
  56.       }
  57.     }else{ /* Si le '&' n'était pas présent en début de ligne */
  58.       if (strncmp(c,"save",4)==0){
  59. puts("primitive save" );
  60. c+=4;
  61.       }
  62.       if (strncmp(c,"load",4)==0){
  63. puts("primitive load" );
  64. c+=4;
  65.       }
  66.       if (strncmp(c,"list",4)==0) {
  67. puts("primitive list" );
  68. c+=4;
  69.       }
  70.       if(strncmp(c,"print",5)==0){
  71. puts("primitive print" );
  72. c+=5;
  73.       }
  74.       if (strncmp(c,"quit",4)==0){
  75. puts("exit" );
  76. c+=4;
  77. return OK;
  78.       }           
  79.       c++;     
  80.     }
  81.     /* appeler la fonction deduite (pointeur de fonction?)
  82.      * reinitialiser variable
  83.      *retour en debut de boucle
  84.      */ 
  85.     /* *func(num_critere, val_critere)*/
  86.     num_critere = 0;
  87.     free(val_critere);
  88.   }
  89.   /* traitement recursif ? */
  90.   return OK;
  91. }

Reply

Sujets relatifs:

Leave a Replay

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