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 :

Utiliser du texte avec des accents


Sujet :

C++

  1. #1
    Membre averti
    Utiliser du texte avec des accents
    Bonjour,

    Je débute en programmation cpp et j'ai un petit problème avec un tuto.

    Voilà ce qu'ils disent:
    Un mot sur Windows

    Si vous êtes sous Windows et que vous tentez d’afficher du texte avec des accents, vous allez obtenir des caractères bizarres. Pour afficher du code avec des accents, vous allez devoir ajouter les lignes 2, 3 et 8 dans votre code. Nous en reparlerons plus tard.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <iostream>
    #define NOMINMAX
    #include <Windows.h>
     
    int main()
    {
        // À utiliser avant d'afficher du texte.
        SetConsoleOutputCP(1252);
        std::cout << "Oui, je peux utiliser éèàï !" << std::endl;
    }
    Le problème c'est qu'après avoir compilé leur code, voilà ce que j'obtiens:
    Oui, je peux utiliser éèÃ*ï !

    Donc pas du tout la même phrase qu'eux..
    D'où vient le problème ?

  2. #2
    Membre expert
    Cela est très dépendant du format d'enregistrement des fichiers. J'ai l'impression que tu enregistres en utf-8, mais configure la console en ANSI Latin 1 -> les formats ne sont pas compatibles, l'affichage ne correspond pas. Il faudrait utiliser 65001 à la place de 1252.

  3. #3
    Membre averti
    Ah oui, ça fonctionne parfaitement avec 65001.
    Ca la fou mal pour le tuto de zestedesavoir.. 2ème code que je teste dessus et 1er plantage..
    Jme demande si je ne dois pas changer de tuto, mais c'est difficile d'en trouver des récents..
    En tout cas merci pour ton aide..

    edit: Encore plus bizarre que personne ne leur ait signalé leur erreur depuis le temps, ce que je viens de faire.

  4. #4
    Rédacteur/Modérateur

    Le code marche parfaitement tel quel sur mon Windows 10 en compilant avec VS2019.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre averti
    Citation Envoyé par Bousk Voir le message
    Le code marche parfaitement tel quel sur mon Windows 10 en compilsant avec VS2019.
    Ba moi aussi je suis sous Windows 10 avec vs2019 et ça ne fonctionne pas..

  6. #6
    Rédacteur/Modérateur

    Le code est tout de même bof et plein de valeurs magiques.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <iostream>
    #include <windows.h>
     
    int main()
    {
        SetConsoleOutputCP(CP_UTF8);
        std::cout << u8"Oui, je peux utiliser éèàï !";
    }

    Est plus lisible et montre clairement l'objectif.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre averti
    Ouais c'est clair ^

  8. #8
    Expert confirmé
    La gestion des accents dépend de beaucoup de choses :
    - le compilateur
    - l'éditeur de texte
    - le code page de la console.

    Sous Linux, les trois sont presque toujours en UTF-8, donc il y a rarement des problèmes.
    Sous Windows :
    - la plupart des fichiers textes sont au format : 1252 (Western European Windows appelé aussi ANSI) en Europe et Amérique.
    - la console est par défaut au format : 850 (Western European DOS) en Europe.
    - et chaque compilateur a sa propre gestion par défaut des charset.

    La séquence saisie dans un éditeur de code va traverser 4 étapes avant d'arriver à la console.
    a) stockage du fichier source dans un code-page donné (p.e.:1252)
    b) au moment de la compilation du fichier, le compilateur suppose que le fichier est dans un format donné (par défaut source-charset vaut .1252 avec MSVC) et le convertit dans le code dans un code-page donné (par défaut execution-charset vaut .1252 avec MSVC)
    c facultative) quand le code se déroule, il peut convertir ses chaînes (de UTF-8 vers un code-page ou inversement)
    d) le texte est émis vers la console, le texte et la console doivent utiliser le même code-page (la console Windows est par défaut en 850)

    D'où le conseil de la formation : sous Windows forcer la page code console à 1252, comme les autres étapes sont habituellement toutes à 1252, ça devrait fonctionner. Sauf qu'ici un des éléments n'a pas les valeurs auquel on s'attend sous Windows.
    Sous Windows, cette méthode a pas mal d'avantages si on ne veut pas utiliser des caractères exotiques. Par exemple dans une chaîne, chaque caractère correspond à un seul char. En utilisant l'UTF-8 on perd cette simplification.

    Sinon on peut facilement décider d'utiliser l'UTF-8 :
    - l'étape (a), on peut sauvegarder les fichiers sources au format UTF-8 avec BOM. Sans cela, il faut toujours s'assurer que le fichier est enregistré au format attendu par le compilateur, par exemple sous MSVC on a l'option /source-charset:.codepage.
    - Pour l'étape (b) on paramètre le compilateur, par exemple sous MSVC avec l'option /execution-charset:.65001.
    - Pas besoin d'étape (c)
    - Pour l'étape (d), on force la console en UTF-8 par la commande SetConsoleOutputCP( 65001 );.

  9. #9
    Expert éminent
    Le mieux c'est d'échapper les caractères , même si tes chaînes de caractères sont moins exploitables/ lisibles

    C: échappement des caractères \n, \x, \u, \U (<- lien wiki en anglais)

    Mais dans mon code, sous Cygwin, l'ANSI et le wcout ne fonctionne pas bizarre

    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
    #include <iostream>
     
    #include <cstdlib>
    #include <windows.h>
     
     
    /*****************************************************************************/
    /***********************************  Main  **********************************/
    /*****************************************************************************/
     
    int main(int argc, char** argv)
    {
        const char ansi_str[]     =  "Oui, je peux utiliser \xE9\xE8\xE0\xEF !";
        const char UTF8_str[]     =  "Oui, je peux utiliser \xC3\xA9\xC3\xA8\xC3\xA0\xC3\xAF !";
        const wchar_t UTF16_str[] = L"Oui, je peux utiliser \u00E9\u00E8\u00E0\u00EF !";
     
        std::string ansi_std_str("Oui, je peux utiliser \xE9\xE8\xE0\xEF !");
        std::string UTF8_std_str("Oui, je peux utiliser \xC3\xA9\xC3\xA8\xC3\xA0\xC3\xAF !");
        std::wstring UTF16_std_str(L"Oui, je peux utiliser \u00E9\u00E8\u00E0\u00EF !");
     
        SetConsoleOutputCP(1252 /* windows-1252 */);
        std::cout << "ANSI:   Oui, je peux utiliser \xE9\xE8\xE0\xEF !" << std::endl <<
                     "        " << ansi_str << std::endl <<
                     "        " << ansi_std_str << std::endl;
     
     
        SetConsoleOutputCP(65001 /* utf-8 */);
        std::cout << "UTF-8:  Oui, je peux utiliser \xC3\xA9\xC3\xA8\xC3\xA0\xC3\xAF !" << std::endl <<
                     "        " << UTF8_str << std::endl <<
                     "        " << UTF8_std_str << std::endl;
     
     
        SetConsoleOutputCP(1200 /* utf-16 */);
        std::cout << "UTF-16: Oui, je peux utiliser \u00E9\u00E8\u00E0\u00EF !" << std::endl;
        std::wcout << L"        " << UTF16_str << std::endl
                   << L"        " << UTF16_std_str << std::endl;
     
     
        return EXIT_SUCCESS;
    }

  10. #10
    Membre averti
    Citation Envoyé par Bousk Voir le message
    Le code est tout de même bof et plein de valeurs magiques.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <iostream>
    #include <windows.h>
     
    int main()
    {
        SetConsoleOutputCP(CP_UTF8);
        std::cout << u8"Oui, je peux utiliser éèàï !";
    }

    Est plus lisible et montre clairement l'objectif.
    J'ai testé ta solution, mais ça m'écrit encore: Oui, je peux utiliser éèÃ*ï !

    La police de ma console c'est consolas, je crois que c'est la police par défaut non ? (je ne me rappel plus si je l'ai changé)
    Je ne comprend pas ce qui bug sur mon pc qui a pourtant windows 10 et vs2019

    edit: J'ai testé avec d'autres polices ça donne le même résultat

  11. #11
    Expert confirmé
    Bonjour,

    Utiliser les caractères d'échappement permet de gérer le problème du format de fichier. Mais il ne sert qui si on utilise les \u et \U, ainsi l'étape que j'ai appelée (a) est résolue (par besoin d'enregistrement particulier du fichier, et tous les textes sont en UTF)
    Mais l'utilisation des \x est plutôt une complication de portabilité, on force des caractères codé (la Cp1252 ou l'UTF-8 dans l'exemple de foetus) qui gérerait les étapes (a) et (b). J'utilise le conditionnel car le \x devient trop compliqué pour moi.
    Pour simplifier l'étape (b) on peut aussi utiliser les préfixes de chaîne u8, u ou U qui vont garantir que la chaîne concernée dans le code est au format UTF au lieu ce celui par défaut indiqué dans /execution-charset:. On a aussi le préfixe L qui utilise des chaînes standardisées, je ne sais pas s'il est configurable sous Windows, il correspond plutôt à l'UCS2.

  12. #12
    Membre averti
    Ok merci pour cette explication.
    Mais moi j'aimerais quand même comprendre pourquoi 1252 fonctionne chez Bousk et pas chez moi alors qu'on a la même config (win10+vs2019)

  13. #13
    Membre éclairé
    Bonjour


    Mais moi j'aimerais quand même comprendre pourquoi 1252 fonctionne chez Bousk et pas chez moi alors qu'on a la même config (win10+vs2019)
    Parce que chez toi, le texte de ton programme est sauvegardé en UTF8 et chez Bousk en ANSI 1252 (ça c'est souvent un paramètre de ton éditeur de texte (intégré ou pas à ton EDI))

    Cordialement

  14. #14
    Membre averti
    Ok merci bien

  15. #15
    Membre averti
    J'ai même essayé avec Cygwin mais ça me retourne une erreur:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    $ gcc test.cpp -o test.exe
    /usr/lib/gcc/x86_64-pc-cygwin/9.3.0/../../../../x86_64-pc-cygwin/bin/ld*: /tmp/ccdsi2jS.o:test.cpp<img src="images/smilies/icon_sad.gif" border="0" alt="" title=":(" class="inlineimg" />.text+0x2a)*: référence indéfinie vers «*std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)*»
    /tmp/ccdsi2jS.o:test.cpp<img src="images/smilies/icon_sad.gif" border="0" alt="" title=":(" class="inlineimg" />.text+0x2a): relocalisation tronquée pour concorder avec la taille*: R_X86_64_PC32 vers le symbole indéfini std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
    /usr/lib/gcc/x86_64-pc-cygwin/9.3.0/../../../../x86_64-pc-cygwin/bin/ld*: /tmp/ccdsi2jS.o:test.cpp<img src="images/smilies/icon_sad.gif" border="0" alt="" title=":(" class="inlineimg" />.text+0x5e)*: référence indéfinie vers «*std::ios_base::Init::Init()*»
    /tmp/ccdsi2jS.o:test.cpp<img src="images/smilies/icon_sad.gif" border="0" alt="" title=":(" class="inlineimg" />.text+0x5e): relocalisation tronquée pour concorder avec la taille*: R_X86_64_PC32 vers le symbole indéfini std::ios_base::Init::Init()
    /usr/lib/gcc/x86_64-pc-cygwin/9.3.0/../../../../x86_64-pc-cygwin/bin/ld*: /tmp/ccdsi2jS.o:test.cpp<img src="images/smilies/icon_sad.gif" border="0" alt="" title=":(" class="inlineimg" />.rdata$.refptr._ZNSt8ios_base4InitD1Ev[.refptr._ZNSt8ios_base4InitD1Ev]+0x0)*: référence indéfinie vers «*std::ios_base::Init::~Init()*»
    /usr/lib/gcc/x86_64-pc-cygwin/9.3.0/../../../../x86_64-pc-cygwin/bin/ld*: /tmp/ccdsi2jS.o:test.cpp<img src="images/smilies/icon_sad.gif" border="0" alt="" title=":(" class="inlineimg" />.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0)*: référence indéfinie vers «*std::cout*»
    collect2: erreur: ld a retourné le statut de sortie 1


    Non sérieux, j'aimerais vraiment comprendre pourquoi ça fonctionne chez Bousk et pas chez moi...
    Je veux que ça fonctionne avec l'option 1252 chez moi, comment je dois faire ?
    Ca m'ennuie de continuer le cours de cpp de zestedesavoir tant que n'aurais pas trouvé pourquoi ça ne fonctionne pas chez moi...
    edit: Et quand j'essaie de lancer mon programme compilé avec vs2019 via la fenêtre de Cygwin ça ne m'affiche rien du tout..

    Merci..

  16. #16
    Expert éminent
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    gcc test.cpp -o test.exe

    non je ne comprends pas ca ne compile pas

    • gcc : compilateur/ éditeur de liens C
    • g++ : compilateur/ éditeur de liens C++


    Et au passage, utilise "-Wall" pour activer tous les avertissements

  17. #17
    Membre averti
    A voilà ça fonctionne. Je suis désolé mais je suis tellement habitué à utiliser gcc sous Linux que je n'ai pas pensé qu'il fallait utiliser g++.
    Mais là ça fonctionne j'ai bien les caractères normal.

  18. #18
    Membre averti
    Le problème d'affichage de caractères ne vient pas de mon éditeur de texte, c'est un problème de compilation.
    Car quand je compile mon programme.cpp dans cygwin, les caractères sont bons, mais quand j'essaie de lancer mon programme.cpp (qui a été compilé avec vs2019) dans cygwin, là ça ne fonctionne pas.. Ca me donne toujours ce résultat :

    $ ./ConsoleApplication1.exe
    Oui, je peux utiliser éèÃ*ï !