Erreur à l'exécution mais pas à la compil

Fermé
moi411 - 7 juin 2005 à 13:36
 moi411 - 11 juin 2005 à 18:12
Bonjour tous le monde,
J'ai donc un problème avec un programme qui ne m'affiche pas d'erreur à la compilation mais qui s'arrète lors de l'exécution (quand j'arrive sur l'appelle à une fonction),
il doit:
_avec une première fonction, remplir un tableau avec 50 nombres aléatoires.
_avec une deuxième, vider ce tableau dans un autre (en prenant soin de ne garder que les nombres <91, >65 et le 32 si il est dans le tableau).
_avec une troisième, afficher le deuxième tableau en convertissant les chiffres en caractère ascii.

Toutes les variables doivent être déclarées localement à la fonction main... Ci-joint le code:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>

//prototype de la fonction remplir
void remplir(int *tab1, int *i);

//prototype de la fonction vider
int vider(int *tab1, int *tab2, int *j, int *i);

//prototype de la fonction aff
void aff(int *tab2, int *j, int *i);

int main()
{
int *buffer1; //vecteur de départ
int *buffer2; //vecteur résultat
int *i; //indice de vecteur
int *j; //indice de vecteur
int k; //indice de vecteur
char choix; //switch

do
{
clrscr();
printf("\n\n\tMENU\n\n");
printf("1.Remplir le buffer\n");
printf("2.Tampon resultat\n");
printf("3.Afficher le tampon\n");
printf("4.Quitter\n\n");

printf("\n\n\nFaites un choix: ");
choix=getch();
printf("%c",choix);

switch(choix)
{
//Remplir le tampon
case'1': printf("\nVoici le tampon: \n\n");
remplir(buffer1,i);
for(k=0; k<50; k++) //On affiche le buffer
{
printf("%3d",buffer1);
}
printf("\n\n\n\tAppuyer sur une touche pour continuer...");
getchar();
break;

//Tampon résultat
case'2': if(vider(buffer1,buffer2,j,i)==1)
{
printf("\n\n\nLe tampion resultat est rempli\n\n\n");
}
printf("\n\n\n\tAppuyer sur une touche pour continuer...");
getchar();
break;

//afficher le tampon
case'3': printf("\n\n\nVoici le tampon resultat:\n\n\n");
aff(buffer2,j,i);
printf("\n\n\n\tAppuyer sur une touche pour continuer...");
getchar();
break;

//quitter
case'4':
break;
}
}
while(choix!='4');
return 0;
}

//fonction remplir
void remplir(int *tab1, int *i)
{
srand(time(NULL));

for(*i=0; *i<50; (*i)++) //on remplit le buffer
{
tab1[*i]=rand() %100;
}
}

//fonction vider
int vider(int *tab1, int *tab2, int *j, int *i)
{
*j=0;

for(*i=0; *i<50; (*i)++)
{
if(tab1[*i]<=91 && tab1[*i]>=65 || tab1[*i]==32)
{ //on trie le buffer
tab2[*j]=tab1[*i];
(*j)++;
}
}
return 1;
}

void aff(int *tab2, int *j, int *i)
{
for(*i=0; *i<*j; (*i)++) //on affiche le buffer final
{
printf("%c ",tab2[*i]);
}
}

Voilà c'est tout ce que je peux dire. Si quelqu'un peut m'aider je le(s) remercie d'avance.

6 réponses

manu_ Messages postés 7 Date d'inscription mercredi 8 juin 2005 Statut Membre Dernière intervention 11 juin 2005
8 juin 2005 à 17:11
Bonjour,
le problème est que quand tu déclares tes buffers, tu ne fais que déclarer un pointeur sur un entier, sans que ce pointeur soit initialisé (à la valeur de l'adresse d'un entier).
Par la suite, tu tenteras d'écrire tes nombres aléatoires à un emplacement en mémoire que tu ne connais pas, et sur lequel il t'est interdit par le système d'exploitation d'écrire.

