Petit problème de structure / chaine de caractère

Petit problème de structure / chaine de caractère - C - Programmation

Marsh Posté le 30-06-2009 à 15:31:48    

Bonjour,
 
Je suis un débutant en C, et je bloque sur quelque chose de relativement simple.
 
En fait, je voudrais entrer moi même le contenu de la variable char, directement dans le code, et non en passant par un scanf.
Avec un scanf, je peux entrer le contenu de ma variable jeune.nom, il n'y a pas de problème. Mais lorsque je rentre moi même le contenu dans le code, ça ne fonctionne pas.
 
Ne me demandez pas l'utilité de le faire, je n'en sais rien, je voulais juste faire un test pour voir si j'avais bien compris le fonctionnement, et visiblement, j'ai raté qqc, puisque j'obtiens une erreur "incompatible types in assignements" à la compilation. Si je rentre jeune.nom[100] = "Bob", alors c'est maintenant un étrange  "Son nom est AAAAÞ■" qui apparait dans la console.
 
Que faire? Voici le code.
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct joueur joueur;
  4. struct joueur
  5. {
  6.     int age;
  7.     char nom[100];
  8. };
  9. int main ()
  10. {
  11.     joueur jeune;
  12.     jeune.age = 20;
  13.     jeune.nom = "Bob";
  14.     printf("\nCe joueur a %d ans.\n\n", jeune.age);
  15.     printf("Son nom est %s.", jeune.nom);
  16.     return 0;
  17. }


 
Merci d'avance

Reply

Marsh Posté le 30-06-2009 à 15:31:48   

Reply

Marsh Posté le 30-06-2009 à 15:43:50    

regarde du côté de strcpy
 
sinon, une chaine litérale donne un const char [] et tu dois savoir qu'on ne peut pas faire d'aéffectation directement entre deux tableaux


---------------
last.fm
Reply

Marsh Posté le 30-06-2009 à 16:06:23    

strcpy sert à copier deux chaines, mais là ce n'est pas le cas ^^ j'aimerai juste que l'on m'explique clairement pourquoi je peux entrer une chaine de caractères dans jeune.nom en faisant  
 

Code :
  1. scanf("%s", jeune.nom);


 
mais qu'il est impossible de le faire en faisant simplement

Code :
  1. jeune.nom = "blabla";


?
 
Et, bien entendu, s'il y a un moyen de le faire, je suis preneur ^^
 
merci

Reply

Marsh Posté le 30-06-2009 à 16:35:43    

euuuuh ...
 
 
regarde du côté de strcpy  
 
sinon, une chaine litérale donne un const char [] et tu dois savoir qu'on ne peut pas faire d'affectation directement entre deux tableaux
 
Edit : pour être sympa :
En quoi ton affectation diffère d'une copie ? Qu'est-ce que tu veux faire ?
En quoi faire un strcpy est trop compliqué ? Tu parles de quelque chose de simple, un appel de fonction ne te suffit pas ?


Message édité par theshockwave le 30-06-2009 à 16:45:09

---------------
last.fm
Reply

Marsh Posté le 30-06-2009 à 16:50:09    

toyi91 a écrit :

strcpy sert à copier deux chaines, mais là ce n'est pas le cas ^^ j'aimerai juste que l'on m'explique clairement pourquoi je peux entrer une chaine de caractères dans jeune.nom en faisant  
 

Code :
  1. scanf("%s", jeune.nom);


 
mais qu'il est impossible de le faire en faisant simplement

Code :
  1. jeune.nom = "blabla";


?
 
Et, bien entendu, s'il y a un moyen de le faire, je suis preneur ^^
 
merci

jeune.nom est un tableau, autrement dit c'est une variable qui contient l'adresse de l'emplacement du 1er caractère de la chaine de caractère qu'il représente. Si tu lis la valeur de jeune.nom tu trouvera donc un nombre qui est l'adresse en question. Tu comprends donc que jeune.nom = "blabla" ne veut rien dire.
 
Tu es obligé d'utiliser strcopy ou strncpy pour copier les caractères de "blabla" dans l'emplacement indiqué par l'adresse contenue dans jeune.nom
 
Ne te laisse pas tromper par le cas unique où tu peux écrire jeune.nom = "blabla", c'est à dire lors de la déclaration de jeune.nom.
 

