IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

char* et compagnie


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Webmaster
    Inscrit en
    Février 2013
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 41
    Points : 18
    Points
    18
    Par défaut char* et compagnie
    Bonjour,

    Je code en C depuis 1 an maintenant et je crée un jeu en ce moment. Le problème, c'est que j'ai beaucoup de mal à gérer tout ce qui est char*,char**,…
    Tout ce qui concerne les caractères me pose énormément de problèmes.
    Souvent, les char* que je récupère après traitement ont des caractères aléatoires en plus, les lignes d'un char** sont mélangées…
    Bref,
    Est-ce que quelqu'un sait où je peux trouver un bon tutoriel vraiment centré sur ce genre de chose ? (C'est-à-dire centré sur la gestion de char).

    Merci d'avance.

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Bonjour,

    En fait, la question, c'est surtout de lire la documentation des fonctions de manipulations des chaines.
    Tu trouveras ton bonheur sur la section C de cppreference.com

    Ces fonctions ont de nombreuses subtilités, notamment parce que certaines travaillent sur des chaines (une séquence de char, terminée par un \0), et d'autres sur un bloc de chars (une séquence de char, dont on donne la taille).

    Le gros problème étant qu'il n'y a qu'un seul type pour les deux: (const) char*.

    Bref, il faut réellement apprendre ou vérifier les détails de ces fonctions.
    D'ailleurs, c'est la même chose dans le reste de la vie: pour utiliser quelque chose avec à la fois sûreté et sécurité, il faut vérifier comment s'en servir.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Je code en C depuis 1 an maintenant et je crée un jeu en ce moment. Le problème, c'est que j'ai beaucoup de mal à gérer tout ce qui est char*,char**,…
    Tout ce qui concerne les caractères me pose énormément de problèmes.
    Souvent, les char* que je récupère après traitement ont des caractères aléatoires en plus, les lignes d'un char** sont mélangées…
    C'est typique d'une insuffisante maîtrise des pointeurs, ça manque je pense, de pratiques, il faut t'entraîner et bien comprendre ce mécanisme souvent un frein dans l'apprentissage de ce langage. Si tu persistes ça viendra... Mais c'est plutôt un bon tutoriel sur les pointeurs dont tu as besoin, sur ce forum il y en a des très bien, je te laisse les chercher par tes soins.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sunny62 Voir le message
    Souvent, les char* que je récupère après traitement ont des caractères aléatoires en plus
    Bonjour

    Je pense que tu tentes d'afficher via printf("%s") un tableau de caractères ne contenant pas de '\0'.

    Ce qu'il faut bien comprendre, c'est que le type "chaine" n'existe pas en C. Les codeurs ont alors défini la convention qu'une chaine serait un tableau de caractères contenant impérativement un caractère '\0' (code ascii 0, à ne pas confondre avec le caractère '0' de code ascii 48).

    Ainsi char toto[100]={'h', 'e', 'l', 'l' 'o'} et tu as un simple tableau de 100 caractères contenant 5 caractères définis (et 95 aléatoires) mais si tu écris toto[10]='\0' et toto devient alors une chaine utilisable dans strcmp(), strlen() et autre printf().

    Ces fonctions (qui, elles, ne connaissent que le point de départ et qu'elles stockent dans un "char*") travaillent de la façon suivante: boucler jusqu'à trouver un '\0'.

    Exemple de codage de print() spécifique pour une chaine
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void print_str(char *chaine)
    {
        while (*chaine != '\0') {
            fputc(*chaine, stdout);
            chaine++;
        }
    }

    Si maintenant on repart de char toto[100]={'h', 'e', 'l', 'l' 'o'} et qu'on tente un print_str(toto), cette fonction partira du 'h' et affichera jusqu'à trouver un '\0'. Sauf qu'il n'y en a pas (sauf peut-être dans les 95 aléatoires mais rien ne te le garantit). Donc jusqu'à ce que la fonction tombe sur ce '\0' elle affichera le contenu de toto et tu auras alors à l'écran les caractères aléatoires qu'elle contient (et le programme peut même ne plus s'arrêter s'il n'y a pas de '\0')...

    Donc si tu récupères un flot de caractères issu d'une fonction de création de chaine (strcpy, strdup, fgets) tu es sûr que ce que ton flot contiendra ce '\0' (puisque leur rôle est de "créer" une chaine, elles la "créent" de façon correcte) et t'auras pas de pb. Mais si tu récupères ce flot depuis autre chose plus général (read, fread, memcpy), alors tu es sûr que rien n'oblige ce flot à contenir ce '\0' et tu n'auras pas le droit de le traiter comme une chaine.
    Mais dans ce dernier cas, rien ne t'interdit ensuite de rajouter toi-même ce '\0' au bon endroit. Et cet endroit est facilement déductible car toutes les fonctions en question soit renvoient toujours le nb réel de caractère lu (read, fread), soit ont besoin de connaitre ce nb de caractères au préalable (memcpy) et donc si on les utilise c'est qu'on connait déjà ce nb de caractères.
    Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char toto[100]={'h', 'e', 'l', 'l' 'o'};
    char chaine[5 + 1];
    memcpy(chaine, toto, 5);
    chaine[5]='\0';   // On peut même permuter cette ligne avec la précédente sans soucis (hormis peut-être une difficulté à relire le code plus tard)
    print_str(chaine);

    PS: si tu décides de transformer un tableau en chaine, tu dois aussi penser à rajouter "1" à la taille de ton tableau car le C ne le fait pas pour toi.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 446
    Points : 43 088
    Points
    43 088
    Par défaut
    les fonctions en question soit renvoient toujours le nb réel de caractère lu (read, fread), soit ont besoin de connaitre ce nb de caractères au préalable (memcpy) et donc si on les utilise c'est qu'on connait déjà ce nb de caractères.
    Vu qu'il débute Attention, le nb connu au préalable n'est pas forcément le nombre traité/lu, il faut analyser le retour de la fonction. Exemple, si on demande à read de lire 25 caractères dans un fichier et que celui-ci en fait 20, on aura l'info par le retour de la fonction que 20 caractères ont été lu et non pas 25, et si -1 alors ça veut dire erreur.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Exemple, si on demande à read de lire 25 caractères dans un fichier et que celui-ci en fait 20, on aura l'info par le retour de la fonction que 20 caractères ont été lu et non pas 25
    C'est ce à quoi je pensais quand j'ai écrit "renvoient toujours le nb réel de caractères lu"

    Citation Envoyé par chrtophe Voir le message
    , et si -1 alors ça veut dire erreur.
    Ca c'est pour plus tard...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre à l'essai
    Homme Profil pro
    Webmaster
    Inscrit en
    Février 2013
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 41
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Je pense que tu tentes d'afficher via printf("%s") un tableau de caractères ne contenant pas de '\0'.
    [...]
    Oui je sais ce genre de chose, d'ailleurs lorsque je copie un texte je le fais de cette façon :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void unefonction(char* text){
    char copitext[strlen(text)+1];
    strcpy(copitext,text);
    }

    Et donc je ne comprend pas pq des caractères s'ajoute alors... J'essaye même parfois de garden en mémoire la taille de text et de rajouter à la fin du traitement : copitext[strlen(text)+1]='\0'

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sunny62 Voir le message
    Oui je sais ce genre de chose, ...

    Et donc je ne comprend pas pq des caractères s'ajoute alors... J'essaye même parfois de garden en mémoire la taille de text et de rajouter à la fin du traitement : copitext[strlen(text)+1]='\0'
    Tu le sais peut-être... mais tu ne le prends pas en compte. strlen() est une fonction qui nécessite une chaine en entrée ; car elle aussi se sert du '\0' pour calculer la longueur. Si ce que tu lui passes n'a pas ce '\0', elle non plus ne peut pas fonctionner !!!
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre à l'essai
    Homme Profil pro
    Webmaster
    Inscrit en
    Février 2013
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 41
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Tu le sais peut-être... mais tu ne le prends pas en compte. strlen() est une fonction qui nécessite une chaine en entrée ; car elle aussi se sert du '\0' pour calculer la longueur. Si ce que tu lui passes n'a pas ce '\0', elle non plus ne peut pas fonctionner !!!
    Ce text est un char[50000] text = strcpy("une chaine récupérer de la bdd"); et cette chaine par contre s'affiche normalement.

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sunny62 Voir le message
    Ce text est un char[50000] text = strcpy("une chaine récupérer de la bdd"); et cette chaine par contre s'affiche normalement.
    Alors soit c'est char *text=strdup("une chaine récupérer de la bdd") et faudra penser un jour où l'autre à faire free(text) ; soit char text[5000]; strcpy(text, "une chaine récupérer de la bdd"). Eventuellement dans ce dernier cas tu as le droit d'écrire aussi char text[5000]; char *pt=strcpy(text, "une chaine récupérer de la bdd") mais c'est comme si tu écrivais char text[5000]; strcpy(text, "une chaine récupérer de la bdd"); char *pt=text.

    En revanche, déclarer un tableau de 5000 char et affecter à ce tableau (et non le pointeur) le char* renvoyé par strcpy(); là je reste sec sur le comportement final de ce genre d'action...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Je suis même surpris que ca compile, avec un seul pointeur en argument.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre à l'essai
    Homme Profil pro
    Webmaster
    Inscrit en
    Février 2013
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 41
    Points : 18
    Points
    18
    Par défaut
    Oui pardon, vous avez raison, c'est bien char text[50000];strcpy(text,"une chaine de caractere");je me suis trompé. Mais malgrés tout le problème persiste.
    strdup permet d'allouer la place nécéssaire uniquement ?

  13. #13
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sunny62 Voir le message
    Mais malgrés tout le problème persiste.
    A ce niveau là, il faut maintenant des sources pour qu'on y voit plus clair...
    Citation Envoyé par sunny62 Voir le message
    strdup permet d'allouer la place nécéssaire uniquement ?
    Oui. C'est un condensé de malloc(juste_ce_qu_il_faut)+strcpy()
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Réponses: 3
    Dernier message: 02/07/2003, 16h24
  2. Char(x) -> chaine concaténée d'espaces ?
    Par rgz dans le forum Débuter
    Réponses: 7
    Dernier message: 27/06/2003, 11h59
  3. [PostgreSql] Problème de cadreage de char !!!
    Par moipastoi dans le forum Requêtes
    Réponses: 3
    Dernier message: 08/05/2003, 18h01
  4. Réponses: 6
    Dernier message: 24/03/2003, 17h11
  5. Traitement d'un char* renvoyé par une DLL en C++
    Par LuluTchab dans le forum Langage
    Réponses: 4
    Dernier message: 22/03/2003, 21h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo