На данный вопрос уже ответили:
Русский язык в консоли
3 ответа
Я недавно начал изучать С++, у меня есть компилятор Dev C++. Когда я делаю
std::cout<<"Привет!";
то получается абракадабра! А если перебираю символы циклом, то русские буквы отображаются правильно. Я думаю проблема в различии кодировок dos и windows. Кто знает какие-нибудь примочки для Dev C++ (типа keycyr для pascal) или операторы/функции/процедуры C++ позволяющие сменить кодировку std::cout.
Ответ
С setlocale() по науке правильно, но если локализация кривовата (как у меня на этой машине), то не работает.
В Windows есть 2 функции, CharToOem(char, char) и OemToChar(char, char) для перевода cp-1251 в cp-866 (консоль) и обратно.
Пример:
#include
main ()
{
char str[1000], buf[1000];
int itty = isatty(fileno(stdin)),
otty = isatty(fileno(stdout));
strcpy(str, "привет");
if(otty)
CharToOem(str, str);
puts(str);
fgets(str, 1000, stdin);
if (itty)
OemToChar(str, str);
str[strlen(str) - 1] = `\0`;
if (strstr("привет", str))
strcpy(buf, "да, часть от 'привет'");
else
strcpy(buf, "такого нет в слове 'привет'");
if(otty)
CharToOem(buf, buf);
puts(buf);
}
В программе набрано в cp-1251 (она же ANSI).
При вводе с консоли, независимо от setlocale() придется переводить кодировку. Также обратите внимание, что параметры командной строки, набранные в консоли поступают в программу в кодировке cp-1251!!!
Кодировка в файлах обычно подразумевается в cp-1251, это надо учитывать при переадресации (>) вывода (stdout, stderr). Я продемонстрировал в примере, как это можно делать.
UPDATE
@insolor дал замечательный ответ как правильно программировать работу с
русскими буквами в консоли Windows, используя стандартные функции
SetConsoleCP(1251) и SetConsoleOutputCP(1251)
В обсуждении (комментариях) к его ответу можно найти различные детали,
в частности установку русского шрифта.
Похоже его ответ прошел незамеченным для некоторых участников форума.
Поэтому я решил привести функцию, вызов которой в самом начале упрощает
программирование ввода/вывода русских букв в Windows и пример
ее использования.
cons1251.c
#include
static int oldin = 0, oldout = 0;
static void exitfunc()
{
SetConsoleCP(oldin);
SetConsoleOutputCP(oldout);
}
void cons1251 ()
{
if (oldin)
return;
atexit(exitfunc);
oldin = GetConsoleCP();
oldout = GetConsoleOutputCP();
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
}
rustest.c
#include
main()
{
printf ("This is russian [аБвГдЕ] before cons1251()
");
cons1251();
printf ("This is russian [аБвГдЕ] after cons1251()
");
char str[1000], buf[1000];
printf ("Привет - введи часть от \"привет\"
"); fflush(stdout);
fgets(str,1000,stdin);
str[strlen(str)-1] = 0;
printf("Вы ввели: '%s'
",str);
if(strstr("привет",str))
printf("да, часть от 'привет'
");
else
printf("такого нет в слове 'привет'
");
fflush(stdout);
puts("ждем ввода to exit..."); fflush(stdout);
fgets(str,1000,stdin);
}
Вызов fflush(stdout) при работе с консолью (tty) необязателен, однако для вывода в некоторых эмуляторах терминала (например в Emacs eshell) необходим.
Это пример компиляции (Windows 7, Emacs eshell) окно в cp1251 поэтому вывод русского текста и до и после cons1251() одинаковый (и правильный).
c:/Users/avp/src/cc/hashcode $ gcc -c cons1251.c
c:/Users/avp/src/cc/hashcode $ gcc rustest.c cons1251.o -o rustest
c:/Users/avp/src/cc/hashcode $ ./rustest
This is russian [аБвГдЕ] before cons1251()
This is russian [аБвГдЕ] after cons1251()
Привет - введи часть от "привет"
иве
Вы ввели: 'иве'
да, часть от 'привет'
ждем ввода to exit...
c:/Users/avp/src/cc/hashcode $
c:/Users/avp/src/cc/hashcode $
К сожалению для стандартного cmd-окошка Copy/Paste не работает, так что попробуйте сами.
Для окна с PowerShell в Win 7 этот метод к сожалению не работает (в отличие от «геморройного» CharToOem/OemToChar).
Надеюсь этот текст окажется кому-то полезным.
UPDATE 2 (for @Rules)
Исходный файл tt.cpp
#include
extern "C" void cons1251(void);
main()
{
std::cout << "Привет, введите слово
";
cons1251();
std::cout << "Привет, введите слово
";
char str[100];
std::cin >> str;
std::cout << "Вы ввели: " << str << std::endl;
}
c:/Documents and Settings/avp/src/hashcode $ g++ tt.cpp cons1251.o -o tt
c:/Documents and Settings/avp/src/hashcode $ ./tt
Привет, введите слово
Привет, введите слово
йцукен
Вы ввели: йцукен
c:/Documents and Settings/avp/src/hashcode $
Пример вывода из эмулятора терминала Emacs eshell. Поэтому первый «Привет...» тоже состоит из нормальных букв. В обычной консоли там «кракозябры», а дальше нормальная кириллица.
Обращаю особое внимание. Перед запуском надо изменить шрифт в консоли на Lucida Console. Иначе будут кракозябры (но другие). Для замены шрифта кликаете правой кнопкой на надписи «Командная строка» окна консоли. В открывшемся меню выбираете «Свойства». В появившемся окне выбираете вкладку «Шрифт» и там выбираете «Lucida Console». Потом подтверждаете, что попросит.
Если при подтверждении выбрать пункт «Изменить ярлык для запуска этого окна», то новые окна командной строки будут уже с нужным шрифтом.
Вроде все.
Комментариев нет:
Отправить комментарий