Setconsolecp 1251 setconsoleoutputcp 1251 что это
Перейти к содержимому

Setconsolecp 1251 setconsoleoutputcp 1251 что это

Функция Сетконсолеаутпуткп

Задает выходную кодовую страницу, используемую консолью, связанной с вызывающим процессом. Консоль использует свою кодовую страницу вывода для преобразования символьных значений, записанных различными функциями вывода, в изображения, отображаемые в окне консоли.

Синтаксис

Параметры

вкодепажеид [in]
Идентификатор заданной кодовой страницы. Дополнительные сведения см. в подразделе «Примечания».

Возвращаемое значение

Если функция выполняется успешно, возвращается ненулевое значение.

Если функция выполняется неудачно, возвращается нулевое значение. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.

Комментарии

Кодовая страница сопоставляет коды символов 256 с отдельными символами. Разные кодовые страницы включают разные специальные символы, как правило, настроенные для языка или группы языков.

Если текущий шрифт является шрифтом в Юникоде фиксированной высоты, сетконсолеаутпуткп изменяет сопоставление символьных значений в наборе глифов шрифта вместо того, чтобы загружать отдельный шрифт при каждом вызове. Это влияет на то, как в окне консоли отображаются расширенные символы (значение ASCII, превышающее 127). Однако, если текущий шрифт является растровым шрифтом, сетконсолеаутпуткп не влияет на отображение расширенных символов.

Чтобы найти кодовые страницы, установленные или поддерживаемые операционной системой, используйте функцию енумсистемкодепажес . Идентификаторы кодовых страниц, доступных на локальном компьютере, также хранятся в реестре в следующем разделе:

Однако лучше использовать енумсистемкодепажес для перечисления кодовых страниц, так как реестр может отличаться в разных версиях Windows. Чтобы определить, является ли конкретная кодовая страница допустимой, используйте функцию исвалидкодепаже . Чтобы получить дополнительные сведения о кодовой странице, включая ее имя, используйте функцию жеткпинфоекс . Список доступных идентификаторов кодовых страниц см. в разделе идентификаторы кодовых страниц.

Чтобы определить текущую выходную кодовую страницу консоли, используйте функцию GetConsoleOutputCP . Чтобы задать и получить кодовую страницу входного кода консоли, используйте функции сетконсолекп и жетконсолекп .

Setconsolecp 1251 setconsoleoutputcp 1251 что это

БлогNot. Ещё раз про setlocale и SetConsoleCP/SetConsoleOutputCP в Studio.

Ещё раз про setlocale и SetConsoleCP/SetConsoleOutputCP в Studio.

Типовая проблема начинающих — «кракозябры» вместо кириллицы при разработке консольных приложений в MS Visual Studio.

Решения известны, но с ними тоже бывают нюансы. В частности, не надо мешать в одной программе setlocale — стандартную функцию из <clocale> и SetConsoleCP / SetConsoleOutputCP — пропиетарные функции от Microsoft из <windows.h> . Что они делают — одному микрософту известно, скорее всего, мешают работать setlocale 🙂

При этом, если указываем кодировку 1251, то при использовании микрософтовских функций необходимо выбрать в свойствах консоли шрифт Lucida Console, а для стандартной setlocale может и не помочь.

Методом научного тыка можно сделать такие выводы:

  • SetConsoleOutputCP() устанавливает кодировку вывода на консоль;
  • SetConsoleCP() устанавливает кодировку ввода из консоли и из редактора кода;
  • setlocale(LC_ALL,».1251″) проверяет, какая кодировка установлена сейчас, и если она не 1251, то меняет ее на 1251, а если уже 1251, то ничего не делает.

Поэтому, если уже установлена кодировка ввода из редактора функцией SetConsoleCP(1251) , то после неё setlocale() ничего менять не будет, и попросту выведет символы в кодировке CP866, решив, что они и так уже в windows 1251.

Если же уже выполнена функция SetConsoleOutputCP(1251) , то setlocale() проверит, какая кодировка ввода установлена, и обнаружит, что кодировка ввода по-прежнему CP866, поэтому она возьмет номера этих уже преобразованных символов (с помощью SetConsoleOutputCP(1251) ), но из кодовой таблицы cp866, и выведет символы с этими номерами из таблицы windows 1251 🙂