Reply

Marsh Posté le 30-06-2009 à 16:55:00    

ngkreator a écrit :

jeune.nom est un tableau, autrement dit c'est une variable qui contient l'adresse de l'emplacement du 1er caractère de la chaine de caractère qu'il représente. Si tu lis la valeur de jeune.nom tu trouvera donc un nombre qui est l'adresse en question. Tu comprends donc que jeune.nom = "blabla" ne veut rien dire.


 
Précisément pasjeune.nom est un ensemble de 100 caractères contigus placés dans l'instance de Joueur, et c'est précisément pour ca qu'on ne peut pas faire pointer ce tableau sur le litéral à droite de l'affectation.


Message édité par theshockwave le 30-06-2009 à 16:55:16

---------------
last.fm
Reply

Marsh Posté le 30-06-2009 à 18:01:19    

Je vais ignorer ton message.

Reply

Marsh Posté le 30-06-2009 à 18:43:18    

Ok ok :) merci pour l'explication :) je vais essayer tt ca ^^ bonne journée

Reply

Marsh Posté le 30-06-2009 à 19:13:03    

ngkreator a écrit :

Je vais ignorer ton message.


 
C'est ton droit le plus absolu.


---------------
last.fm
Reply

Marsh Posté le 30-06-2009 à 19:15:23    

Tout va bien alors.

Reply

Marsh Posté le 30-06-2009 à 19:15:23   

Reply

Marsh Posté le 30-06-2009 à 22:25:44    

+1 avec ngkreator.
 
Toute affection de tableau via [] comme dans char nom[] est la même chose que de faire char* nom, ce qui montre bien qu'il affecte à la variable nom un pointeur (vers la case-mémoire du premier element du tableau)
 
Donc jeune.nom = "Bob" n'a aucun sens (il attend une adresse mémoire, tu lui donnes un string)
 
Le mieux, strcpy, ou si tu veux quelquechose qui ressemble plus à scanf : http://www.cplusplus.com/reference [...] io/sscanf/

Reply

Marsh Posté le 01-07-2009 à 02:33:15    

boblenain200 a écrit :

+1 avec ngkreator.
 
Toute affection de tableau via [] comme dans char nom[] est la même chose que de faire char* nom, ce qui montre bien qu'il affecte à la variable nom un pointeur (vers la case-mémoire du premier element du tableau)
 
Donc jeune.nom = "Bob" n'a aucun sens (il attend une adresse mémoire, tu lui donnes un string)
 
Le mieux, strcpy, ou si tu veux quelquechose qui ressemble plus à scanf : http://www.cplusplus.com/reference [...] io/sscanf/


 
Mais arrêtez avec ca ! Il n'attend pas une adresse mémoire ! Un tableau n'est en aucun cas une l-value. On ne peut rien lui affecter, addresse mémoire ou non. Ce n'est PAS un pointeur. Un tableau, c'est avant tout un ensemble de données contigües. Si on veut l'adresse du premier élément, on fait &tab[0]. Le comportement lors du passage en paramètre à une fonction n'a rien à voir avec le comportement qu'on obtient en déclarant un tableau sur la pile ou simplement au sein d'un structure.
 
Qui plus est, dans son cas, sscanf n'est pas ce qu'il attend. A la limite, je comprendrais qu'on lui propose de passer son char[100] dans sa structure en const char*, mais ici, sscanf est inutile.

Message cité 1 fois
Message édité par theshockwave le 01-07-2009 à 02:37:19

---------------
last.fm
Reply

Marsh Posté le 01-07-2009 à 03:53:11    

Je vais ignorer ton message, mais pas la norme qui dit...

Reply

Marsh Posté le 01-07-2009 à 11:55:01    

ngkreator a écrit :

Je vais ignorer ton message, mais pas la norme qui dit...


 
chapitre 5.3 du K&R, trouve-moi un endroit où il est dit qu'un tableau est un pointeur. Déclarer un tableau revient à déclarer un groupe d'éléments. La facilité syntaxique que tu as en utilisant le nom de ton tableau comme si c'était un pointeur ne fait pas du tableau un pointeur.
 
Pour confirmer ce que je te dis, je t'invite à prendre l'exemple de toyi91 plus haut :

