Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
957 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Probleme avec les '[ ]' et les '*' dans une structure

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Probleme avec les '[ ]' et les '*' dans une structure

n°1982769
lassault1
Posté le 10-04-2010 à 13:16:36  profilanswer
 

Bonjour et bon Samedi a tous ;)
 
Pourquoi ce code ne fonctionne pas lorsque je mets des '[]' dans les tableaux de ma structure ?
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct
  4. {
  5. char nom[100];
  6. char prenom[100];
  7. char adresse[1000];
  8. char sexe[50];
  9. long age;
  10. }Personne ;
  11. int main()
  12. {
  13.     long i;
  14.     Personne joueur[2];
  15.     joueur[0].nom = "Dupont";
  16.     joueur[0].prenom = "Paul";
  17.     joueur[0].age = 17;
  18.     joueur[0].adresse = "23 rue du parc a Paris";
  19.     joueur[0].sexe = "garcon";
  20.     joueur[1].nom = "Alibaba";
  21.     joueur[1].prenom = "Stephanie";
  22.     joueur[1].age = 19;
  23.     joueur[1].adresse = "54 avenue des fleurs a Paris";
  24.     joueur[1].sexe = "fille";
  25.     for (i = 0; i < 2; i++)
  26.         printf("Joueur 1 : Vous vous appellez %s %s, vous avez %ldans, vous habitez %s et vous etes un(e) %s, bon match!\n", joueur[i].nom, joueur[i].prenom, joueur[i].age, joueur[i].adresse, joueur[i].sexe);
  27. return 0;
  28. }


 
 
Et lorsque je mets des '*' dans les tableaux de ma structure ça fonction nikel ?
 

Code :
  1. typedef struct
  2. {
  3. char *nom;
  4. char *prenom;
  5. char *adresse;
  6. char *sexe;
  7. long age;
  8. }Personne ;

mood
Publicité
Posté le 10-04-2010 à 13:16:36  profilanswer
 

n°1982776
Joel F
Real men use unique_ptr
Posté le 10-04-2010 à 13:52:49  profilanswer
 

parce qu'un tableau n'ets pas un pointeur. Je te conseille de réviser tes bases avec une bonne lecture du K&

 

et à moins que tu alloues tes pointeurs et que tu utilsies strcpy pour y copeir tes chaines, non ca ne marche pas.
compiler != fonctionner


Message édité par Joel F le 10-04-2010 à 13:53:20
n°1982778
lassault1
Posté le 10-04-2010 à 14:03:24  profilanswer
 

Moi j'ai appris que les tableaux sont des pointeurs sur le 1er élément..

n°1982788
Elmoricq
Modérateur
Posté le 10-04-2010 à 14:54:12  profilanswer
 

Non.

 

Un pointeur, c'est juste une variable contenant une adresse et un type.
Par exemple :

int a = 42;
int * b = &a;


Ici, b est un pointeur sur l'entier a. C'est-à-dire que b sait où dans la mémoire commence le stockage de données de type "int" (données au pluriel : b ne sait pas du tout qu'il n'y a à cet endroit qu'un seul entier, c'est au programmeur de faire en sorte de ne pas sortir des bornes).

 

Un tableau quant à lui, c'est une séquence de données :

int tableau[] = { 1, 13, 42, 56 };


tableau ici est une séquence d'entiers (il y en a 4, mais ça le tableau ne le sait pas lui-même, c'est encore le taf du développeur de s'en souvenir).

 

Ensuite, il y a la mémoire allouée dynamiquement, dont l'adresse de début est effectivement stockée dans un pointeur :

int *pointeurVersUneZoneMemoire = malloc(42 * sizeof(int));