При этом, иногда мешать два способа всё же придётся. Например, если нужно обрабатывать ввод русских букв с помощью сишных функций проверки класса символов.

Вот такой код, при вводе русских букв, не будет корректно проверять, введена ли буква:

Символы кириллицы в консоли Windows

Ходят упорные слухи, что в Linux нет проблем с работой с кириллицей в консоли. Эта статья для тех, кому повезло меньше — для виндузятников.

Проблема заключается в том, что когда в Microsoft придумывали Windows, то попутно придумали новую кодировку для кириллицы. Трудно сказать зачем, но придумали. А старую кодировку, которая использовалась в MS DOS, оставили. Видимо в целях обратной совместимости. И случилась жопа. С выходом новых версий Windows ситуация только ухудшилась. Т.к. консоль, уже как часть операционной системы, унаследовала кодировку кириллицы от MS DOS.

В итоге сейчас для кириллицы имеем две кодировки: cp866 — старая досовская кодировка и cp1251 (она же windows-1251) — новая, от Windows. В настоящее время дело осложняется тем, что окончательно созрел Unicode, что дает еще несколько кодировок не совместимых с cp1251 и с cp866, и не совсем совместимых между собой. Но о Unicode как-нибудь в другой раз.

Кстати, буковки «cp» в названии кодировки означает codepage — кодовая страница в смысле «страница кодировки символов».

Кроме того, консоль имеет собственную настройку кодовой страницы. Для России по умолчанию — cp866. (Локализация самой винды, по видимому, роли не играет). Настройка кодовой страницы консоли может быть изменена командой chcp <номер кодовой страницы> .

Итак, при написании программ строки могут встречаться в двух различных кодировках в следующих местах:

  1. В исходных текстах программ в виде литералов.
  2. Вывод на консоль.
  3. Ввод с консоли.
  4. Вывод в файл.
  5. Ввод из файла.

Кроме того, винда при вводе и выводе кириллицы где-то в своих глубинах может делать некие преобразования кодировок, выдавая результаты, не поддающиеся расшифровке.

Первое правило при работе с национальными алфавитами: все строки должны быть в единой кодировке.

При несоблюдении этого правила будет невозможно сравнение и сортировка строк (а также и символов), и будет затруднён корректный ввод и вывод строк на консоль или в файл.

Еще один подводный камень:

В окне консоли, использующем растровые шрифты (Raster fonts), корректно отображается только кодовая страница оригинального производителя оборудования (OEM), установленная с Windows XP. Другие кодовые страницы отображаются корректно в полноэкранном режиме или в окне консоли, которое использует шрифты True Type.

Цитата из MS TechNet.

При этом в самой консоли отображение кириллицы при вводе (в командной строке) работает даже при использовании растровых шрифтов.

Второе правило при работе с национальными алфавитами: в настройках консоли установите для вывода шрифт True Type.

Сделать это можно следующим способом:

  1. Запустите командную строку
  2. Откройте контекстное меню и зайдите в настройки консоли
    Контекстное меню командной строки
  3. Измените шрифт на Lucida Console.
    Изменение шрифта консоли

И еще. Похоже, что ни Unicode, ни UTF-8, ни мультибайтовые строки в консоли напрямую не поддерживаются. По крайней мере, у меня с ними ничего путного не вышло.

Далее несколько советов для борьбы с этими проблемами.

Самый простой (и самый неудобный) способ

Работать в «родной» для консоли кодовой странице, в cp866. Т.е. все строки с кириллицей в исходном коде программы должны быть написаны в кодировке cp866. В этой же кодировке должны быть все входные файлы для программы. И в этой же кодировке будут и все выходные файлы. Полное впечатление, что мы вернулись на 20 лет назад, в MS DOS.

Если под рукой есть IDE, которая работает в консоли — особых проблем не возникнет. Если же использовать среду разработки под Windows GUI, то возникают вполне понятные сложности, поскольку IDE обычно работают в кодировке cp1251, «родной» для Windows. Кстати, как бы ни хаяли MS Visual Studio, она умеет работать с исходными текстами программ в различных кодировках, корректно их отображая в своем редакторе.

