Unicode character Visual C++

2020-03-31 10:21发布

问题:

I'm trying to make my program work with unicode characters. I'm using Visual Studio 2010 on a Windows 7 x32 machine.

What I want to print is the queen symbol ("\ul2655") and it just doesn't work. I've set my solution to use unicode.

This is my sample code:

 #include <iostream>
 using namespace std;

 int main()
 {
    SetConsoleOutputCP(CP_UTF8);
    wcout << L"\u2655";

    return 0;
 }

Also, I've tried many other suggestions, but nothing worked. (eg. change the cmd font, apply chcp 65001, which is the same as SetConsoleOutputCP(CP_UTF8), etc).

What is the problem? It's for the first time I encounter such a situation. On linux, it's different.

Thank you.

回答1:

Once I managed to print chess pieces on the console; there are several complexities involved here.

First of all, you have to enable UTF-16 mode on stdout; this is described here as well as here, and it's exactly as Mehrdad explained.

#include <io.h>
#include <fcntl.h>

...

_setmode(_fileno(stdout), _O_U16TEXT);

Then, even if the output reached the console correctly, on the console you may get garbage instead of the intended characters; this comes form the fact that, at least on my machine (Windows 7), the default console font doesn't support the chess pieces glyphs.

To fix this, you have to choose a different TrueType font which supports them, but to make such a font available you have to go through some hoops; personally, I found out that DejaVu Sans Mono works just fine.

So, at this point, your code should work, and code like this (the example I wrote in the past to test this issue):

#include <wchar.h>
#include <stdio.h>
#include <locale.h>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif

enum ChessPiecesT
{
    King,
    Queen,
    Rock,
    Bishop,
    Knight,
    Pawn,
};

enum PlayerT
{
    White=0x2654,   /* white king */
    Black=0x265a,   /* black king */
};

/* Provides the character for the piece */
wchar_t PieceChar(enum PlayerT Player, enum ChessPiecesT Piece)
{
    return (wchar_t)(Player + Piece);
}

/* First row of the chessboard (black) */
enum ChessPiecesT TopRow[]={Rock, Knight, Bishop, Queen, King, Bishop, Knight, Rock};

void PrintTopRow(enum PlayerT Player)
{
    int i;
    for(i=0; i<8; i++)
        putwchar(PieceChar(Player, TopRow[Player==Black?i: (7-i)]));
    putwchar(L'\n');
}

/* Prints the eight pawns */
void PrintPawns(enum PlayerT Player)
{
    wchar_t pawnChar=PieceChar(Player, Pawn);
    int i;
    for(i=0; i<8; i++)
        putwchar(pawnChar);
    putwchar(L'\n');
}

int main()
{
#ifdef _WIN32
    _setmode(_fileno(stdout), _O_U16TEXT);
#else
    setlocale(LC_CTYPE, "");
#endif
    PrintTopRow(Black);
    PrintPawns(Black);
    fputws(L"\n\n\n\n", stdout);
    PrintPawns(White);
    PrintTopRow(White);
    return 0;
}

should work equally well on Windows and Linux.

Now you still have a problem: the glyphs will be too small to be meaningful in any way:

this can be solved only by enlarging the console font, but you'd get all the other characters to be way too big to be usable. Thus, all in all, probably the best fix is just to write a GUI application.



回答2:

Try this instead

_setmode(_fileno(stdout), _O_U16TEXT);