Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème d'encodage

    25 juin 2023 à 18:07:45

    Bonjour, j'ai commencé récemment à coder en langage C avec VS Code mais j'ai remarqué un problème d'encodage étrange.

    Illustration :

    Pouvez-vous m'aider, s'il vous plaît ?

    Merci par avance pour vos retours !

    -
    Edité par LapinLapinou 25 juin 2023 à 18:08:19

    • Partager sur Facebook
    • Partager sur Twitter
      25 juin 2023 à 18:54:06

      Bonjour ! Tu es sous Windows ? J'ai fait du C sous Windows 7, et à l'époque la console n'utilisait pas le même encodage que les éditeurs. Pour afficher les lettres accentuées, j'utilisais cette correspondance :

              c = getchar() ;
              switch (c)
              {
                  case 224 : printf("\\205" ) ; break ; // a accent grave
                  case 226 : printf("\\203" ) ; break ; //          circonflexe
                  case 228 : printf("\\204" ) ; break ; //   trêma
                  case 233 : printf("\\202" ) ; break ; // e accent aigu
                  case 232 : printf("\\212" ) ; break ; //          grave
                  case 234 : printf("\\210" ) ; break ; //          circonflexe
                  case 235 : printf("\\211" ) ; break ; //   trêma
                  case 238 : printf("\\214" ) ; break ; // i accent circonflexe
                  case 239 : printf("\\213" ) ; break ; //   trêma
                  case 244 : printf("\\223" ) ; break ; // o accent circonflexe
                  case 246 : printf("\\224" ) ; break ; //   trêma
                  case 249 : printf("\\227" ) ; break ; // u accent grave
                  case 251 : printf("\\226" ) ; break ; //   accent circonflexe
                  case 252 : printf("\\201" ) ; break ; //   trêma
                  case 255 : printf("\\230" ) ; break ; // y trêma
                  case 230 : printf("\\221" ) ; break ; // ae collés
                  case 231 : printf("\\207" ) ; break ; // c cédille
                  case 241 : printf("\\244" ) ; break ; // n de canyon
                  case 192 : printf("\\267" ) ; break ; // A accent grave
                  case 194 : printf("\\266" ) ; break ; //   accent circonflexe
                  case 196 : printf("\\216" ) ; break ; //   trêma
                  case 201 : printf("\\220" ) ; break ; // E accent aigu
                  case 200 : printf("\\324" ) ; break ; //   accent grave
                  case 202 : printf("\\322" ) ; break ; //   accent circonflexe
                  case 203 : printf("\\323" ) ; break ; //   trêma
                  case 206 : printf("\\327" ) ; break ; // I accent circonflexe
                  case 207 : printf("Iš" ) ; break ; // pas trouvé...
                  case 212 : printf("O^" ) ; break ; // pas trouvé...
                  case 214 : printf("\\231" ) ; break ; // O trêma
                  case 217 : printf("\\353" ) ; break ; // U accent grave
                  case 219 : printf("\\352" ) ; break ; //   accent circonflexe
                  case 220 : printf("\\232" ) ; break ; //   trêma
                  case 221 : printf("\\330" ) ; break ; // Y trêma
                  case 198 : printf("\\222" ) ; break ; // AE collés
                  case 199 : printf("\\200" ) ; break ; // C cédille
                  case 209 : printf("\\245" ) ; break ; // N de canyon
                  case 171 : printf("\\256" ) ; break ; // guillemets ouvrants
                  case 187 : printf("\\257" ) ; break ; // guillemets fermants
                  case 215 : printf("\\236" ) ; break ; // fois
                  case 247 : printf("\\366" ) ; break ; // divisé
                  // case 126 : printf("" ) ; break ; // pas trouvé ...
                  case 177 : printf("\\361" ) ; break ; // plus ou moins
                  case 186 : printf("\\247" ) ; break ; // degrés
                  case 216 : printf("\\235" ) ; break ; // ensemble vide
                  default  : printf("%c", c ) ;
              }

      Si je me souviens bien :

      − On tape une lettre, qui est lue par 'getchar' sous forme d'un n° ASCII étendu.

      − Mais pour l'afficher avec 'printf' il faut utiliser l'encodage de la console, qui est différent.

      (Si je me souviens bien. Mais c'est vieux, j'ai retrouvé ça dans un fichier datant de 2012. Je ne sais pas si les Windows récents ont toujours cet inconvénient.)

      • Partager sur Facebook
      • Partager sur Twitter
        25 juin 2023 à 19:01:51

        Utilises le bouton code </> du forum pour poster ton code ! (tu peux modifier ton post, lien modifier en haut à droite du post).
        Pour ton problème, c'est que tu dois être sous Windows, et que la console windows ne gère pas très bien les accents.
        essais avec un code comme celui ci :
        #include <stdio.h>
        #include <locale.h>
        
        int main()
        {
            setlocale(LC_ALL, "");
            printf("é");
            return 0;
        }
        mais ça va dépendre aussi de l'encodage de ton fichier source, il faudrait qu'il soit en win 1252

        -
        Edité par rouIoude 25 juin 2023 à 19:09:27

        • Partager sur Facebook
        • Partager sur Twitter
        ...
          25 juin 2023 à 19:05:35

          Hello,

          Encore une idée: en console, tape "chcp 1252" (sans les guillemets). Tu peux aussi (solution de dépannage) mettre system("chcp 1252"); en ligne 4bis (nécéssite stdlib.h)

          Edit: main() renvoie un int. Il manque un return(qqchose).

          -
          Edité par edgarjacobs 25 juin 2023 à 19:11:41

          • Partager sur Facebook
          • Partager sur Twitter

          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

            25 juin 2023 à 19:08:13

            Bonjour, oui, je suis sous Windows. Merci mais je ne comprends pas bien ton code et comment l'appliquer pour chaque caractère accentué, par exemple...
            • Partager sur Facebook
            • Partager sur Twitter
              26 juin 2023 à 2:03:07

              Comme on te l'a dit, Windows semble utiliser plusieurs systèmes d'encodage. Explique nous ce que tu veux faire.

              Le code suivant:

               
              #include <stdio.h>

              #include <stdlib.h>


              int main(void) {

                  unsigned char c = 'é';


                  system("chcp");   // chcp sans paramètre donne l'encodage lors de l'exécution.


                  printf("*%c*\n", c);


              }

               
              donne le warning suivant:   (mon éditeur est en UTF-8 / 65001)
               


              aa.c: In function 'main':                                                                                               


              aa.c:4:23: warning: multi-character character constant [-Wmultichar]                                                  

               
                  4 |     unsigned char c = 'é';                                                                                      


                    |                       ^~~                                                                                       


              Et si j'exécute tout de même:
               


              **

              -
              Edité par PierrotLeFou 26 juin 2023 à 2:11:57

              • Partager sur Facebook
              • Partager sur Twitter

              Le Tout est souvent plus grand que la somme de ses parties.

                26 juin 2023 à 9:16:40

                Pour expliquer un peu

                • En C il y a une bizarrerie sur les constantes censées contenir un caractére. On peut - pour des raisons historiques - écrire
                char c = 'xyz';

                Et alors c contiendra le premier octet 'x'

                • C a été conçu en confondant caractère et octet, avec l'hypothèse qu'un caractère tenait dans un "byte" qui tenait dans un octet
                • Comme on se sert des octets pour toutes les zones tampon (exemple pour un read), il devrait y avoir un type "byte", ça serait plus logique. Mais bon, y a déjà char, dont on ne sait pas si il est signé ou pas, who cares ?
                • De nos jours, on utilise souvent l'encodage utf8 pour unicode. Il se trouve que c'est un codage "multibyte", dans lequel seul les 128 caractères Ascii 7 bits sont codés sur un octet. Les autres, c'est sur 2, 3,... en particulier c'est le cas du 'é'.

                Alors on a un problème quand on compile un texte source utf8 pour produire un exécutable qui tournera sur un console avec le codage cp 1252 ou autre isolatin 8 bits.

                PS: Faut se rappeler que le langage C, c'est un langage bricolé pour remplacer l'assembleur pour la programmation du noyau et des utilitaires de base d'unix, avec comme contrainte initiale forte de devoir tourner en mémoire sur quelques kilo-octets.  A l'époque, on faisait mieux en matière de conception de langages de programmation (PL/I était sorti en 64, par exemple).  Le succès de C, c'est venu en grande partie à cause  de la compatibilité Unix d'un côté et parce que ça compilait sur des micros de l'autre dans les années 80. Du coup ça c'est développé sauvagement, chaque compilateur avec ses extensions et variantes, avant que le langage soit réellement standardisé (1989....) : beaucoup trop tard pour rectifier les erreurs de tir....

                -
                Edité par michelbillaud 26 juin 2023 à 10:16:26

                • Partager sur Facebook
                • Partager sur Twitter
                  26 juin 2023 à 15:03:13

                  Salut LapinLapinou,

                  Tu pourrais aussi simplement installer une console qui gère nativement UTF8.

                  Microsoft en a réalisé une, qui est sous licence MIT (open source donc), et qui est disponible depuis son store.

                  https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701?hl=fr-fr&gl=fr&rtc=1

                  https://github.com/microsoft/terminal

                  • Partager sur Facebook
                  • Partager sur Twitter
                    26 juin 2023 à 19:28:48

                    michelbillaud a écrit:

                    char c = 'xyz';

                    Et alors c contiendra le premier octet 'x'

                    Chez moi, c contient 'z' ?!? (peut-être compiler dependant ?)

                    -
                    Edité par edgarjacobs 26 juin 2023 à 19:30:31

                    • Partager sur Facebook
                    • Partager sur Twitter

                    On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                      26 juin 2023 à 19:46:23

                      En effet. Erreur de ma part. En testant, chez moi ça met aussi le dernier caractère de la séquence.

                      Un coup d'oeil au projet de standard C-23  https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf

                      Je traduis/résume 6.4.4.4 character constants (page 65)

                      Une constante caractère, c'est

                      • un préfixe d'encodage, optionnel, qui peut être u8 (utf_8), u (utf-16) , U (utf-32) ou L (wchar_t)
                      • une séquence non vide de caractères-C, entre "quotes"

                      Le caractère C, c'est

                      • n'importe quel caractères sauf  ', \ ou saut de ligne
                      • ou une séquence avec préfixe \, genre \n, \', etc

                      Semantique (11)

                      • si un seul caractère : la valeur numérique de celui-ci
                      • si plusieurs, ça dépend
                      The value of an integer character constant containing more than one character (e.g.,’ab’), or containing a character or escape sequence that does not map to a single value in the literal encoding, is implementation-defined.

                      Bref, faut pas faire ça !


                      -
                      Edité par michelbillaud 26 juin 2023 à 19:49:34

                      • Partager sur Facebook
                      • Partager sur Twitter
                        27 juin 2023 à 17:36:34

                        Bonjour Robun,

                            case 233 : printf("\\202" ) ; break ; // e accent aigu

                        233 est le code ascii du caractère é

                        mais alors, 202, ca correspond à quoi ?

                        (j'ai fait le test, pour afficher é, il faut que j'écrive \202 et non pas \\202)

                        -
                        Edité par Phil_1857 27 juin 2023 à 17:39:07

                        • Partager sur Facebook
                        • Partager sur Twitter
                          27 juin 2023 à 18:37:22

                          Le \202 représente un caractère écrit en octal. On a bien '\n' pour la fin de ligne.


                          Avec chcp 850 je peux lire le  é
                           


                          #include <stdio.h>


                          int main(void) {


                              unsigned char c = '\202';


                              printf("%c\n", c);


                          }

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Le Tout est souvent plus grand que la somme de ses parties.

                            28 juin 2023 à 10:57:58

                            Bonjour Pierrot,

                            Justement, c'est bizarre, 202 en octal ce n'est pas le caractère é, d'après la table des codes ASCII, c'est 351 :

                            DÉC  OCT  HEX  BIN          Symbole  Numéro HTML  Nom HTML  Description

                            130   202  82    10000010  ‚                &#130;              &sbquo;       Guillemet-virgule inférieur

                            233  351   E9    11101001   é                &#233;             &eacute;      Lettre minuscule latine e accent aigu

                            -
                            Edité par Phil_1857 28 juin 2023 à 11:02:28

                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 juin 2023 à 11:24:38

                              Phil_1857 a écrit:

                              d'après la table des codes ASCII, c'est 351 :

                              Sauf que la table ASCII s’arrête à 127 décimal, la suite dépend des Code Page utilisé.

                              Edit : en CP 850 le é est bien à 130 soit 0202 en octal

                              -
                              Edité par rouIoude 28 juin 2023 à 11:37:38

                              • Partager sur Facebook
                              • Partager sur Twitter
                              ...
                                28 juin 2023 à 12:36:19

                                Les codages 8 bits habituels : iso-latin1 petit nom habituel de https://fr.wikipedia.org/wiki/ISO/CEI_8859-1

                                Le é est dans la case E9 (hexa) donc  351 décimal,   233 octal

                                 L'isolatin-15 est une mise à jour qui diffère pour 8 caractères https://fr.wikipedia.org/wiki/ISO/CEI_8859-15 dont €, OE et oe (liés).

                                Comme d'habitude Microsoft embête tout le monde en faisant exprès des trucs pas standard (*), dans la page de code 850

                                https://fr.wikipedia.org/wiki/Page_de_code_850


                                le é est dans la case 82 (120 en décimal). EDIT 130, pas 120.

                                Avec Windows 252, c'est en E9, comme iso-latin1 et 15 https://fr.wikipedia.org/wiki/Windows-1252.

                                (*) enfin, c'est historiquement IBM un truc d'IBM (rappelez vous, le PC...) qui date d'avant ISO-LATIN (années 90). Le problème, c'est de distribuer des systèmes d'exploitation avec des consoles qui fonctionnent avec ce standard antique.

                                -
                                Edité par michelbillaud 28 juin 2023 à 13:48:53

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  28 juin 2023 à 13:33:04

                                  Merci pour ces éclaircissements, c'est un peu le bazar quand même :-)

                                  En C, le code suivant m'imprime bien la lettre é :

                                   int main(void)
                                  {
                                  	printf("\202");
                                  	getch();
                                  	return(0);
                                  }

                                  En Python, le code suivant :

                                  c = 'é'
                                  dec = ord(c)
                                  octal = oct(dec)
                                  print('code ascii de {} en décimal : {} en octal : {}'.format(c,dec,octal))

                                  m'imprime bien :

                                  code ascii de é en décimal : 233 en octal : 0o351



                                  -
                                  Edité par Phil_1857 28 juin 2023 à 13:35:04

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    28 juin 2023 à 13:39:09

                                    Parce que en python tu utilise la page code 1252

                                    #include <stdio.h>
                                    #include <windows.h>
                                    
                                    int main(void)
                                    {
                                        SetConsoleOutputCP(1252);
                                        printf("\351");
                                        return 0;
                                    }

                                    écrit bien un 'é'


                                    Phil_1857 a écrit:

                                    c'est un peu le bazar quand même :-)

                                    Oui, souvent le plus simple, c'est de passer la console en cp 1252 en pensant que l'éditeur de code doit aussi être en 1252.

                                    Après comme Windows est plutôt destiné à des applications graphique, ils ne ce sont pas attardé sur la console.

                                    michelbillaud a écrit:

                                    le é est dans la case 82 (120 en décimal).

                                    130 en décimal !



                                    -
                                    Edité par rouIoude 28 juin 2023 à 13:49:50

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    ...
                                      28 juin 2023 à 13:52:20

                                      Merci pour la correction

                                      > c'est un peu le bazar

                                      Et même plus qu'un peu. Un des objectifs de C était d'avoir des programmes sources  portables,  avec les histoires d'encodage, c'est un peu raté pour y arriver en C.

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        28 juin 2023 à 18:32:28

                                        Voilà pourquoi, il y a dix ans, j'ai écrit un petit programme qui affiche toutes les possibilités (sur ma console). Il faut tester, expérimenter... et essayer de comprendre un jour. :)

                                        L'éditeur utilisait l'extension ISO-Latin 1, mais la console utilisait une autre extension (la page de code 850 si j'ai bien compris vos messages), d'où les codes différents. Ce n'est pas de l'ASCII mais des extensions de l'ASCII. Je ne sais pas comment ça marche sur les Windows récents.

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          29 juin 2023 à 11:13:16

                                          robun a écrit:

                                          Je ne sais pas comment ça marche sur les Windows récents.

                                          Ça n'a pas beaucoup changé, en interne et pour les application graphique c'est de l' UTF-16 LE (avant que l'UTF-8 existe).

                                          Les code source peuvent être en CP 1252 , ISO 8859-1 (Latin-1) et consœurs...  et en UTF-8 si compilation en UNICODE. (Les compilateurs n'apprécie pas l'UTF-16)

                                          Et la console est toujours en CP 850. 

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          ...
                                            29 juin 2023 à 12:24:34

                                            > Et la console est toujours en CP 850.

                                            Sinon on ne poserait pas la question sur le forum

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              1 juillet 2023 à 0:28:10

                                              Il y a un truc (a trick) (of the tail <-- excellent album!) qui permet de mettre la console dans le code page souhaité: il suffit de modifier le champ "cible" dans le raccourci:


                                              Notez l'ajout de /K chcp 1252 dans le champ "cible"

                                              Edit: et pour être transparent, on peut écrire /K chcp 1252 > NUL

                                              -
                                              Edité par edgarjacobs 1 juillet 2023 à 0:49:42

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                                              Problème d'encodage

                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                              • Editeur
                                              • Markdown