OVH Cloud OVH Cloud

Affichage de caracères étendus dans la console.

5 réponses
Avatar
Loïc Joly
Quand je fais dans mon code un cout<< "éùàç" << endl; par défaut, ce
sont des caractères étranges qui s'affichent.

J'ai réussi à afficher les caractères corrects, d'abord en appelant
SetConsoleOutputCP(1252), puis en changeant à la main la police utilisé
pour la console de "Police Raster" vers "Lucida Condole". Par contre, je
n'ai pas réussi à faire sélectionner cette police par programme.
Quelqu'un sait-il comment faire ?

Ou alors quelqu'un a-t-il une autre solution ?

--
Loïc

5 réponses

Avatar
jean dupont
----- Original Message -----
From: "Loïc Joly"
Newsgroups: fr.comp.os.ms-windows.programmation
Sent: Sunday, October 17, 2004 3:11 PM
Subject: Affichage de caracères étendus dans la console.


Quand je fais dans mon code un cout<< "éùàç" << endl; par défaut, ce
sont des caractères étranges qui s'affichent.

J'ai réussi à afficher les caractères corrects, d'abord en appelant
SetConsoleOutputCP(1252), puis en changeant à la main la police utilisé
pour la console de "Police Raster" vers "Lucida Condole". Par contre, je
n'ai pas réussi à faire sélectionner cette police par programme.
Quelqu'un sait-il comment faire ?

Ou alors quelqu'un a-t-il une autre solution ?

--
Loïc



Les éditeurs de type GUI n'utilisent pas le même jeu de caractères (code
ANSI ) que les applications en mode console(code OEM).
Il y a deux façons de résoudre le problème soit on utilise un éditeur
capable
d'écrire en mode OEM pour écrire le fichier source (par exemple avec wordpad
enregistrer en mode texte MS-DOS), soit on utilise la fonction
CharToOem(chaine_ansi,chaine_oem) et ensuite cout<<chaine_oem
Avatar
Loïc Joly
jean dupont wrote:
From: "Loïc Joly"



Quand je fais dans mon code un cout<< "éùàç" << endl; par défaut, ce
sont des caractères étranges qui s'affichent.





[...]

on utilise la fonction
CharToOem(chaine_ansi,chaine_oem) et ensuite cout<<chaine_oem



Effectivement, mais ça me semblait assez lourd d'utilisation. J'ai
finalement décidé de partir dans cette direction, mais en créant ma
propre classe qui fait ça tout seul. Je donne ici le code si certains en
veulent.

/**
* Exemple d'utilisation
*/

#include <iostream>
#include "WinConsoleStreamBuf.h"

using namespace std;

int main()
{
cout << "éèçàù" << endl; // Pas bon
loic::handleAccentsInMsWindowsConsole();
cout << "éèçàù" << endl; // Bon !
}

/**
* Fichier WinConsoleStreamBuf.h
*/

#include <streambuf>
#include <ostream>

#ifndef _WIN32
#error This file is only designed (and useful) on MsWindows
#endif

namespace loic
{

class WinConsoleStreamBuf: public std::streambuf
{
public:
explicit WinConsoleStreamBuf(std::streambuf *buf);
~WinConsoleStreamBuf();

private:
WinConsoleStreamBuf(WinConsoleStreamBuf &);
WinConsoleStreamBuf& operator=(WinConsoleStreamBuf&);
virtual std::streambuf* setbuf(char_type* s, std::streamsize n);

virtual int_type overflow(int_type c);
virtual int sync();

std::streambuf *myBuf;
};

void handleAccentsInMsWindowsConsole();
} // namespace loic


/**
* Fichier WinConsoleBuffer.cpp
*/

#include "WinConsoleStreamBuf.h"
#include <iostream>
#include <windows.h>

namespace loic
{

WinConsoleStreamBuf::WinConsoleStreamBuf(std::streambuf *buf):
myBuf(buf)
{
}

WinConsoleStreamBuf::~WinConsoleStreamBuf()
{
delete myBuf;
}

std::streambuf* WinConsoleStreamBuf::setbuf(char_type* s, std::streamsize n)
{
// ne fait rien, ce qui est autorisé. Une version plus complète
// devrait vraissemblablement utiliser setvbuf
return NULL;
}

WinConsoleStreamBuf::int_type WinConsoleStreamBuf::overflow(int_type c)
{
if (traits_type::eq_int_type(c, traits_type::eof()))
{
// la norme ne le demande pas exactement, mais si on nous passe eof
// la coutume est de faire la meme chose que sync()
return (sync() == 0
? traits_type::not_eof(c)
: traits_type::eof());
}
else
{
char charBuffer[2];
charBuffer[0] = static_cast<char>(c);
charBuffer[1] = 0;
char OEMBuffer[2];
CharToOem(charBuffer, OEMBuffer);
//std::cout << OEMBuffer;
myBuf->sputc(OEMBuffer[0]);
return true;
}
}

int WinConsoleStreamBuf::sync()
{
return myBuf->pubsync();
}


void handleAccentsInMsWindowsConsole()
{
std::cout.rdbuf(new WinConsoleStreamBuf(std::cout.rdbuf()));
}

} // namespace loic

