Problème avec strcpy

Myrath92 Messages postés 7 Date d'inscription   Statut Membre Dernière intervention   -  
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour,
Donc voilà au cadre d'un projet scolaire on nous a demandé de créer un analyseur lexica. En gros c'est un programme qui lit un bout de code à partir d'un fichier pour retourner une structure à deux champs l'un est la nature du bout de code (identifiant, mot clé, entier, réel, ponctuation...) le second est ça valeur ou 0. Le problème c'est que mon programme crash à l'appel de strcpy pour une raison que j'ignore, mon fichier contient 25. Merci.

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

// verification de l'ouverture du fichier
FILE* aEteOuvert(char nom[9]);

//verification du type du caractère lu
char* deType(char cc);

//structure à retrouver
typedef struct resultat
{
char* champ1;
char* champ2;
} res;

res* Anal_lex(FILE* fich, res* s);

//affiche le tableau
void affichTab(char** tab, int tai);

//initialiser le tableau de mot clés
char** motCle();

// verifie si c'est un entier
void estNum(FILE* fich1,int* j1,int* k1, res* s1);

//verifie si c'est reel
void estReel(FILE* fich2,int* j2,int* k2,res* s2);

//verifie si c'est un mot clé
void estMotCle(char** t,res* s3);

//vérifie si c'est un identifiant
void estId(FILE* fich4,res* s4);

//fonction principale
int main()
{
res* st;
FILE* fichier;
st= malloc(sizeof(res));
st->champ1=(char*) malloc(25*sizeof(char));
st->champ2= (char*) malloc(25*sizeof(char));
st->champ1="rien";
st->champ2="rien";
fichier=aEteOuvert("test.txt");
st=Anal_lex(fichier,st);
printf("\n La nature est :%s",st->champ1);
printf("\n La valeur est :%s",st->champ2);
fclose(fichier);
free(st->champ1);
free(st->champ1);
free(st);
return 0;
}

res* Anal_lex(FILE* fich, res* s)
{
char** ta;
char ch;
ta=motCle();
ch=(char) fgetc(fich);
printf("\n %d \n",ch);
switch (ch)
{
case '\t': case '\n': case ' ': if (strcmp(s->champ1,"rien"))
Anal_lex(fich,s);
else
return s;
break;
case ';' :s->champ1="pv";
s->champ2="0";
break;

case ')' : s->champ1="pf";
s->champ2="0";
break;

case '(' : s->champ1="po";
s->champ2="0";
break;

case ':' : s->champ1="dp";
s->champ2="0";
break;

case ',' : s->champ1="v";
s->champ2="0";
break;

case '+' : s->champ1="opa";
s->champ2="plus";
break;

case '*' : s->champ1="opa";
s->champ2="moins";
break;

case '!' : if (fgetc(fich)!='=')
{
s->champ1="erreur";
s->champ2="erreur";
}
else
{
s->champ1="opa";
s->champ2="dif";
}
break;

case '<' : s->champ1="opa";
s->champ2="inf";
if (fgetc(fich)=='=')
{
s->champ1="opa";
s->champ2="ioueg";
}
break;

case '>' : s->champ1="opa";
s->champ2="sup";
if (fgetc(fich)=='=')
{
s->champ1="opa";
s->champ2="soueg";
}
break;

case '=' : s->champ1="affect";
s->champ2="0";
if (fgetc(fich)=='=')
{
s->champ1="opa";
s->champ2="eg";
}
break;
default:

s->champ1="erreur";
s->champ2="erreur";
if (ch=='-'||isdigit(ch))
{
int j,k;
s->champ1="entier";
if (ch=='-')
{
s->champ2="-";
}
else
printf("debug1 \n");
strcpy(s->champ2,&ch); // ça crash ici!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
printf("debug2");
j=0;
k=0; //pour savoir s'il y a un poinr en cours de lecture donc non entier
printf("debug10\n");
estNum(fich,&j,&k,s);
printf("debug11\n");
if ((k==1)&&(j>1))
{
fseek(fich,-1*j,SEEK_CUR);
j=0;
s->champ1="reel";
s->champ2="-";
estReel(fich,&j,&k,s);
}
else if ((k==2)||(j==1))
{
s->champ1="erreur";
s->champ2="erreur";
}

}
if (isalpha(ch))
{
s->champ1="ident";
s->champ2=&ch;
estId(fich,s);
estMotCle(ta,s);
}
break;
}
free(ta);
return s;
}

void affichTab(char** tab, int tai)
{
int ind;
printf("\n|");
for(ind=0;ind<tai;ind++)
{
printf("%s|",tab[ind]);
}
printf("\n");
}

char** motCle()
{
char** Tref;
Tref = (char**) malloc(sizeof(char*)*5);
*Tref="integer";
*(Tref+1)="real";
*(Tref+2)="bool";
*(Tref+3)="start";
*(Tref+4)="stop";
return Tref;
}

void estId(FILE* fich4,res* s4)
{
char chtest;

chtest=(char) fgetc(fich4);
printf("\n %c",chtest);
if (isalnum(chtest))
{
strcat(s4->champ2,&chtest);
estId(fich4,s4);
}
}

void estNum(FILE* fich1,int* j1,int* k1,res* s1)
{
char chtest;
printf("makammalch");
(*j1)++;
chtest=(char) fgetc(fich1);
if (chtest=='-')
{
(*k1)=1;
}
else if ((chtest=='.'))
{
(*k1)=1;
}
else if (isdigit(chtest))
{
strcat(s1->champ2,&chtest);
estNum(fich1,j1,k1,s1);
}
}

void estReel(FILE* fich2,int* j2,int* k2,res* s2)
{
char chtest;
(*j2)++;
chtest=(char) fgetc(fich2);
if (chtest=='-')
{
*k2=2;
}
else if (chtest=='.')
{
if ((!(strcmp(s2->champ2,"-")))||(strchr(s2->champ2,'.'))!=NULL)
{
*k2=2;
}
else
{
strcat(s2->champ2,&chtest);
estReel(fich2,j2,k2,s2);
}
}
else if (isdigit(chtest))
{
strcat(s2->champ2,&chtest);
estReel(fich2,j2,k2,s2);
}
}

void estMotCle(char** t,res* s3)
{
int l=0;
int l1=0;

while ((l==0) && (l1<5))
{
if (strcmp(s3->champ2,t[l1]))
{
s3->champ1="motCle";
l1=1;
}
l1++;

}
}



FILE* aEteOuvert(char nom[5])
{
FILE* fil;
fil=fopen(nom,"r");
if (fil!=NULL)
printf("\n fichier ouvert avec succes");
else
printf("\n l'ouverture du fichier a echoue");
return fil;
}



1 réponse

fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
En fait, le strcpy() c'est la seule chose qui est juste ;-).

st->champ1=(char*) malloc(25*sizeof(char));
Pour info, pas besoin de cast en C.

st->champ1="rien";
Cela ne copie pas la chaîne rien dans la zone allouée par malloc(). Cela rattache juste st->champ1 à la zone dans la mémoire comprenant la chaîne "rien". Du coup, il y a fuite de mémoire.
Je pense que toi tu voulais faire : strcpy(st->champ1, "rien");
Et ça, c'est à faire pour st->champ2 également.

chtest=(char) fgetc(fich1);
if (chtest=='-')

Pourquoi ne pas déclarer chtest en int ? Ca serait mieux.
Ainsi cela donnerait : chtest=fgetc(fich1);
if (chtest=='-') /*pas de cast car '-' renvoie un int et non un char*/

strcat(s2->champ2,&chtest);
chtest est un char. Donc il ne se termine pas par un '\0'. Tu ne peux donc pas utiliser strcat...

Voilà. Corrige déjà tout ça, et reposte ton code entre deux balises "code c" s'il reste des erreurs ; ça sera plus lisible.
<"code c">Ici tu mets ton code<"/code"> (sans les guillemets)
Cdlt

Google is your friend
2
Myrath92 Messages postés 7 Date d'inscription   Statut Membre Dernière intervention  
 
Merci, Je le corrige le plus tôt possible et je reposte le résultat.
0
Myrath92 Messages postés 7 Date d'inscription   Statut Membre Dernière intervention  
 
 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// verification de l'ouverture du fichier