Il faut donc que tu déclares un pointeur sur un tableau de 50 entiers :
int buffer1[50] ; //vecteur de départ

Autre solution : te servir de la fonction malloc.
int *buffer1; //vecteur de départ
buffer=(int*)malloc(sizeof(int)*50) ;

La fonction malloc renvoie un pointeur sur un tableau (plus généralement sur une zone en mémoire) de n octets, n étant la valeur de son paramètre. Cette opération s'appelle l'allocation mémoire. Si l'allocation échoue (parce que tu as demandé par exemple une zone mémoire trop grande), la valeur retournée par
0
manu_ Messages postés 7 Date d'inscription mercredi 8 juin 2005 Statut Membre Dernière intervention 11 juin 2005
8 juin 2005 à 22:26
Excuse moi pour l'interruption. Voilà la suite :
...la fonction malloc est NULL. De plus, après l'utilisation d'une zone mémoire allouée avec malloc, il faut avant de terminer ton programme la libérer au moyen de la fonction free. Son unique paramètre est le pointeur préalablement initialisé avec malloc.

Autre erreur aussi importante : l'utilisation des pointeurs i et j est mauvaise. Le fait que tu déclares un pointeur i ne signifie pas que l'adresse contenue dans i soit l'adresse d'un entier présent en mémoire. La solution est :
int i ;
int j ;

...

remplir(buffer1,&i) ;

...

vider(buffer1,buffer2,&j,&i)

...

aff(buffer2,&j,&i) ;

...


Autre erreur dans printf("%3d",buffer1); : buffer1 est un tableau d'entier et non un entier. L'instruction correcte est printf("%3d",buffer1[k]);

Voilà !
Au niveau de l'algorithme j'ai pas trop regardé, mais en général je trouve que tu te compliques la vie avec tes pointeurs ; tes fonctions ont un "effet de bord" pas nécessaire et qui alourdit considérablement le code.
Préfère les variables locales à l'intérieur de tes fonctions. A ta demande je peux te proposer mon écriture de ton programme.

En tous les cas bonne programmation !
0
Salut,
Merci pour tes corrections, pour le printf("%3d",buffer1[k]); je ne sais pas comment j'ai fais pour ne pas le voir!!! (sans doute le stress puisque c'était mon examen!!!)

Sinon pour la fonction malloc, je ne l'ai jamais utilisé. Je savais qu'elle existait, mais sans plus.
Toujours pour malloc, pour résumer on réserve (dans mon cas) 50 emplacements mémoire et si j'ai bien compris c'est le même principe que si on faisait: int buffer1[50]...
Par contre avec int *buffer1, on réserve 1 seul emplacement mémoire et les 49 autres se placent n'importe où. C'est bien ça?

Encore une chose, la consigne voulait que les variables soit déclarée localement à la fonction main, personnellement je n'aurai pas fais comme ça non plus...

Sinon je te remercie pour ton aide et si tu pouvais m'écrire ton code
se ne serai pas de refus... Bonne programmation à toi aussi.
0
manu_ Messages postés 7 Date d'inscription mercredi 8 juin 2005 Statut Membre Dernière intervention 11 juin 2005
10 juin 2005 à 16:41
Salut !
D'abord, quand ton prof demande des variables locales, je pense qu'il ne parle que des buffers. Il n'y a aucun interêt à déclarer des variables dont l'utilisation sera faite dans d'autres fonctions. En revanche, et c'est ce que ton prof ne voulait pas, c'est que tu définisses en global tes buffers et d'autres variables ; c'est une programmation bien moins propre et moins "esthétique".

Précision : avec int *buffer1 tu ne déclares qu'une variable pouvant contenir l'adresse d'un entier, mais tu ne réserves pas de place pour cet entier sur lequel tu "voudrais" pointer.
C'est ensuite à toi de réserver de la place pour tes 50 entiers, et d'affecter à buffer1 l'adresse du premier entier réservé.

