Pour afficher les caractères accentués sous windows en mode console

Soyez le premier à donner votre avis sur cette source.

Vue 9 821 fois - Téléchargée 695 fois

Description

Le code ASCII de base a été mis au point pour la langue anglaise, il ne contient donc pas de caractères accentués, ni de caractères spécifiques à une langue. Il a été ensuite étendu pour apporter des solutions à ce besoin. Deux codages particuliers ont été ainsi définis : le code ASCII étendu OEM, défini aux débuts des PC IBM, c'est celui qui est encore utilisé pour les affichages en mode console sous Windows, et le code ASCII étendu ANSI utilisé par les autres systèmes d'exploitation. C'est pourquoi il est très utile de pouvoir afficher correctement des mots ayant des caractères accentués de manière très voisine et avec très peu de changement en passant d'une environnement à l'autre. C'est ce que s'efforce de faire la solution ci-jointe construite grâce à plusieurs échanges avec CptPingu. L'explication est la suivante. En C++, il n'est pas possible de redéfinir l'opérateur << pour un type pod (plain old data, type classique comme int, double, char, etc.). L'opérateur << pour les std::string existant déjà, il y aurait eu ambiguïté. La solution consiste en une astuce simple : on définit une classe d'encapsulation pour les std::string, ce qui permet d'avoir un nouveau type. La surcharge n'existant pas pour ce type, on peut donc redéfinir l'opérateur << pour ce type équivalent au std::string. Et comme le std::string convertit le char*/char[] reçu en entrant cela fonctionne aussi pour le type char*/char[]. Merci CptPingu.

Source / Exemple :


//------------------------   fichier oem.hpp   ---------------------------
#ifndef OEM_HPP
#define OEM_HPP
#include <windows.h>
   
struct SetOEM 
{ 
explicit SetOEM(const std::string& s) 
    : _s(s) 
  { 
  } 
  const std::string _s; 
}; 
    
inline SetOEM 
OEM(const std::string& s) 
{ 
  return s; 
} 
    
std::ostream& 
operator<<(std::ostream& out, const SetOEM& oem) 
{ 
  char* s = new char[oem._s.size() + 1]; 
  CharToOemA(oem._s.c_str(), s); 
  out << s; 
  delete [] s; 
  return out; 
} 
   
#endif // OEM_HPP
//------------------------   fichier main.cpp   --------------------------
#include <iostream>
#include <string>
#include "oem.hpp"
int main()
{ 
  const char caf[] = "Les caractères français doivent être convertis"; 
  const std::string str = "Noëlle aperçut là-bas l'âne bâté"; 
  std::cout << std::endl; 
  std::cout << OEM("Démo de OEM() n° 1 : ") << OEM(caf) << std::endl << std::endl 
            << OEM("Démo de OEM() n° 2 : ") << OEM("Cet été fut très chaud !") << std::endl << std::endl 
            << "Mais sans OEM()    : " << "Cet été fut très chaud !" << std::endl << std::endl 
            << OEM("Démo de OEM() n° 3 : ") << OEM(str) << std::endl  << std::endl 
            << "Mais sans OEM()    : " << str << std::endl << std::endl 
            << std::endl << "Au revoir !" << std::endl << std::endl; 
  getchar(); 
  return 0; 
}

Conclusion :


Comme le montre le main() on peut afficher en C++ sous Windows en mode console avec l'ASCII étendu OEM des mots ayant des caractères accentués d'une manière très voisine de ce qui serait fait si ce mode utilisait l'ASCII étendu ANSI. Et de cette manière la portabilité éventuelle dans un autre environnement est extrêmement facile à effectuer. On peut aussi noter que par rapport à la solution utilisant setlocale on a ici la possibilité de mélanger les caractères spéciaux de plusieurs langues et de plus c'est compatible avec les compilateurs et systèmes anciens.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Renfield
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
22 août 2018
54 -
un petit :

setlocale( LC_CTYPE , "fra" ) ;

issu de clocale.h

et zou...
pgl10
Messages postés
313
Date d'inscription
samedi 18 décembre 2004
Statut
Membre
Dernière intervention
6 juillet 2019
1 -
Merci Renfield. C'est une information complémentaire qui intéressera de nombreux visiteurs. A noter que dans http://www.cppfrance.com/code.aspx?ID=53813 fredg19 a écrit dans jour_naissance.cpp : #include <clocale> ... setlocale(LC_ALL, "french"); pour le même besoin. Mais chez moi chacune de ces deux solutions voisines se compile bien mais ne fonctionne pas. Je suppose que d'autres auraient le même résultat que moi.
fredg19
Messages postés
11
Date d'inscription
jeudi 5 mars 2009
Statut
Membre
Dernière intervention
16 mars 2015
-
J'approuve PGL10, je crois que le #include <clocale> est la meilleure solution pour les accents.
cs_FraGag
Messages postés
82
Date d'inscription
jeudi 19 février 2004
Statut
Membre
Dernière intervention
18 avril 2008
-
Je n'ai jamais essayé setlocale, mais je sais que SetConsoleCP et SetConsoleOutputCP permettent de définir l'encodage de la console. En passant 1252 aux deux fonctions, la console fonctionnera avec la page de codes 1252. Si je me souviens bien, on peut même spécifier 65001 pour que la console fonctionne en UTF-8; on a alors accès à tous les caractères Unicode (tant que la police utilisée dans la console a les glyphes correspondants).
Jojo Lancien
Messages postés
7
Date d'inscription
vendredi 8 juin 2012
Statut
Membre
Dernière intervention
8 juin 2012
-
Le débutant que je suis est en admiration devant cet exemple d'utilisation de la surcharge en cpp. Les commentaires m'ont également beaucoup appris et, jamais plus, je n'écrirai de programme console qui affiche incorrectement les accents. Mais, bien sûr, celà ne résout pas complètement le problème OEM/ANSI car si on tape la commande
main.exe >texte.txt
seules les lignes non converties seront correctes si on ouvre texte.txt avec le bloc-note.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.