--
Loïc
Avatar
Luc Hermitte
Loïc Joly wrote in
news:4174166a$0$31756$:

Effectivement, mais ça me semblait assez lourd d'utilisation. J'ai
finalement décidé de partir dans cette direction, mais en créant ma
propre classe qui fait ça tout seul. Je donne ici le code si certains
en veulent.



[snip buffer filtrant]



Normalement, il faudrait plutôt imbuer cin et cout avec la code_cvt facet
qui s'occuperait de tout cela.

Il y a pas mal de temps, j'avais posté une telle solution ici (voir
signature), mais elle était imparfaite pour la partie lecture sous VC 6.

L'approche par buffer filtrant semble résoudre tout cela. C'est bon à
savoir.

--
Luc Hermitte
http://hermitte.free.fr/Info/C++/locale.tar.gz
Avatar
Loïc Joly
Luc Hermitte wrote:

Loïc Joly wrote in
news:4174166a$0$31756$:


Effectivement, mais ça me semblait assez lourd d'utilisation. J'ai
finalement décidé de partir dans cette direction, mais en créant ma
propre classe qui fait ça tout seul. Je donne ici le code si certains
en veulent.




[snip buffer filtrant]




Normalement, il faudrait plutôt imbuer cin et cout avec la code_cvt facet
qui s'occuperait de tout cela.



Tiens, je n'ai pas regardé de ce côté.

Il y a pas mal de temps, j'avais posté une telle solution ici (voir
signature), mais elle était imparfaite pour la partie lecture sous VC 6.

L'approche par buffer filtrant semble résoudre tout cela. C'est bon à
savoir.



En fait, je me suis rendu compte après que j'avais oublié la partie cin.
Pour que ça marche, il faut aussi changer le buffer de cin, et ajouter
une fonction underflow :

WinConsoleStreamBuf::int_type WinConsoleStreamBuf::underflow()
{
// Assurance contre des implementations pas strictement conformes à la
// norme qui guaranti que le test est vrai. Cette guarantie n'existait
// pas dans les IOStream classiques.
if (gptr() == NULL || gptr() >= egptr())
{
int gotted = myBuf->sbumpc();
if (gotted == EOF)
{
return traits_type::eof();
}
else
{
char OEMBuffer[2];
OEMBuffer[0] = static_cast<char>(gotted);
OEMBuffer[1] = 0;
OemToChar(OEMBuffer, myInputBuffer);
setg(myInputBuffer, myInputBuffer, myInputBuffer+1);
return traits_type::to_int_type(*myInputBuffer);
}
}
else
{
return traits_type::to_int_type(*myInputBuffer);
}
}

--
Loïc
Avatar
Aurélien REGAT-BARREL
> J'ai finalement décidé de partir dans cette direction, mais en créant ma
propre classe qui fait ça tout seul. Je donne ici le code si certains en
veulent.


[snip]
class WinConsoleStreamBuf: public std::streambuf



J'avais tenté un truc du genre, mais en dérivant filebuf et en l'ouvrant sur
CONOUT$. Ca marche pas pour des caractères simples (peut être que overflow
en est la cause, je sais pas j'ai pas le niveau en C++ surtout pour les
flux) et c'est pas tout à fait correct dans la mesure où si cout a été
redirigé vers un fichier par exemple ça n'en tient pas compte à cause de
CONOUT$ qui vaut toujours la sortie console. Peut être qu'il y a un moyen
d'ouvrir un filebuf sur un HANDLE ?

#include <fstream>
#include <iostream>

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

template<class Elem, class Traits>
class oem_filebuf :
public std::basic_filebuf<Elem, Traits>
{
protected:
virtual std::streamsize xsputn(const Elem *Ptr, std::streamsize Count)
{
char * buff = new char[ Count + 1 ];
// copier avec le ''
::lstrcpy( buff, Ptr );
::CharToOem( buff, buff );
std::streamsize count std::basic_filebuf<Elem, Traits>::xsputn( buff, Count );
delete [] buff;
return count;
}
};

// object static utilisé pour modifier cout
struct InitOemCout
{
// code de modif dans le constructeur
InitOemCout()
{
// CONOUT$ = sortie console
this->oem.open( "CONOUT$", std::ios_base::out );
std::cout.rdbuf( &oem );
}
oem_filebuf<char, std::char_traits<char> > oem;
};

static InitOemCout init_oem_cout;


int main()
{
std::cout << "ça màrche héhé!n";
std::cout << 'è' << 'n'; // marche pas :-(
}

--
Aurélien REGAT-BARREL