Вывод на консоль Windows 7

Способ подходит, если необходим только вывод кириллицы на консоль, и вы работаете под Windows 7. Под Windows XP это не работает (прим. редактора — все работает).

Самое простое — использовать функцию setlocale() :

Функция setlocale() устанавливает или изменяет для текущей программы информацию о национальной специфике (то, что задается в апплете Region and Language в Control panel). Описание функции можно найти в MSDN.

Также популярен урезанный вариант вызова:

Здесь используется, что символ LC_ALL равен 0 и подразумевается, что в операционной системе установлена страна пребывания Россия (локализация самой Винды роли не играет). Но лучше все-таки использовать полную форму.

Функция достаточно капризная. Это касается второго параметра. Некоторые значения, которые указаны в документации, могут на каких-то системах (компиляторах?) не работать.

Ввод и вывод на консоль

Для корректного ввода и вывода кириллицы на консоль надо использовать пару функций: SetConsoleOutputCP() и SetConsoleCP() . Описания в MSDN здесь и здесь соответственно.

В качестве единственного параметра обеим функциям передается номер кодовой страницы. В нашем случае (кириллица) — это 1251.

Этот способ работает и для Windows XP, и для Windows 7. Опробовано с Dev-C++ 5.6.3 (компилятор TDM-GCC 4.8.1 и MS Visual Studio 2012.

Следующая тестовая программа демонстрирует вывод кириллицы на консоль, ввод кириллической строки с консоли, контрольный вывод введенной строки, сравнение введенной строки с эталонной и вывод введенной строки в файл.

Исходный текст в кодировке cp1251:

Эта программа также удобна для экспериментов с различными кодовыми таблицами и их сочетаниями.

Для практических целей можно использовать шаблон:

Здесь я намеренно оставил закомментированный вызов setlocale(LC_ALL, «Russian»); . На ввод-вывод кириллицы он уже не влияет, но может потребоваться для других национальных настроек (разделитель дробной части числа, формат даты, времени и пр.)

Функции перекодировки

В Windows API есть две (а точнее, четыре пары) функции, осуществляющие перекодировку OEM <->ANSI (так сказано в документации). Проще говоря, в контексте рассматриваемого вопроса, это перекодировка между cp866 (OEM) и cp1251 (ANSI).

«Опасные» функции без контроля длины строки:

В качестве параметров получают указатели на входной и выходной буферы. Нулевой символ считается концом входной строки.

«Безопасные» функции с контролем длины строки:

В качестве параметров получают указатели на входной и выходной буферы и количество символов для входной строки. Нулевые символы не считаются концом строки. Преобразуется указанное количество символов.

На самом деле перечисленные функции являются макросами, которые раскрываются, к примеру для CharToOemBuff , в CharToOemBuffW (при поддержке Unicode) или в CharToOemBuffA (ANSI — без поддержки Unicode). Но о таких тонкостях обычно можно не вспоминать.

Эти функции полезны, когда вывод идёт в одной кодировке, а ввод — в другой. Такая ситуация складывается, например, при использовании только функции setlocale() : вывод осуществляется в cp1251, а ввод — в cp866. Следуя первому правилу, введенную строку надо преобразовать к cp1251. Для этого используется OemToCharBuff() .

Также эти функции могут быть использованы перед выводом строки в файл или после ввода строки из файла, в случае, если кодировки не совпадают.

P. S. Не судите строго — это мой первый опыт в написании статьи. Я так посмотрел, люди пишут, а чем я хуже? Тем более, что появилось чем поделиться. А оказалось, что это трудно. И написать, и ошибки проверить, и иллюстрации подготовить.

На написание статьи меня сподвиг вопрос о «кракозябрах в XP». Под это дело из руин даже был извлечен старый комп с XP. И оказалось, что проблема действительно имеет место. Пришлось провести небольшое исследование, результаты которого я здесь и изложил. Также скомпилировал доступную информацию по этой теме из материалов сайта, что бы все было в одном месте. Насколько у меня это получилось — решать вам. Буду рад замечаниям и дополнениям в комментариях к статье.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *