Malloc

judy-brainy Messages postés 22 Statut Membre -  
judy-brainy Messages postés 22 Statut Membre -
Bonjuor tout le monde
j'ai un probleme au niveau de ce programme
en fait, apparemment c'est un probleme d'allocation, parceque lorsque j'utilise pas un appel de fonction (j'ecris toutes les instructions au niveau du proramme principal), tout marche tres bien; sinn, si je dois faire appel à une fonction, bien sur je dois utiliser un pointeur (passage par adresse), lorsqu'il s'agit de type simples (entiers, caracteres ...) de même, aucun souci... mais des qu'il s'agit d'un tableau dans une structure, et un passage par adresse ... c'est la pagaille!!! des que je change un champs, comme si il ya initialisation totale des autres champs!!
comment ecrire malloc? ou est ce que je dois la saisir??
j'ai besoin de faire une allocation statique de tableau (tableau statique)

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

typedef struct lst
{
int t[20]; //un tableau
int n; //nombre des elements de ce tableau
} LIST;

void ajout_fin(LIST *l, int val) //passage par adresse
{
int i;
l->n++; //incrémentation du nombre des elements
l->t[l->n-1]=val; //insertion de la valeur dans la derniere case
}

void main()
{
LIST *l;
int i;
int val;

printf("n=");
scanf("%d",&l->n);

//saisie du tableau

for(i=0;i<l->n;i++)
{
printf("donner l'element n°%d \n:",i);
scanf("%d",&l->t[i]);
}

//ajout d'un element a la fin

printf("donner l'element à ajouter a la fin: \n");
scanf("%d",&val);

ajout_fin(l, val);

printf("affichage du tableau: \n");
for(i=0;i<l->n;i++)
{
printf("t[%d]=%d \n",i,l->t[i]);
}

getch();
}

ce programme n'est qu'une partie d'un programme sur lequel je travaille depuis des semaines et je crois que ce detail qui bloque tout !! :s
j'ai tres besoin que ca marche!!

3 réponses

Pacorabanix Messages postés 4122 Date d'inscription   Statut Membre Dernière intervention   663
 
ok je crois que je comprends ton souci.

alors bien évidemment tu dois faire un malloc pour la structure elle-même. malloc(sizeof(LIST) ou un truc du genre.

[EDIT après commentaire ci-dessous] Elle contient une variable tableau. un tableau en C c'est presque comme un pointeur vers le premier élément.

tu devrais pouvoir faire ainsi : déclarer int t* pour ton tableau et ensuite :

//allocation pour la structure   
l = malloc(sizeof(LIST));   

if ( l != null ) {   
    /*on alloue le tableau */  
   /*tu peux demander le n ici, comme ça tu pourras allouer la taille que tu veux directement   ou alors simplement allouer 20 cases. */ 
   l.t = malloc(l.n*sizeof(int));  
   
   /*  reste du programme ... */  
   
}   
else printf("Erreur");


j'ai peut-être fait une ou deux fautes, je n'ai pas testé le code.
0
judy-brainy Messages postés 22 Statut Membre 1
 
ahh d'accord, voila un truc que je viens de connaitre, je peux pas donc insérer un tableau dans une structure ... pourtant ca m'indique aucune erreur ... donc je vai revoir mon conde et esperons que ca marche cette fois ci merci ;-)
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847
 
Salut Pacorabanix,

Ensuite, il faut bien que tu comprennes que la structures ne contient pas concrètement le tableau. Elle contient une variable tableau.
Non, la structure comprend bel et bien le tableau. Donc pas besoin, et il ne faut surtout pas allouer le tableau. Sinon le compilateur va râler.

Et c'est là toute l'importance de bien savoir qu'un tableau en C, c'est un pointeur vers le premier élément.
Non, un tableau ce n'est pas un pointeur. Le compilateur le transforme en pointeur seulement dans certains contextes (comme le passage en argument, dans des opérations, ...). Pour le reste, il s'agira d'un tableau en tant que tel.

Cdlt,
0
Pacorabanix Messages postés 4122 Date d'inscription   Statut Membre Dernière intervention   663
 
arf je me suis fourvoyé! merci fiddy d'être derrière moi...

bon, ceci dit le nom d'un tableau est [i]presque/i un pointeur vers le premier élément... donc en définissant la structure avec int * t ; au lieu de int t[20], ma solution devrait être un peu plus correcte....

alors il suffit donc de faire un malloc pour la structure dans ce cas ? je n'ai pas de compilateur sous la main pour tester.
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847
 
La règle est très simple : on n'alloue que les pointeurs.
Si tu as : struct Liste *l; tu dois allouer comme tu l'as si bien dit avec malloc(sizeof (struct Liste));
Et il faudra de plus allouer tous les pointeurs dans la structure. Si tu as un tableau : int t[20], l'allocation de la structure dans le heap fera en sorte d'allouer 20 bytes*sizeof(int) cases.
Par contre si tu as int *t, ta solution est effectivement correcte.
0
judy-brainy Messages postés 22 Statut Membre 1
 
