Страницы

Поиск по вопросам

четверг, 6 декабря 2018 г.

Русский язык в исходном коде в Dev C++ [дубликат]

На данный вопрос уже ответили: Русский язык в консоли 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 #include #include #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 // русский текст в кодировке cp1251 (она же ANSI) // обратите внимание, не нужен
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». Потом подтверждаете, что попросит.
Если при подтверждении выбрать пункт «Изменить ярлык для запуска этого окна», то новые окна командной строки будут уже с нужным шрифтом.
Вроде все.

Комментариев нет:

Отправить комментарий