23

For example, if I write:

cout << "Привет!" << endl; //it's hello in Russian

In the console it would be something like ╧ЁштхЄ!.

OK, I know that we can use:

setlocale(LC_ALL, "Russian");

But after that, command line arguments in Russian do not work (if I start my program through a BAT file):

StartProgram.bat

chcp 1251
MyProgram.exe -user=Олег -password=Пароль

So, after setlocale the program can't read Russian arguments properly.

This happens because the BAT file in CP1251, but the console is in CP866.

So, there is a question:

How can I write Russian text in the C++ console and at the same time have Russian command line arguments read properly.

ctype.h
  • 1,470
  • 4
  • 20
  • 34
VextoR
  • 5,087
  • 22
  • 74
  • 109

8 Answers8

8

See this entry from Michael Kaplan's blog:

http://www.siao2.com/2008/03/18/8306597.aspx

Shog9
  • 156,901
  • 35
  • 231
  • 235
Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
5

Have you tried using wcout? It is similar to cout, but it accepts "wide" characters, which should permit the proper unicode encodings.

This article about localization, and another, both from MSDN may be of use.

Community
  • 1
  • 1
e.James
  • 116,942
  • 41
  • 177
  • 214
  • 2
    Unless I am completely mistaken, unicode will be a necessity for cyrillic. Regular 8-bit ASCII does not have glyphs for most of the characters in the cyrillic alphabet. The console output from your example (`╧ЁштхЄ`) is composed of some exotic 8-bit ASCII characters because the correct characters aren't available in that encoding. – e.James Feb 14 '10 at 17:11
  • 2
    Hmm.. Windows cyrillic is 1251 (Windows-1251) codepage. But DOS cyrillic uses 866 codepage. So, "Привет!" in CP1251 = "╧ЁштхЄ!" in CP866. This is what happened, I write in C++ as cp1251, but console shows it as cp866. – VextoR Feb 14 '10 at 17:22
  • Ah, the joys of character encodings :) – e.James Feb 14 '10 at 17:43
  • Don't forget if you're using wcout to put `L` in front of all your literals. Therefore, `wcout << L"Привет!" << endl;` in your example. – Billy ONeal Feb 14 '10 at 18:01
  • thanks, but this not working too, I think because I don't use Unicode – VextoR Feb 14 '10 at 18:13
  • @VextoR: start using it. Look at MichKap's blog again (see other link) - Microsoft "supports" 8 bit encodings for _legacy_ reasons. In particular, they are unlikely to change things, even when you'd consider them bugs - changing them would risk breaking the old programs, without any benefit for the newer Unicode apps. – MSalters Feb 15 '10 at 12:31
3

Console set to be in 1251 instead of in 866:

 //Save As Windows 1251
    #include<stdio.h>
    #include<windows.h>
    int main(int argc, char **argv){ 
        SetConsoleOutputCP(1251);
        SetConsoleCP(1251);
        if(argc<2)return 0;
        else printf("Hello %s %s\n",argv[1],argv[2]);
    } 

Program is argument.exe and result:

D:\Debug>argument Олег Пароль
Hello Олег Пароль

vladasimovic
  • 310
  • 3
  • 5
1

You can try using the following functions setlocale() and SetConsoleOutputCP()

setlocale(LC_ALL, "Russian");
SetConsoleOutputCP(866);
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
kruk
  • 27
  • 1
1

For me this seems to resolve the problem:

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

using namespace std;

int main(void) {
    _setmode(_fileno(stdout), _O_U16TEXT);
    wcout << L"Огњен" << endl;
    return 0;
}
0

Have you set the language for non-unicode programs to be Russian, in the Regional and Language Options section of the Control Panel?

(I have no idea what the usual setup for Russian-speaking programmers might be; I just wonder whether it is common to set this to some kind of English to avoid confusing overly-parochial tools.)

Unless my memory is playing tricks, when I was working with some code from Japanese developers it was this step that got the console displaying non-Unicode Japanese text (Shift-JIS encoding) properly.

0

WriteConsoleW can handle UNICODE e.g. Cyrillic letters without problems. If you won’t miss the formatting features of wcout, you can redirect the standard wcout stream buffer and print it with WriteConsoleW.

A full example is shown here

// save and redirect cout buffer
wostringstream  newCoutBuffer;
wstreambuf*     oldCoutBuffer = wcout.rdbuf(newCoutBuffer.rdbuf());    

// do your wcout stuff here
// do your wcout stuff here

DWORD dwWritten;
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), newCoutBuffer.str().c_str(),newCoutBuffer.tellp(),&dwWritten,NULL);  

// restore cout buffer
wcout.rdbuf(oldCoutBuffer);
Community
  • 1
  • 1
seizu
  • 477
  • 4
  • 9
-1

The most correct way is using wcout + std::imbue.

But one should know that there was some changes in setlocale API which happened in Windows Vista/7. "Russian" locale string isn't recognized as "cp866" anymore, at least in Visual C++ CRT.

To get cp866 output, try use this instead:

::setlocale( LC_ALL , "russian_russia.866" );
Yury Rumega
  • 220
  • 1
  • 12