Code :
  1. typedef struct joueur
  2. {
  3.     int age;
  4.     char nom[100];
  5. } joueur;


 
Je t'invite à regarder ce que te donne un sizeof sur cette structure et à comparer avec le sizeof d'une structure définie comme ca :
 

Code :
  1. typedef struct joueur
  2. {
  3.     int age;
  4.     char* nom;
  5. } joueur;


 
Tu verras, ca n'a rien à voir, et ce n'est pas pour rien.
 
De même, quand tu déclares un tableau sur la pile, tu n'alloues aucun espace pour un pointeur vers l'adresse.
Après, il en est autrement pour les arguments de fonction, mais là, ce n'est pas le sujet.


---------------
last.fm
Reply

Marsh Posté le 01-07-2009 à 14:00:53    

theshockwave a écrit :

Un tableau n'est en aucun cas une l-value.

 

Je suis fondamentalement d'accord avec ta position, excepte sur ce point precis.

 

Un objet de type tableau est -- comme un objet d'un type incomplet ou un objet const -- une l-value non modiable.  De tels objets se convertissent dans la plupart des contextes (les exceptions etant les operandes de sizeof, &, ++,  --, . et les operateurs d'assignements, certains de ces operateurs demandent des l-values modifiables comme operande et donc n'acceptent pas les tableaux parce qu'ils ne le sont pas) en un pointeur vers leur premier element.  Le resultat de cette conversion n'est lui pas une l-value.  Il n'est pas possible d'avoir une r-value de type tableau.


Message édité par Un Programmeur le 01-07-2009 à 14:03:13

---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 01-07-2009 à 14:43:27    

mmmh, il me semblait que pour être une l-value, il fallait avant tout pouvoir être à gauche d'une opération d'affectation (ce qui n'est donc pas directement le cas pour un tableau) et être adressables (ce qui n'est pas non plus le cas d'un tableau non plus). Autant la nuance l-value non-modifiable me parait évidente pour les const, autant pour les tableaux, ca me laisse perplexe. Tu as un peu de lecture à conseiller à ce sujet ?


---------------
last.fm
Reply

Marsh Posté le 01-07-2009 à 14:56:59    

C99, 6.3.2.1/1

Citation :

A modifiable lvalue is an lvalue that does not have array
type, does not have an incomplete type, does not have a const-qualified
type, and if it is a structure or union, does not have any member
(including, recursively, any member or element of all contained aggregates
or unions) with a const-qualified type.

 

Il y a une note sur une autre partie de cet alinea:

 
Citation :

The name "lvalue" comes originally from the assignment expression E1
= E2, in which the left operand E1 is required to be a (modifiable)
lvalue. It is perhaps better considered as representing an object "locator
value". What is sometimes called "rvalue" is in this International
Standard described as the "value of an expression".

 

An obvious example of an lvalue is an identifier of an object. As a further
example, if E is a unary expression that is a pointer to an object, *E is
an lvalue that designates the object to which E points.

 

C90 est fondamentalement identique meme si la formulation n'est pas la meme mot pour mot.


Message édité par Un Programmeur le 01-07-2009 à 14:57:29

---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 01-07-2009 à 19:46:25    

ngkreator a écrit :

Je vais ignorer ton message.


Tu devrais pas pourtant :??: (ha ok posté trop vite :D)


Message édité par bjone le 01-07-2009 à 19:48:01
Reply

Marsh Posté le 10-07-2009 à 23:21:56    

ngkreator a écrit :

jeune.nom est un tableau, autrement dit c'est une variable qui contient l'adresse de l'emplacement du 1er caractère de la chaine de caractère qu'il représente.


Euh, non. Un tableau de char ne contient aucune adresse. Ce n'est pas un pointeur... Simplement, vu du compilateur, son nom a pour valeur l'adresse de son premier élément, c'est tout... Cette valeur n'est pas modifiable (non-modifiable L-value).

 
Citation :

Si tu lis la valeur de jeune.nom tu trouvera donc un nombre qui est l'adresse en question.


Là, on est d'accord.

 
Citation :

Tu es obligé d'utiliser strcopy


Un peu plus de rigueur please... strcpy() ...

  


Message édité par Emmanuel Delahaye le 10-07-2009 à 23:24:41

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed