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 -
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;
}
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
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
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
ç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.
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,