Ensuite, il existe une petite différence avec int buffer1[50] et l'utilisation du malloc : avec la première solution, ton programme executable contiendra l'emplacement de ces 50 entiers (si tu regardes la taille de ton fichier EXE en réservant 5000 entiers, celui-ci sera plus gros qu'avec 50 entiers). L'utilisation de malloc "retarde" cette réservation : c'est lors de l'execution de ton programme que celui-ci va demander à Windows de chercher quelque part en mémoire une zone pour 50 entiers, et Windows te renverra un pointeur sur une telle zone (ou NULL si il n'a pas pu en trouver). D'ailleurs que tu demandes 50 ou 50000 entiers dans un malloc, ton executable aura la même taille.

Voilà, j'pense que je t'enverrai d'ici peu le code source sans l'utilisation de malloc (ce sera à toi de faire une autre version avec !).
Salut !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
manu_ Messages postés 7 Date d'inscription mercredi 8 juin 2005 Statut Membre Dernière intervention 11 juin 2005
10 juin 2005 à 17:05
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>

//prototype de la fonction remplir
void remplir(int *tab1) ;

//prototype de la fonction vider. Valeur de retour : le nombre d'éléments effectivement copiés dans tab2
int vider(int *tab1, int *tab2) ;

//prototype de la fonction aff
void aff(int *tab,int NbElemAAfficher) ;

int main()
{
int buffer1[50] ; //vecteur de départ
int buffer2[50] ; //vecteur résultat
int NbElemB2 ; // Le nombre d'éléments de buffer2

char choix ;

NbElemB2=0 ; // Pour éviter d'afficher le buffer2 quand il n'est pas rempli


do
{
//clrscr() ;
printf("\n\n\tMENU\n\n") ;
printf("1.Remplir le buffer\n") ;
printf("2.Tampon resultat\n") ;
printf("3.Afficher le tampon\n") ;
printf("4.Quitter\n\n") ;

printf("\n\n\nFaites un choix: ");
choix=getch();
printf("%c",choix);

switch (choix)
{
//Remplir le tampon
case'1':
printf("\nRemplissage du tampon...");
remplir(buffer1) ;
printf("OK !\n") ;
printf("\n\n\n\tAppuyer sur une touche pour continuer...");
getchar();
break;
//Tampon résultat
case'2':
printf("Vidage du tampon 1 dans le tampon2...") ;
NbElemB2=vider(buffer1,buffer2) ;
printf("\n\n\nLe tampion resultat est rempli\n\n\n");
printf("\n\n\n\tAppuyer sur une touche pour continuer...");
getchar();
break;
//afficher le tampon
case'3':
printf("\n\n\nVoici le tampon resultat:\n\n\n");
aff(buffer2,NbElemB2);
printf("\n\n\n\tAppuyer sur une touche pour continuer...");
getchar();
break;
//quitter
case'4':
break;
}
}
while(choix!='4') ;

return 0;
}

//fonction remplir
void remplir(int *tab1)
{
int i ;
srand(time(NULL));

for(i=0;i<50;i++) //on remplit le buffer
{
tab1[i]=rand()%100;
}
}

//fonction vider
int vider(int *tab1, int *tab2)
{
int i ;
int j ;

j=0 ;

for(i=0;i<50;i++)
{
if (tab1[i]<=91 && tab1[i]>=65 || tab1[i]==32)
{ //on trie le buffer
tab2[j]=tab1[i];
j++;
}
}
return j ;
}


void aff(int *tab,int NbElemAAfficher)
{
int i ;
for(i=0;i<NbElemAAfficher;i++) //on affiche le buffer final
{
printf("%c ",tab[i]);
}
}


Voilà, y'a peut-être un peu trop de \n, mais sinon, cà marche nickel !
0
Salut,
je te remercie pour le code et pour tout le reste. Pour ce qui est de la précision c'est exactement ce que je voulais savoir, je ferais donc une autre version avec le fameux malloc (peut-être pas tout de suite parce que j'ai encore des exams mais je le ferais)...

Encore merci et comme j'ai compris je pense qu'il n'y aura pas de prochaine fois... j'espère!!!

Salut.
0