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 :

Pb avec l'accentuation


Sujet :

C++

  1. #1
    Membre émérite Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    601
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 601
    Par défaut Pb avec l'accentuation
    Hello.
    Je souhaite afficher une chaîne de caractère finale dans laquelle j'ai ajouté un caractère après chaque caractère d'une chaîne de caractère initiale.
    Cela fonctionne parfaitement avec ce code pour des chaînes sans caractères accentués
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <iostream>
    #include <string>
    using namespace std;
     
    int main() {
    	string chaine_1 = "abc de";
     
    	cout << chaine_1 << endl;
     
    	for (char c1 : chaine_1) {
    		cout << c1;
    	}
    	cout << endl;
     
    	for (char c1 : chaine_1) {
    		cout << c1 << "_";
    	}
    	cout << endl;
     
    	return 0;
    }
    "abc de" avec "_" devient "a_b_c_ _d_e_".

    En revanche, si je tente "Test éé àè !", j’obtiens : "T_e_s_t_ _ _�_�_�_�_ _�_�_�_�_ _!_"
    Pourtant, les 2 premiers affichages fournissent bien les accents ....
    J'ai aussi essayé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	for (int c = 0; c < int(chaine_1.size()); c++) {
    		cout << chaine_1.at(c) << "_";
    	}
    avec le même résultat.
    Mon code source est bien en utf-8.
    Bref, je suis bloqué

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 771
    Par défaut
    Va te documenter sur les encodages Unicode : UTF-8/ UTF-16/ UTF-32

    La taille d'1 chaîne détermine le nombre de caractères. Mais comme 1 caractère peut varier entre 1 et 4 octets, alors sa "taille en octets" est différente

    "Test éé àè !" correspond à "54 65 73 74 20 C3 A9 C3 A9 20 C3 A0 C3 A8 20 21" (<- des espaces entre chaque octet)
    20 étant l'espace, tu voies que le caractères, en UTF-8, é c'est 0xC3 0xA9, à c'est 0xC3 0xA0 et è, 0xC3 0xA8.

    C'est d'ailleurs pour cela que les caractères indéfinis (les losanges) tu en as 8 pour 4 caractères.
    Ce sont toutes des valeurs supérieures à 0x7F, la limite de l'ASCII

  3. #3
    Membre émérite Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    601
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 601
    Par défaut
    C'est bien compliqué ...
    L'erreur arrive même avec un code encore plus simple d'inversion de chaine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	string chaine_1 = "Test  éé àè !";
    	string chaine_2 = string(chaine_1.rbegin(),chaine_1.rend());
    	cout << chaine_1 << endl;
    	cout << chaine_2 << endl;
    affiche
    Test éé àè !
    ! �à� �é� tseT
    Il existe peut-être une librairie qui s'occupe de ce problème d'accents

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 771
    Par défaut
    Citation Envoyé par ypcman Voir le message
    Il existe peut-être une librairie qui s'occupe de ce problème d'accents
    Oui et non

    Parce que, ayant 1 chaîne Unicode, il faut la lire pour extraire chaque caractère. Tu ne peux pas découper de façon constante/ régulière en prenant tous les chars, tous les 2 chars, ...
    Il faut vraiment lire ta chaîne.

    Et donc oui, 1 librairie peut t'aider. Comme tu peux le faire à la main.
    Lis le wikipédia, tu vas voir, il faut compter le nombre de 1 au début du premier octet

  5. #5
    Membre Expert Avatar de gabriel21
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2007
    Messages : 548
    Par défaut
    Petite question, mais qui a son importance, où affiches tu ton message et sur quel OS ?
    En effet si tu affiches dans une console que ce soit sous Linux comme sous Windows, rien ne te dis que cette console est en mode UTF8. Bon sous Linux, c'est le cas de la majorité des cas. Sous Windows, si la console Powershell est généralement en UTF8, de tête la console cmd est en ASCII par défaut. Cela est paramétrable pour Linux et Powershell, pour cmd, je ne sais pas, ne faisant plus de développement sous Windows depuis près de 15 ans.
    Si c'est une bibliothèque graphique, il faut voir dans la documentation de celle ci, le mode par défaut et comment le modifier.

    Le problème des losanges et points d'interrogation dans les noms de fichiers, je le rencontre régulièrement quand il y a des partages de fichiers qui sont en UTF8 mais que le système qui s'y connecte ne le comprends pas (vieux Linux, Unix, Aix et Windows).

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 771
    Par défaut
    Il me semble que Windows a changé, mais la ligne de commande affiche le code page OEM (ouais OEM)
    Wikipedia Windows code page en anglais *

    Il faut utiliser la commande chcp 65001 pour changer le code page avec celui UTF-8 (il y a la liste dans mon lien précédent *)

    Regarde le tableau sur la page Wikipedia en anglais pour mettre des codes Unicode.

    Tu peux également coder "Test \xC3\xA9\xC3\xA9 \xC3\xA0\xC3\xA8 !"

  7. #7
    Membre émérite Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    601
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 601
    Par défaut
    Fedora 34 et la console interne d'Eclipse IDE ...
    et comme je l'ai écrit, un simple cout affiche la chaîne avec tous ses accents. Manifestement, c'est bien le découpage de la chaîne en caractères qui pose problème

  8. #8
    Membre émérite Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    601
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 601
    Par défaut
    J'ai fait plus simple. Pouvez-vous tester ce code et me dire si les caractères acentués s'affichent correctement ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
    #include <string>
    using namespace std;
     
    int main() {
    	string chaine_1 = "Test  éé àè !";
     
    	for (char c1 : chaine_1) {
    		cout << c1;
    	}
    	cout << endl;
     
    	for (char c1 : chaine_1) {
    		cout << c1 << endl;
    	}
     
    	return 0;
    }
    Chez moi, ça donne
    Test éé àè !
    T
    e
    s
    t












    !
    Mon "text file encoding" est bien sûr UTF-8

  9. #9
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 771
    Par défaut
    Tu ne piges pas le truc : 1 caractère Unicode peut varier entre 1 et 4 octets

    Donc la première boucle fonctionne parce que les octets ne sont pas séparés.
    Je le redis en UTF-8, é c'est 0xC3 0xA9, à c'est 0xC3 0xA0 et è, 0xC3 0xA8.
    Tu peux également coder "Test \xC3\xA9\xC3\xA9 \xC3\xA0\xC3\xA8 !"

    Mais ta deuxième boucle met des fins de ligne entre chaque octet \n, \r, \r\n au choix

  10. #10
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Bonjour,

    En plus de t'assurer que la console qui affiche le texte est bien en utf-8 tu dois également t'assurer que ton compilateur lit les fichiers sources en utf-8.
    A noter que tu dois depuis c++ 11, précédé ta chaine utf-8 par u8 => https://en.cppreference.com/w/cpp/la...string_literal
    La classe std::string ne gère absolument AUCUN encodage. C'est juste un tableau d'octet donc les 3/4 de ces fonctions n'ont aucun sens en UTF-8 ( Iterateur, etc... )

    Pour MSVC : /UTF-8 https://docs.microsoft.com/fr-fr/cpp...?view=msvc-160

    Pour GCC : -finput-charset=UTF-8 https://gcc.gnu.org/onlinedocs/gcc-6.1.0/cpp/Character-sets.html

    Pour Clang : tous les fichiers sont par défaut lus en UTF-8 ( ASCII étant naturellement aligné 1 pour 1 avec UTF-8 )

    Il existe une libraire bien connue et très utilisée pour gérer tout ça et qui est utilisée dans toute l'industrie digne de ce nom pour gérer l'internationalisation ( https://icu.unicode.org/ )

    Sinon pour comprendre ce qu'il y a à comprendre sur l'unicode ( UTF-8, UTF-16, UTF-32 ) tu dois au minimum lire ces 2 sources:

    1. http://utf8everywhere.org/
    2. https://www.joelonsoftware.com/2003/...ts-no-excuses/



  11. #11
    Membre émérite Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    601
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 601
    Par défaut
    Merci Foetus d'écrire en gros vu mon âge avancé
    Je pense avoir compris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main() {
    	string chaine_1 = "Test  éé àè !";
    	cout << chaine_1 << endl;
    	cout << "Affichage du 't' codé sur 1 octet : " << chaine_1.substr(3,1) << endl;
    	cout << "tentative d'affichage du 1° 'é' sur 1 octet : " << chaine_1.substr(6,1) << endl;
    	cout << "Affichage du 1° 'é' codé sur 2 octets : " << chaine_1.substr(6,2)<< endl;
    	return 0;
    }
    affiche logiquement
    Test éé àè !
    Affichage du 't' codé sur 1 octet : t
    tentative d'affichage du 1° 'é' sur 1 octet : �
    Affichage du 1° 'é' codé sur 2 octets : é
    Merci Astraya pour les les explications et le lien vers la librairie dédiée. je vais regarder tout ça.

  12. #12
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 771
    Par défaut
    Voici ce que tu dois faire (non testé)
    J'avais dit de compter les 1 dans le premier octet, mais tu peux simplement faire des tests de plage de valeurs (mais à tester)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #include <iostream>
    #include <string>
     
    #include <cstdlib>
     
     
    int main() {
        std::string str="Test éé àè !";
     
        std::cout << str << std::endl;
     
        size_t index;
        unsigned char c; // <- unsigned very important
        bool is_valid;
     
    //  Display code point
        for(index=0, c=str[index]; (c != '\0'); ++index) {
            c=str[index];
     
            if (c != '\0') {
                std::cout << "0x" << std::hex << (int) c << ' ';
            }
        }
        std::cout << std::endl;
     
    //  Let's go
        for(index=0, c=str[index], is_valid=true; (is_valid && (c != '\0'));) {
            if (c <= 0x7F) {
                std::cout << c << '_';
                ++index;
            } else if ((c >= 0xC2) && (c <= 0xDF)) {
                std::cout << c << str[index + 1] << '_';
                index += 2;
            } else if ((c >= 0xE0) && (c <= 0xEF)) {
                std::cout << c << str[index + 1] << str[index + 2] << '_';
                index += 3;
            } else if ((c >= 0xF0) && (c <= 0xF4)) {
                std::cout << c << str[index + 1] << str[index + 2] << str[index + 3] << '_';
                index += 4;
            } else {
                is_valid = false;
            }
     
            c = str[index];
        }
        std::cout << std::endl;
     
     
        return EXIT_SUCCESS;
    }

  13. #13
    Membre émérite Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    601
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 601
    Par défaut
    C'est clair merci !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. MySQL, utf8 et ordre de tri avec initiales accentuées
    Par Ferdinand dans le forum Outils
    Réponses: 8
    Dernier message: 04/10/2007, 00h10
  2. Réponses: 5
    Dernier message: 19/09/2007, 14h47
  3. [MySQL] unserialize avec contenu accentué
    Par localhost dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 17/01/2006, 18h46
  4. [JEditorPane] Problème avec caractère accentué
    Par scifire dans le forum Composants
    Réponses: 6
    Dernier message: 14/09/2005, 14h58
  5. HashCode avec lettres accentuées...
    Par Kineas dans le forum C++
    Réponses: 4
    Dernier message: 08/04/2005, 10h54

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