pointeurVersUneZoneMemoire est un pointeur vers l'adresse de début d'une zone mémoire de taille suffisante pour accueillir 42 entiers, zone mémoire dynamiquement créée lors de l'exécution du programme. Ce bout de mémoire n'existe pas du tout avant cette ligne de code, et il perdurera jusqu'à ce qu'un appel à free() vienne le libérer (une "fuite mémoire", ou "memory leak" en anglais, c'est donc de la mémoire qu'on alloue, mais qu'on ne libère jamais, et qui finit par faire grossir indéfiniment la taille du programme en mémoire durant son exécution).

 


Cette zone mémoire peut ensuite s'utiliser syntaxiquement comme un tableau. Mais seulement syntaxiquement.
Par contre, un tableau ne se comporte pas comme une zone de mémoire dynamique : tu n'alloues pas dynamiquement un tableau, tu ne le libères pas non plus. Et tu ne peux pas l'agrandir ou le déplacer.
Ton tableau est assujetti à la portée courante, et n'existe que dans la portée courante.
Une zone mémoire allouée dynamiquement peut être accédée à partir de n'importe où dans le programme, pas le tableau.

 

Vois donc un tableau comme une zone de mémoire fixe, contenant une séquence de données, de portée locale.

 

Et vois un pointeur comme un moyen d'accéder à un objet, et non l'objet lui-même.


Message édité par Elmoricq le 10-04-2010 à 14:58:30
n°1982795
Joel F
Real men use unique_ptr
Posté le 10-04-2010 à 15:24:49  profilanswer
 

lassault1 a écrit :

Moi j'ai appris que les tableaux sont des pointeurs sur le 1er élément..


change d'école

n°1982807
gilou
Modérateur
Modzilla
Posté le 10-04-2010 à 16:50:43  profilanswer
 

lassault1 a écrit :

Pourquoi ce code ne fonctionne pas lorsque je mets des '[]' dans les tableaux de ma structure ?

Parce qu'on ne peut initialiser un tableau par une chaine qu'au moment de sa déclaration.
Quand tu fais:
joueur[0].nom = "Dupont";
C'est trop tard, car le tableau joueur[0].nom a déjà été initialisé lors de la déclaration
Personne joueur[2];
Donc a ce stade la, pour copier des caractères dans un tableau, on utilise tout simplement strcpy, strncpy, etc.
Ce code ci fonctionne (et j'ai modifié un petit pb de ta ligne avec le printf).

 


Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. typedef struct
  5. {
  6. char nom[100];
  7. char prenom[100];
  8. char adresse[1000];
  9. char sexe[50];
  10. long age;
  11. }Personne ;
  12. int main()
  13. {
  14.     long i;
  15.     Personne joueur[2];
  16.     strcpy(joueur[0].nom, "Dupont" );
  17.     strcpy(joueur[0].prenom, "Paul" );
  18.     joueur[0].age = 17;
  19.     strcpy(joueur[0].adresse, "23 rue du parc a Paris" );
  20.     strcpy(joueur[0].sexe, "garcon" );
  21.     strcpy(joueur[1].nom, "Alibaba" );
  22.     strcpy(joueur[1].prenom, "Stephanie" );
  23.     joueur[1].age = 19;
  24.     strcpy(joueur[1].adresse, "54 avenue des fleurs a Paris" );
  25.     strcpy(joueur[1].sexe, "fille" );
  26.     for (i = 0; i < 2; i++)
  27.         printf("Joueur %i : Vous vous appellez %s %s, vous avez %ldans, vous habitez %s et vous etes un(e) %s, bon match!\n", i, joueur[i].nom, joueur[i].prenom, joueur[i].age, joueur[i].adresse, joueur[i].sexe);
  28. return 0;
  29. }
 

A+,


Message édité par gilou le 10-04-2010 à 16:53:17

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°1982815
lassault1
Posté le 10-04-2010 à 18:06:41  profilanswer
 

Merci a vous..mais il me reste quelques questions..
 
1/ si j'ai bien compris char nom[] est identique a char* nom et char *nom que dans les prototypes de fonction et non lors des déclarations.. ?
 
2/ Pour ma question initiale, dans ce code,  quand je réponds 'Dupont' a la question Quel est votre nom ? c'est comme si je fais utilisateur.nom = "Dupont" alors que nom est un tableau (char nom[100];)
 

Code :
  1. struct Personne
  2. {
  3.     char nom[100];
  4.     char prenom[100];
  5.     char adresse[1000];
  6.    
  7.     int age;
  8.     int garcon; // Booléen : 1 = garçon, 0 = fille
  9. };
  10. int main(int argc, char *argv[])
  11. {
  12.     Personne utilisateur;
  13.     printf("Quel est votre nom ? " );
  14.     scanf("%s", utilisateur.nom);
  15.     printf("Votre prenom ? " );
  16.     scanf("%s", utilisateur.prenom);
  17.     printf("Vous vous appelez %s %s", utilisateur.prenom, utilisateur.nom);
  18.     return 0;
  19. }


 
3/ Pourquoi ce code fonctionne pas ??
 

Code :
  1. char nom[100];
  2. nom = "Dupond" /* ne marche pas */;


 
Et celui oui sans utiliser de pointeur ni strcpy??
 

Code :
  1. char nom[100] = "Dupond" /* marche  */;


n°1982862
Joel F
Real men use unique_ptr
Posté le 10-04-2010 à 22:21:49  profilanswer
 

char nom[100] = "Dupond" definit une chaine constante.

n°1982865
gilou
Modérateur
Modzilla
Posté le 10-04-2010 à 23:53:51  profilanswer
 

lassault1 a écrit :

3/ Pourquoi ce code fonctionne pas ??
 

Code :
  1. char nom[100];
  2. nom = "Dupond" /* ne marche pas */;


 
Et celui oui sans utiliser de pointeur ni strcpy??
 

Code :
  1. char nom[100] = "Dupond" /* marche  */;



C'est a se demander si tu as lu ma réponse.
char nom[100] = "Dupond";
Tu initialise un tableau au moment de sa déclaration: Ca, c'est autorisé par le C, parce qu'au moment ou le compilateur construit le tableau, il sait ce que tu va mettre dedans: Le compilo construit un tableau de 100 cases, et met les caractères 'D', 'u', 'p', 'o', 'n', 'd', '\0' dans les premières cases du tableau qu'il est en train de construire. Bref, en C, char nom[100] = "Dupond"; a un sens spécial, c'est une abréviation pour char nom[100] = {'D', 'u', 'p', 'o', 'n', 'd', 0};
tandis que
char nom[100];
Tu déclares un tableau, sans l'initialiser. Le compilo construit un tableau de 100 cases, et ne met rien de spécial dans les cases du tableau qu'il est en train de construire (leur contenu est donc n'importe quoi).
nom = "Dupond";
Ca tu ne peux pas, parce que a ce stade, le tableau est déja construit. Si tu veux que cette chaine soit contenue par le tableau, ce n'est plus une initialisation que tu vas faire, mais une modification du contenu des cases du tableau. Et pour faire une modification du contenu des cases d'un tableau, il y a diverses méthodes, par exemple:
strcpy(nom, "Dupond" );
ou bien
nom[0] = 'D';  nom[1] = 'u'; nom[2] = 'p'; nom[3] = 'o'; nom[4] = 'n'; nom[5] = 'd'; nom[6] = '\0'; (avec cette dernière écriture, on voit bien qu'on modifie le contenu des cases d'un tableau déja existant)
etc.
Grosso modo, tu peux te dire que si nom = "Dupond"; est incorrect, c'est parce que nom étant un tableau, il peut parfois être vu comme pointant sur une adresse fixe, celle de son premier élément. Comme cette adresse est fixe, elle ne peut pas être remplacée par celle de la chaine "Dupond".
 
Notes que pour être complet, si tu fais char nom[] = "Dupond"; c'est équivalent a déclarer un tableau, avec juste la bonne taille pour contenir la chaine (donc équivalent à char nom[7] = "Dupond"; ici).
 
Quand tu fais char nom[100] = "Dupond"; tu peux ensuite modifier les éléments du tableau nom.
 
Par contre, si tu fais:
char *nom = "Dupond";
ou bien
char *nom;
nom = "Dupond";
tu es dans un autre cas de figure: tu ne peux pas modifier le contenu de nom, tant qu'il pointe sur cette chaine.
Le compilo, quand il rencontre cette déclaration avec une initialisation (ou une assignation), il crée dans une zone mémoire de la place pour stocker la chaine "Dupond", et il fait pointer nom dessus. Mais le compilo, si ailleurs dans le programme, il rencontre a nouveau pointeur sur la chaine "Dupond" (char *pseudo = "Dupond";), plutôt que faire un doublon, il va réutiliser cette zone mémoire. Mais alors, il est important pour le compilo que cette zone mémoire ne soit pas modifiable, sinon, si je pouvais modifier le 3e caractère de nom, ca modifierais aussi le 3e caractère des autres pointeur sur la chaine "Dupond", alors qu'ils n'ont rien a voir avec nom.
Donc en C, char *nom = "Dupond"; définit une chaine constante, non modifiable (sinon, le programme plantera a l'exécution, en râlant), et un pointeur dessus.
 
A+,


Message édité par gilou le 11-04-2010 à 01:14:51

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°1982912
lassault1
Posté le 11-04-2010 à 11:23:25  profilanswer
 

Merci gilou c'est très bien expliqué..
 
Cependant il reste 2 petite questions :
 

Code :
  1. Grosso modo, tu peux te dire que si nom = "Dupond"; est incorrect, c'est parce que nom étant un tableau, il peut parfois être vu comme pointant sur une adresse fixe, celle de son premier élément


 
Je pensé que "nom ici" était  l'adresse du 1er élément du tableau dans tout les cas et non un tableau ..
 

Code :
  1. si tu fais:
  2. char *nom = "Dupond";
  3. ou bien
  4. char *nom;
  5. nom = "Dupond";
  6. tu es dans un autre cas de figure: tu ne peux pas modifier le contenu de nom, tant qu'il pointe sur cette chaine.


 
J'ai pas vraiment compris pourquoi quand je fais :
char *nom;
nom = "Dupond";
alors ne ne peux pas modifier son contenu ?

mood
Publicité
Posté le 11-04-2010 à 11:23:25  profilanswer
 

n°1982933
gilou
Modérateur
Modzilla
Posté le 11-04-2010 à 13:26:08  profilanswer
 

Parce que quand il a vu "Dupond", le compilo, avec ses petites mains, il a créé une zone qui contient de manière consécutive 'D' 'u' 'p' 'o' 'n' 't' et il a fait pointer nom dessus (ie nom a pour valeur l'adresse de cette zone).
Mais si plus loin dans ton code le compilo trouve char * monautrepointeur; monautrepointeur = "Dupond"; le compilo, il se souvient qu'il a déja vu cela, et plutot que de recréer une zone qui contient de manière consécutive 'D' 'u' 'p' 'o' 'n' 't' et faire pointer monautrepointeur dessus, il réutilise la zone déja crée. [c'est une décision prise il y a longtemps, a la création du langage C, quand il y avait peu de mémoire pour les programmes, et qu'on essayait de l'économiser]
Donc maintenant nom et monautrepointeur pointent sur la même zone mémoire, qui contient  'D' 'u' 'p' 'o' 'n' 't'.
Mais maintenant, si nom modifie son contenu, ca va modifier aussi le contenu de monautrepointeur puisque c'est le même, alors qu'on veut peut être pas cela, puisque rien ne dit que les variables nom et monautrepointeur désignent la même chose. Peut être que nom désigne une variable de la fonction nom_client()  et monautrepointeur une variable de la fonction nom_livreur() et que par hasard, ils portent le même nom à un moment donné.
Donc pour éviter ces modifications qui peuvent avoir des effets indésirables, les créateurs du langage C ont décrété que quand le compilo a vu "Dupond", le compilo, avec ses petites mains, il a créé une zone qui contient de manière consécutive 'D' 'u' 'p' 'o' 'n' 't' dans une zone de mémoire qui est décrétée "non-modifiable" et que si plus loin, au cours de l'exécution du programme, on essaye de modifier la mémoire dans cette zone, le programme déclenche une erreur (et en général, plante).
C'est une méthode brutale et directe, on aurait pu faire plus subtil, mais ça aurait nettement compliqué l'écriture d'un compilateur a l'époque, et les techniques d'écriture de compilateurs en étaient a leurs débuts a l'époque.
A+,


Message édité par gilou le 11-04-2010 à 13:35:28

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°1983343
lassault1
Posté le 12-04-2010 à 20:21:38  profilanswer
 

Merci a vous.. c'est résolu...


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Probleme avec les '[ ]' et les '*' dans une structure

 

Sujets relatifs
Probleme chemin dirname()Problème avec mon site
Problème feuille de style CSS#'!*%@!?#!!** de saloperie de *!!#¡@* de PHP de m*@#*!
Problème MySQL CountStructure
Java : problème de radar sur robocodePostgresl, probleme de jointure
Problème lors du passage de PHP4 à PHP5[RESOLU][SQL/ACCESS] Problème jointure
Plus de sujets relatifs à : Probleme avec les '[ ]' et les '*' dans une structure


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR