Ответ 1
Смотрите эту запись в блоге Майкла Каплана:
Например, если я пишу:
cout << "Привет!" << endl; //it hello in Russian
В консоли это будет что-то вроде ╧ЁштхЄ!
.
Хорошо, я знаю, что мы можем использовать:
setlocale(LC_ALL, "Russian");
Но после этого аргументы командной строки на русском языке не работают (если я запускаю свою программу через файл BAT):
StartProgram.bat
chcp 1251
MyProgram.exe -user=Олег -password=Пароль
Итак, после setlocale
программа не может правильно прочитать русские аргументы.
Это происходит из-за того, что файл BAT в CP1251, но консоль находится в CP866.
Итак, возникает вопрос:
Как писать русский текст на консоли С++ и в то же время правильно читать аргументы командной строки.
Смотрите эту запись в блоге Майкла Каплана:
Пробовали ли вы использовать wcout
? Он похож на cout
, но он принимает "широкие" символы, что должно допускать правильные кодировки в кодировке unicode.
Эта статья о локализации и еще, оба из MSDN могут быть полезны.
Вы можете попробовать использовать следующие функции setlocale()
и SetConsoleOutputCP()
setlocale(LC_ALL, "Russian");
SetConsoleOutputCP(866);
Консоль установлена в 1251 вместо 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]);
}
Программа - аргумент .exe и результат:
D:\Debug > аргумент Олег пароль
Здравствуйте, Олег пароль
Установили ли вы, что язык для программ, отличных от юникода, является русским, в разделе "Язык и региональные стандарты" на панели управления?
(я понятия не имею, что такое обычная установка для русскоязычных программистов, я просто задаюсь вопросом, распространено ли это на каком-то английском языке, чтобы избежать путаницы чрезмерно ограниченных инструментов.)
Если моя память не играет в трюки, когда я работал с некоторым кодом от японских разработчиков, именно этот шаг заставил консоль правильно отображать японский текст не Unicode (Shift-JIS-кодирование).
WriteConsoleW может обрабатывать UNICODE, например. Кириллические буквы без проблем. Если вы не пропустите функции форматирования wcout, вы можете перенаправить стандартный буфер wcout и напечатать его с помощью WriteConsoleW.
// 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);
Наиболее правильным способом является использование wcout + std:: imbue.
Но следует знать, что в API-интерфейсе setlocale произошли некоторые изменения, которые произошли в Windows Vista/7. "Русская" языковая строка больше не распознается как "cp866", по крайней мере, в Visual С++ CRT.
Чтобы получить выход cp866, попробуйте использовать это вместо:
::setlocale( LC_ALL , "russian_russia.866" );
Для меня это, похоже, решает проблему:
#include <fcntl.h>
#include <io.h>
#include <iostream>
using namespace std;
int main(void) {
_setmode(_fileno(stdout), _O_U16TEXT);
wcout << L"Огњен" << endl;
return 0;
}