Problème avec strcpy

Fermé
Myrath92 Messages postés 7 Date d'inscription samedi 1 février 2014 Statut Membre Dernière intervention 5 mai 2014 - 4 mai 2014 à 10:59
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 6 mai 2014 à 11:13
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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 4/05/2014 à 19:19
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 samedi 1 février 2014 Statut Membre Dernière intervention 5 mai 2014
5 mai 2014 à 18:57
Merci, Je le corrige le plus tôt possible et je reposte le résultat.
0
Myrath92 Messages postés 7 Date d'inscription samedi 1 février 2014 Statut Membre Dernière intervention 5 mai 2014
Modifié par Myrath92 le 5/05/2014 à 21:47
 #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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
6 mai 2014 à 11:13
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