l'allocation doit être faite dans le programme principal ou dans les fonctions? ... en fait ici je n'ai écrit qu'une seule fonction, mais yen a d'autres (ajout_element, supprime_element, creer_liste_vide ...)
donc j'imagine que l'allocation se fait au niveau de la fonction de creer_liste_vide ...
je pense aussi qu'à chaque fois j'ajoute un element, je dois lui allouer de la place aussi (donc il va y avoir allocation d'un element)

de même dans supprime_element, je devrai utiliser free()
0
tatou_38 Messages postés 1954 Date d'inscription   Statut Membre Dernière intervention   121
 
Il y a aussi un autre problème fatal :

void main()
{
LIST *l;
int i;
int val;

printf("n=");
scanf("%d",&l->n);

Tu as déclaré l comme étant un pointeur sur une structure de type LIST. Pourquoi pas.

Tu utilises ce pointeur l pour y ranger la valeur lue par scanf().

Problème sur quoi pointe l ??? Et bien sur rien car l n'est pas initialisé, autrement dit le scanf() va mettre la valeur saisie quelque part dans la mémoire, pourquoi pas à une adresse qui va tout faire planter, ou qui va corrompre des données.

TU NE PEUX PAS UTILISER DE POINTEURS NON INITIALISE !!!

il faut par exemple que tu ajoutes avant le scanf() :

l = malloc(sizeof(LIST));
if (!l) { gestion d'erreur }

Maintenant l pointe bien sur une zone mémoire correctement définie.

N'oublie pas de désallouer l une fois devenu inutile ( free(l) );

Je n'ai pas été plus loin dans ton code.

Un truc : Utilise la notation hongroise pour bâtir tes noms de variable :

sNombre ==> variable de type short
usNombre ==> variable de type unsigned short
lNombre ==> variable sur un long
etc ...

psNombre ==> pointeur sur un short
pusNombre ==> pointeur sur un unsigned short
ppusNombre ==> pointeur sur pointeur sur un unsigned short
etc ...

Ainsi tu auras une programmation beaucoup plus claire et tu ne pourras plus confondre des pointeurs et des variables !
0
judy-brainy Messages postés 22 Statut Membre 1
 
j'ai bien initialisé ma liste mais jai pas tout ecri ici, sinn ca va prendre de tres longues pages ... merci ;-)
0
Pacorabanix Messages postés 4122 Date d'inscription   Statut Membre Dernière intervention   663
 
scanf("%d",&l->n);

esaye plutot :

scanf("%d", &(l->n) );

et teste si la valeur de n est bien enregistrée
0
judy-brainy Messages postés 22 Statut Membre 1
 
merci tout le monde! c'est bon pour l'allocation ... quoi que le programme ne marche toujours pas, et là j'arrive pas a voir c'est où encor le probleme :s car l'operateur se ferme automatiquement en m'indiquant une erreur genre opertion illigale
bon voici le programme complet si jamais vous aurez le temps de tout le lire, mais avant voici son principe: il transforme une expression parenthésée en expression polonaise et ca grâce aux piles et aux files:

#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#define max 20

typedef struct pile //structure comportant le tableau et son nombre d'elements
{
char t[20];
int n;
} pile;

typedef struct File
{
char t[20];
int n;
} File;

pile creerpilevide()
{
pile *p;
p=(pile*)malloc(sizeof(pile));
p->n=0;
return *p;
}

File creerfilevide()
{
struct File *f;
f=(File*)malloc(sizeof(File));
f->n=0;
return *f;
}

int pilepleine(pile p)
{
return (p.n==max);
}

int pilevide(pile p)
{
return (p.n==0);
}

int filepleine(File f)
{
return (f.n==max);
}

int filevide(File f)
{
return (f.n==0);
}

//===

void empiler(pile *p, char val) // les elements s'ajoutent a la fin
{

if (pilepleine(*p))
{
printf("erreur la pile est pleine");
}
else
{

p->t[(p->n)-1]=val;
(p->n)++;

}
}

char obtenir_element_pile(pile *p) // on obtient le dernier element
{
return p->t[(p->n)-1];
}

void depiler(pile *p)
{

if (pilevide(*p))
{
printf("erreur la pile est vide");
}
else
{

(p->n)--;

}
}

void decG(File *f)
{
int i;
if ((f->n)>=2)
{
for(i=0;i>=(f->n)-2;i++)
// juska lavant derniere case(qui va etre remplacée par la derniere)

{
f->t[i]=f->t[i+1]; // la file d'attente va avancer
}
}
}

void enfiler(File *f, char val) // les elements s'ajoutent a la fin
{

if (filepleine(*f))
{
printf("erreur la file est pleine");
}
else
{

(f->n)++;
f->t[(f->n)-1]=val;

}
}

char obtenir_element_file(File *f) // on obtient le premier element
{
return f->t[0];

}
void defiler(File *f)
{

if (filevide(*f))
{
printf("erreur la file est vide");
}
else
{

decG(f);
// pour defiler la file, elle doit avancer, on fait un decalage gauche

(f->n)--;; // le nombre des elements va se reduire

}

}

// on affiche tous les elements de la file, du premier jusqu'au dernier

void affiche_file(File *f)
{
int i;
char element;

printf("voici l'ecriture polonaise: ");
for(i=0;i<(f->n);i++)
{
element=obtenir_element_file(f);
printf("%c",element);
defiler(f);
}
}

void main()
{
int i;
char *ch;

printf("donner l'operation: \n");

scanf("%s",ch);

char operateur;

struct pile *p;
struct File *f;

*p=creerpilevide();
*f=creerfilevide();

for(i=0;i<strlen(ch);i++)
{
if ((*(ch+i)>='0') && (*(ch+i)<='9')) // verifier si c'est un entier
{

enfiler(f,*(ch+i));

}

else
{
if (((*(ch+i)=='+') || (*(ch+i)=='-')) || ((*(ch+i)=='*') || (*(ch+i)=='/')))
// verif si c'est un operateur
{

empiler(p,*(ch+i));

}
else
{
if (*(ch+i)==')')
{

while (!pilevide(*p))
{
operateur=obtenir_element_pile(p);
depiler(p);

enfiler(f,operateur);

}
}
}
}
}

//affichage de la file
affiche_file(f);

getch();

}
0