FILE* aEteOuvert(char nom[9]);

//verification du type du caractère lu
char* deType(char cc);

//structure à retrouver
typedef struct resultat
{
    char* champ1;
    char* champ2;
} res;

res* Anal_lex(FILE* fich, res* s);

//affiche le tableau
void affichTab(char** tab, int tai);

//initialiser le tableau de mot clés
char** motCle();

// verifie si c'est un entier
void estNum(FILE* fich1,int* j1,int* k1, res* s1);

//verifie si c'est reel
void estReel(FILE* fich2,int* j2,int* k2,res* s2);

//verifie si c'est un mot clé
void estMotCle(char** t,res* s3);

//vérifie si c'est un identifiant
void estId(FILE* fich4,res* s4);

//fonction principale
int main()
{
    res* st;
    FILE* fichier;
    st= malloc(sizeof(res));
    st->champ1=(char*) malloc(10*sizeof(char));
    st->champ2= (char*) malloc(10*sizeof(char));
    strcpy(st->champ1,"rien");
    strcpy(st->champ2,"rien");
    fichier=aEteOuvert("test.txt");
    st=Anal_lex(fichier,st);
    printf("\n La nature est  :%s",st->champ1);
    printf("\n La valeur est  :%s",st->champ2);
    fclose(fichier);
    free(st->champ1);
    free(st->champ1);
    free(st);
    return 0;
}

res* Anal_lex(FILE* fich, res* s)
{
    char** ta;
    int ch;
    ta=motCle();
    ch=fgetc(fich);
    printf("\n %d \n",ch);
   switch (ch)
    {
        case '\t': case '\n': case ' ': if (strcmp(s->champ1,"rien"))
                                        Anal_lex(fich,s);
                                        else
                                        return s;
                                        break;
        case ';' :strcpy(s->champ1,"pv");
                  strcpy(s->champ2,"0");
                  break;

        case ')' : strcpy(s->champ1,"pf");
                   strcpy(s->champ2,"0");
                   break;

        case '(' : strcpy(s->champ1,"po");
                   strcpy(s->champ2,"0");
                   break;

        case ':' : strcpy(s->champ1,"dp");
                   strcpy(s->champ2,"0");
                   break;

        case ',' : strcpy(s->champ1,"v");
                   strcpy(s->champ2,"0");
                   break;

        case '+' : strcpy(s->champ1,"opa");
                   strcpy(s->champ2,"plus");
                   break;

        case '*' : strcpy(s->champ1,"opa");
                   strcpy(s->champ2,"fois");
                   break;

        case '!' : if (fgetc(fich)!='=')
                 {
                    strcpy(s->champ1,"erreur");
                    strcpy(s->champ2,"erreur");
                 }
                 else
                 {
                    strcpy(s->champ1,"opa");
                    strcpy(s->champ2,"dif");
                 }
                 break;

        case '<' : strcpy(s->champ1,"opa");
                   strcpy(s->champ2,"inf");
                 if (fgetc(fich)=='=')
                 {
                   strcpy(s->champ1,"opa");
                    strcpy(s->champ2,"ioueg");
                 }
                 break;

        case '>' : strcpy(s->champ1,"opa");
                   strcpy(s->champ2,"sup");
                 if (fgetc(fich)=='=')
                 {
                    strcpy(s->champ1,"opa");
                    strcpy(s->champ2,"soueg");
                 }
                 break;

        case '=' : strcpy(s->champ1,"affect");
                   strcpy(s->champ2,"0");
                  if (fgetc(fich)=='=')
                  {
                    strcpy(s->champ1,"opa");
                    strcpy(s->champ2,"eg");
                  }
                  break;
        default:

            strcpy(s->champ1,"rien");
            strcpy(s->champ2,"rien");
    if (ch=='-'||isdigit(ch))
        {
          int j,k;
          strcpy(s->champ1,"Entier");
          if (ch=='-')
          {
           strcpy(s->champ2,"-");
          }
          else
           strcpy(s->champ2,(char*) &ch);
           j=0;
           k=0; //pour savoir s'il y a un poinr en cours de lecture donc non entier
           estNum(fich,&j,&k,s);
           if ((k==1)&&(j>1))
          {
              fseek(fich,-1*j,SEEK_CUR);
              j=0;
              strcpy(s->champ1,"Reel");
              strcpy(s->champ2,"-");
              estReel(fich,&j,&k,s);
          }
          else if ((k==2)||(j==1))
            {
               strcpy(s->champ1,"erreur");
               strcpy(s->champ2,"erreur");
            }

        }
        if (isalpha(ch))
        {
          strcpy(s->champ1,"Ident");
          strcpy(s->champ2,(char*) &ch);
          estId(fich,s);
          estMotCle(ta,s);
          }
        break;
        }
        free(ta);
    return s;
}

void affichTab(char** tab, int tai)
{
    int ind;
    printf("\n|");
    for(ind=0;ind<tai;ind++)
    {
        printf("%s|",tab[ind]);
    }
    printf("\n");
}

char** motCle()
{
    char** Tref;
    Tref = (char**) malloc(sizeof(char*)*5);
    *Tref="integer";
    *(Tref+1)="real";
    *(Tref+2)="bool";
    *(Tref+3)="start";
    *(Tref+4)="stop";
    return Tref;
}

void estId(FILE* fich4,res* s4)
{
    int chtest;
    chtest=fgetc(fich4);
    printf("\n %c",chtest);
    if (isalnum(chtest))
    {
    strcat(s4->champ2,(char*) &chtest);
    estId(fich4,s4);
    }
}

void estNum(FILE* fich1,int* j1,int* k1,res* s1)
{
  char chtest;
  (*j1)++;
  chtest=(char) fgetc(fich1);
  if (chtest=='-')
  {
         (*k1)=1;
  }
  else if ((chtest=='.'))
  {
        (*k1)=1;
  }
  else if (isdigit(chtest))
  {
      strcat(s1->champ2,&chtest);
      estNum(fich1,j1,k1,s1);
  }
}

void estReel(FILE* fich2,int* j2,int* k2,res* s2)
{
    int chtest;
  (*j2)++;
  chtest=fgetc(fich2);
  if (chtest=='-')
  {
      *k2=2;
  }
  else if (chtest=='.')
            {
                if ((!(strcmp(s2->champ2,"-")))||(strchr(s2->champ2,'.'))!=NULL)
                    {
                        *k2=2;
                    }
               else
                    {
                        strcat(s2->champ2,(char*) &chtest);
                        estReel(fich2,j2,k2,s2);
                    }
            }
  else if (isdigit(chtest))
  {
      strcat(s2->champ2,(char*) &chtest);
      estReel(fich2,j2,k2,s2);
  }
}

void estMotCle(char** t,res* s3)
{
int l=0;
int l1=0;

while ((l==0) && (l1<5))
{
    if (strcmp(s3->champ2,t[l1]))
    {
        strcpy(s3->champ1,"Mot_Cle");
        l1=1;
    }
    l1++;

}
}



FILE* aEteOuvert(char nom[5])
{
    FILE* fil;
    fil=fopen(nom,"r");
    if (fil!=NULL)
        printf("\n fichier ouvert avec succes");
    else
        printf("\n l'ouverture du fichier a echoue");
    return fil;
}


ça ne crash plus Merci beaucoup :D Par contre pour un fichier d'input où il n'y a que des lettres il n'arrive pas à sortir du estId, pour une raison qui m'est inconnue...Pour l'instant ;)
Encore merci.
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Il reste encore des parties non corrigées :
strcpy(s->champ2,(char*) &ch);
ch n'est pas un char* mais un char... Ca va poser problème.

strcat(s4->champ2,(char*) &chtest);
chtest n'est pas un char*, ça va poser problème...

Remarque supplémentaire :
Tref = (char**) malloc(sizeof(char*)*5);
*Tref="integer";

Pourquoi faire un malloc ?
Tu pourrais faire simplement : char *Tref[]={"Integer", "real", "...",...};

Sinon, je remets (car je suis têtu :-)) :
st= malloc(sizeof(res));
st->champ1=(char*) malloc(10*sizeof(char));

Le (char*) est facultatif et même déconseillé. Si toutefois tu veux le garder, alors il faut le faire partout, y compris pour st=(...)malloc(...)

Cdlt,
0