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 :

Pourquoi ce code ne m'affiche pas la bonne valeur ?


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Pourquoi ce code ne m'affiche pas la bonne valeur ?
    Pourquoi ce petit bout de code ne m'affiche pas la valeur attendue ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char * tab = new unsigned char['h','e','l','l','o','\0'];
    cout << *tab << endl;   //il m'affiche 'î' au lieu de 'h', pareil pour *(tab+1) il m'affiche 'à' au lieu de 'e'
    Comment je dois faire pour afficher les valeurs correctes de mon taleau de char ?
    Merci

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 51
    Points : 32
    Points
    32
    Par défaut
    Ne devrais-tu pas faire une boucle pour afficher chaque valeur de ton tableau ?

  3. #3
    Membre averti

    Inscrit en
    Juillet 2008
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 186
    Points : 350
    Points
    350
    Par défaut
    tab est un poiteur sur la chaîne de caractères. C'est lui qu'ils faut injecter dans le flux. Pas besoin de le déréférencer.


  4. #4
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut
    Salut,
    Essaye plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // Ce code suggère une compilation ANSI
    char *tab = new char[10];
    sprintf(tab, "hello");
    std::cout << tab << std::endl;
    Je ne crois pas que tu puisses utiliser des chaînes de caractères avec des unsigned char*, je crois que tu es obligé de les signer.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Mr. X Voir le message
    Pourquoi ce petit bout de code ne m'affiche pas la valeur attendue ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char * tab = new unsigned char['h','e','l','l','o','\0'];
    Ca ne marche pas comme ça! Entre les crochets [] tu dois mettre la taille de ton tableau. Tu ne peux pas mettre des valeurs d'initialisation.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       unsigned char tab[]="hello";
       std::cout<<tab<<std::endl;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
       unsigned char * tab = new unsigned char[6];
       tab[0]='h';
       tab[1]='e';
       tab[2]='l';
       tab[3]='l';
       tab[4]='o';
       tab[5]='\0';
       std::cout << tab << std::endl;
    Citation Envoyé par Mr. X Voir le message
    cout << *tab << endl; //il m'affiche 'î' au lieu de 'h', pareil pour *(tab+1) il m'affiche 'à' au lieu de 'e'
    Normal, tu n'avais alloué qu'un buffer de taille 0. Et encore, tu as de la chance, car si ta zone mémoire n'avait pas contenu un 0, tu aurais pu aller jusqu'à une zone interdite et là !
    Citation Envoyé par Mr. X Voir le message
    Comment je dois faire pour afficher les valeurs correctes de mon taleau de char ?
    Merci
    Réviser les notions de tableau et de new[].

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Spout Voir le message
    Je ne crois pas que tu puisses utiliser des chaînes de caractères avec des unsigned char*, je crois que tu es obligé de les signer.
    Sous visual et sous gcc/windows, std::cout<<unsigned char* fonctionne et ça ne me choque pas sinon cela voudrait dire une conversion implicite vers du short/int/long.

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    En c++ il est préfèrable d'utiliser les std::string

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    En c++ il est préfèrable d'utiliser les std::string
    Sur le principe, tout à fait d'accord. std::string est faite pour ça. Mais dans son exemple, le problème ne venait pas de là.

  9. #9
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Mais dans son exemple, le problème ne venait pas de là.
    oui oui mais vous lui avez déjà expliqué.
    C'est juste une précision car faire des char * c'est faire du C.


    D'ailleurs, à votre avis que fait cette ligne? ou pourquoi les , compile?
    (j'adore ce bug , c'est le gros bug de mon premier projet que j'ai dû corrigé )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char * tab = new unsigned char['h','e','l','l','o','\0'];

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    oui oui mais vous lui avez déjà expliqué.
    Oublie le vous.

    Citation Envoyé par Mongaulois Voir le message
    D'ailleurs, à votre avis que fait cette ligne? ou pourquoi les , compile?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char * tab = new unsigned char['h','e','l','l','o','\0'];
    Super bonne question. A la lecture, j'avais pensé qu'il faisait: évalutation de 'h' puis évaluation de 'e', etc... puis évaluation de '\0' , empilement de cette dernière évaluation et appel de new. Pour moi ',' agit comme opérateur binaire (c'est pour ça que ça compile): d'abord l'expression de gauche est évaluée, puis l'expression de droite est évaluée, et la valeur retour est l'expression de droite (http://msdn.microsoft.com/en-us/library/t29e07xd.aspx). Donc, je me serais attendu à ce qu'il fasse un new ['0'=48]. Or, Visual me génère un new[0], mais là je suis pas capable d'expliquer...
    Voilà le code assembleur généré jusqu'à l'appel du new:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    xor         ecx,ecx 
    mov         eax,1 
    xor         edx,edx 
    mul         eax,edx 
    seto        cl   
    neg         ecx  
    or          ecx,eax 
    push        ecx  
    call        operator new[]

  11. #11
    screetch
    Invité(e)
    Par défaut
    le dernier char est '\0' pas '0', donc la valeur ascii 0, donc 0

  12. #12
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Normal, tu n'avais alloué qu'un buffer de taille 0. Et encore, tu as de la chance, car si ta zone mémoire n'avait pas contenu un 0, tu aurais pu aller jusqu'à une zone interdite et là !
    un bon vieux crash est bien meilleur pour montrer que ca ne marche pas qu'un comportement qui "marche presque", et quand ca "marche presque" j'appelle jamais ca de la chance, plutot de la malchance. dans un monde parfait, des que tu ferais une erreur, tu meurs
    (a ne pas appliquer en politique)

  13. #13
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    C'est bien cela
    la virgule sert de Séquenceur dans les opération.
    donc on fait bien un new unsigned char['\0']; => new unsigned char[0];

    Bon la c'est moins drôle.
    Mais je l'ai eu dans un simulateur qu'il fallait corriger où un nombre était écrit avec une virgule et non un point
    http://www.developpez.net/forums/d71...float-virgule/

    J'adore ce bug. Tellement subtile qu'il passe inaperçu.

    [edit]
    par contre je ne sait plus si résultat de 'h','e','l','l','o','\0' est définie.L'ordre est respecté(il me semble) mais que le retour utilisé non...

  14. #14
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Sous visual et sous gcc/windows, std::cout<<unsigned char* fonctionne et ça ne me choque pas sinon cela voudrait dire une conversion implicite vers du short/int/long.
    OK, mais je parlais de toutes les fonctions CRT pour les chaînes de caractères (sprintf, strlen, ...)

  15. #15
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses !

  16. #16
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Je dois aussi remplir mon tableau de unsigned char à partir d'un unsigned entré en paramètre mais je n'arrive pas à convertir un unsigned en unsigned char

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    fonction(unsigned n) {
        unsigned i=0, chiffre;
        taille = SMB::getNbDigits(n); //cette fonction donne bien le nombre de chiffres du nombre passé en paramètre
        tab = new unsigned char[taille];
        while(n > 0) {
            chiffre = n%10;
            n = n/10;
            tab[i] = (unsigned char)chiffre; //c'est ici qu'il faut que je convertisse chiffre en char mais apparement ma méthode n'est pas bonne alors comment faire ???
            i++;
        }
    }

  17. #17
    Membre averti Avatar de Vespasien
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    383
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 383
    Points : 434
    Points
    434
    Par défaut
    le type me semble incomplet: char | int | ...

  18. #18
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    signed, unsigned, long et short, impliquent par défaut "int".

    Donc unsigned == unsigned int, signed long == signed long int,...

  19. #19
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Mr. X Voir le message
    Je dois aussi remplir mon tableau de unsigned char à partir d'un unsigned entré en paramètre mais je n'arrive pas à convertir un unsigned en unsigned char
    Tu veux dire 0 en '0', etc..., j'imagine?

    Citation Envoyé par Mr. X Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    fonction(unsigned n) {
        unsigned i=0, chiffre;
        taille = SMB::getNbDigits(n); //cette fonction donne bien le nombre de chiffres du nombre passé en paramètre
        tab = new unsigned char[taille];
        while(n > 0) {
            chiffre = n%10;
            n = n/10;
            tab[i] = '0' +(unsigned char)chiffre; //c'est ici qu'il faut que je convertisse chiffre en char mais apparement ma méthode n'est pas bonne alors comment faire ???
            i++;
        }
    }

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Pour en revenir à la source du problème
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    unsigned char * tab = new unsigned char['h','e','l','l','o','\0'];
    Visual ne dit rien sur cette ligne, mais gcc met la puce à l'oreille. Car il génère quelques warning du type:
    Citation Envoyé par gcc
    warning: left-hand operand of comma has no effect
    Le code ASM généré par gcc est on ne peut plus simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    movl   $0x0,(%esp,1)
    call   0x402270 <operator new[](unsigned)>
    OK, c'est ce qu'on en attend en décortiquant l'opérateur ',' (en en ne se trompant pas entre '\0' et '0' )
    Par contre, visual génère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    xor         ecx,ecx 
    mov         eax,1 
    xor         edx,edx 
    mul         eax,edx 
    seto        cl   
    neg         ecx  
    or          ecx,eax 
    push        ecx  
    call        operator new[]
    Et là, j'avoue que je suis perdu. Qu'est ce que cela signifie, et donc comment Visual a-t-il compris le code?
    Je comprend: on met le registre ecx à 0, on met 1 dans eax, on met edx à 0, on multiplie eax par edx, donc on se retrouve avec eax à 0! Met dans cl l'overflow flag (0), complément à 2 de ecx (donc, 0), or ecx(0) avec eax(0), donc 0, puis push de 0 et appel de new. Je ne vois pas du tout le rapport avec l'instruction de départ: 'h','e','l','l','o','\0'. Si quelqu'un peut m'expliquer, ce serait avec plaisir.

Discussions similaires

  1. Requete qui n'affiche pas les bonnes valeurs
    Par snips67 dans le forum Langage SQL
    Réponses: 11
    Dernier message: 29/01/2010, 10h54
  2. Pourquoi ce programme ne m'affiche pas le bonjour
    Par phenix1988 dans le forum C++
    Réponses: 6
    Dernier message: 29/01/2009, 17h15
  3. pourquoi mes coordonnées ne s'affichent pas à l'ecran?
    Par christianf dans le forum AWT/Swing
    Réponses: 10
    Dernier message: 21/09/2007, 10h45
  4. [Outils][Crystal Report] Pourquoi mes icones ne s'affichent pas ?
    Par tonynho dans le forum SAP Crystal Reports
    Réponses: 6
    Dernier message: 12/05/2006, 15h29

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