Setconsolecp 1251 setconsoleoutputcp 1251 что это
Различие функций setlocale() и SetConsoleCP()/SetConsoleOutputCP()
Не работают функции SetConsoleCP() и SetConsoleOutputCP()
Необходимо сделать так, чтобы программа воспринимала кириллицу в потоках ввода и вывода (setlocale.
Setlocale vs. SetConsoleCP
В чём разница? Локаль определяет, в какой кодировке символы представляются в программе, а.
Вам не понять всю любовь и идеологию шиндоуз, особенно по части кодировок. Добавлено через 13 часов 1 минуту если вывести на экран через SetConsoleCP, кстати я так понимаю что кодировку консоли нужно вернуть назад? как то получается что если ничего не делать то в консоли одно, в файле другое. если все отключить то кириллица есть, но не там. но экспорт в тхт остаётся в ascii-1251 команда setlocale(LC_ALL, «Russian»); даёт плохой результат причем равный setlocale(LC_ALL, «.1251»); Учу C++ по книжке Страуструпа, не выводятся русские символы. Вот код: В Code::Blocks всё работает и без крякозяблов. Даже без setlocale. Для данной задачи существует множество решений. Если вам нужно быстрое и не обязательно универсальное решение, чтобы сильно не разбираться, прокручивайте к разделу «Менее правильные, но пригодные решения». Для начала, проблема у консоли Windows состоит в том, что её шрифты, которые стоят «по умолчанию», показывают не все символы. Вам следует сменить шрифт консоли на юникодный, это позволит работать даже на английской Windows. Если вы хотите поменять шрифт только для вашей программы, в её консоли нажмите на иконку в левом верхнем углу → Свойства → Шрифт. Если хотите поменять для всех будущих программ, то же самое, только заходите в Умолчания, а не Свойства. Дальнейшее рассмотрение касается лишь Microsoft Visual Studio. Если у вас другой компилятор, пользуйтесь предложенными на свой страх и риск, никакой гарантии нету. Настроив среду, перейдём к решению собственно задачи. (Ещё одна проблема, которую решает использование широких строк: узкие строки при компиляции кодируются в однобайтную кодировку используя текущую системную кодовую страницу, то есть, ANSI-кодировку. Если вы компилируете вашу программу на английской Windows, это приведёт к очевидным проблемам.) Вам нужно _setmode(_fileno(. ), _O_U16TEXT); для переключения режима консоли: Такой способ должен работать правильно с вводом и выводом, с именами файлов и перенаправлением потоков. Если очень не хочется переходить на Unicode, и использовать однобайтную кодировку, будут возникать проблемы. Для начала, символы, не входящие в выбранную кодировку (например, для случая CP1251 — базовый английский и кириллица), работать не будут, вместо них будет вводиться и выводиться абракадабра. Кроме того, узкие строковые константы имеют ANSI-кодировку, а это значит, что кириллические строковые литералы на нерусской системе не сработают (в них будет зависимая от системной локали абракадабра). Держа в голове эти проблемы, переходим к изложению следующей серии решений. В любом случае, поставьте юникодный шрифт в консоли. (Это первый абзац «сложного» решения.) Убедитесь, что ваши исходники в кодировке CP 1251 (это не само собой разумеется, особенно если у вас не русская локаль Windows). Если при добавлении русских букв и сохранении Visual Studio ругается на то, что не может сохранить символы в нужной кодировке, выбирайте CP 1251. (1) Если компьютер ваш, вы можете поменять кодовую страницу консольных программ на вашей системе. Для этого сделайте вот что: Преимущества способа: примеры из книг начнут работать «из коробки». Недостатки: смена реестра может повлечь за собой проблемы, кодировка консоли меняется глобально и перманентно — это может повлиять сломать другие программы. Плюс эффект будет только на вашем компьютере (и на других, у которых та же кодировка консоли). Плюс общие проблемы неюникодных способов. (2) Вы можете поменять кодировку только вашей программы. Для этого нужно сменить кодировку консоли программным путём. Из вежливости к другим программам не забудьте потом вернуть кодировку на место! Это делается либо при помощи вызова функций в начале программы, либо про помощи вызова внешней утилиты (То есть, у вас должно получиться что-то вроде и дальше обыкновенный код программы.) Можно обернуть эти вызовы в класс, чтобы воспользоваться плюшками автоматического управления временем жизни объектов C++. (если выполняете задание из Страуструпа можно вставить в конец заголовочного файла std_lib_facilities.h ) Если вам нужен не русский, а какой нибудь другой язык, просто замените 1251 на идентификатор нужной кодировки (список указан ниже в файле), но, разумеется, работоспособность не гарантируется. Остались методы, которые тоже часто встречаются, приведём их для полноты. Метод, который часто рекомендуют — использование конструкции setlocale(LC_ALL, «Russian»); У этого варианта (по крайней мере в Visual Studio 2012) гора проблем. Во-первых, проблема с вводом русского текста: введённый текст передаётся в программу неправильно! Нерусский текст (например, греческий) при этом вовсе не вводится с консоли. Ну и общие для всех неюникодных решений проблемы. Поэтому стоит хранить исходники в Unicode (например, UTF-8). Причем сохранить следует с сигнатурой Ситуацию частично спасает пересохранение исходников в кодировке UTF-8 с обязательным символом BOM, без него Visual Studio начинает интерпретировать «широкие» строки с кириллицей весьма своеобразно. Однако, указав BOM (Byte Order Mark — метка порядка байтов) кодировки UTF-8 — символ, кодируемый тремя байтами 0xEF, 0xBB и 0xBF, мы получаем узнавание кодировки UTF-8 в любой системе Стоит пояснить кое-что для тех, кто ищет правильный ответ по поводу функции setlocale: Метод, который часто рекомендуют — использование конструкции setlocale(LC_ALL, «Russian»); У этого варианта (по крайней мере в Visual Studio 2012) гора проблем. Во-первых, проблема с вводом русского текста: введённый текст передаётся в программу неправильно! Нерусский текст (например, греческий) при этом вовсе не вводится с консоли. Ну и общие для всех неюникодных решений проблемы. Я добавлю по этому методу побольше информации: Его вообще не правильно рекомендуют! Начнём с первого: Во втором параметре функция принимает не название страны или языка, хотя в некоторых случаях она сработает, а языковый идентификатор, согласно ISO 3166-1. Поэтому правильно и корректно указывать: «ru-RU». Теперь второе: в документации к этой функции написано чёрным по белому: «If execution is allowed to continue, the function sets errno to EINVAL and returns NULL.» Что буквально толкуется: при возникновении ошибки, функция устанавливает значение переменной errno в EINVAL и возвращает NULL. В случае возникновения ошибки, errno всегда будет равен EINVAL, что означает: не верный аргумент. Поэтому её проверять нет смысла, а вот исполнение функции должно быть проверено. Поэтому правильный вызов функции setlocale выглядит следующим образом: И не забывайте, что setlocale устанавливает локальную таблицу только для ANSI кодировки, поэтому и не будут отображаться греческие, испанские, китайские и даже японские знаки. Для русского языка это будет таблица номер 1251. И важно: почему эта функция является надёжней, нежели прямая установка таблицы символов через SetConsoleCP, ибо потому, что она переключает все внутренние надстройки именно для раскладки под язык. Начиная от стандарта отображения даты, заканчивая знаками разделителя. И да, не стоит устанавливать языковый указатель виде «ru», так как в зависимости от сборки самой ось и имеющихся языковых пакетов, может установиться ru-BY, ru-UA, ru-MO и другие языковые стандарты, значительно отличающиеся от ru-RU. И категорично нельзя указывать «Russia», «Russian», «Russian Federation» (да, такую вакханалию уже встречал пару раз). Хотя функция производит проверку и по названию региона, не всегда в таблице локализации это указано, или может быть указано «Россия» или «Русский» уже на нашей раскладке. Это и есть основная ошибка, из-за которой функция setlocale зачастую отказывается работать. И да, для приложения, работающего в режиме юникогда, стоит использовать функцию _wsetlocale. Она идентична, и также устанавливает базовые настройки для локализации. Кроме того, если проект приложения в Visual Studio настроен в режим юникода, то и будет работать только _wsetlocale, так как setlocale, по документации, не приспособлена к работе с юникодом вообще никак. Совсем забыл указать, что функция setlocale и _wsetlocale, в случае успеха вернёт именно идентификатор региона. То есть, в нашем случае строку «ru_RU\0». Ходят упорные слухи, что в Linux нет проблем с работой с кириллицей в консоли. Эта статья для тех, кому повезло меньше — для виндузятников. Проблема заключается в том, что когда в Microsoft придумывали Windows, то попутно придумали новую кодировку для кириллицы. Трудно сказать зачем, но придумали. А старую кодировку, которая использовалась в MS DOS, оставили. Видимо в целях обратной совместимости. И случилась жопа. С выходом новых версий Windows ситуация только ухудшилась. Т.к. консоль, уже как часть операционной системы, унаследовала кодировку кириллицы от MS DOS. В итоге сейчас для кириллицы имеем две кодировки: cp866 — старая досовская кодировка и cp1251 (она же windows-1251) — новая, от Windows. В настоящее время дело осложняется тем, что окончательно созрел Unicode, что дает еще несколько кодировок не совместимых с cp1251 и с cp866, и не совсем совместимых между собой. Но о Unicode как-нибудь в другой раз. Кстати, буковки «cp» в названии кодировки означает codepage — кодовая страница в смысле «страница кодировки символов». Итак, при написании программ строки могут встречаться в двух различных кодировках в следующих местах: Кроме того, винда при вводе и выводе кириллицы где-то в своих глубинах может делать некие преобразования кодировок, выдавая результаты, не поддающиеся расшифровке. Первое правило при работе с национальными алфавитами: все строки должны быть в единой кодировке. При несоблюдении этого правила будет невозможно сравнение и сортировка строк (а также и символов), и будет затруднён корректный ввод и вывод строк на консоль или в файл. Еще один подводный камень: В окне консоли, использующем растровые шрифты (Raster fonts), корректно отображается только кодовая страница оригинального производителя оборудования (OEM), установленная с Windows XP. Другие кодовые страницы отображаются корректно в полноэкранном режиме или в окне консоли, которое использует шрифты True Type. При этом в самой консоли отображение кириллицы при вводе (в командной строке) работает даже при использовании растровых шрифтов. Второе правило при работе с национальными алфавитами: в настройках консоли установите для вывода шрифт True Type. Сделать это можно следующим способом: И еще. Похоже, что ни Unicode, ни UTF-8, ни мультибайтовые строки в консоли напрямую не поддерживаются. По крайней мере, у меня с ними ничего путного не вышло. Далее несколько советов для борьбы с этими проблемами. Работать в «родной» для консоли кодовой странице, в cp866. Т.е. все строки с кириллицей в исходном коде программы должны быть написаны в кодировке cp866. В этой же кодировке должны быть все входные файлы для программы. И в этой же кодировке будут и все выходные файлы. Полное впечатление, что мы вернулись на 20 лет назад, в MS DOS. Если под рукой есть IDE, которая работает в консоли — особых проблем не возникнет. Если же использовать среду разработки под Windows GUI, то возникают вполне понятные сложности, поскольку IDE обычно работают в кодировке cp1251, «родной» для Windows. Кстати, как бы ни хаяли MS Visual Studio, она умеет работать с исходными текстами программ в различных кодировках, корректно их отображая в своем редакторе. Способ подходит, если необходим только вывод кириллицы на консоль, и вы работаете под Windows 7. Под Windows XP это не работает (прим. редактора — все работает). Самое простое — использовать функцию setlocale() : Функция setlocale() устанавливает или изменяет для текущей программы информацию о национальной специфике (то, что задается в апплете Region and Language в Control panel). Описание функции можно найти в MSDN. Также популярен урезанный вариант вызова: Здесь используется, что символ LC_ALL равен 0 и подразумевается, что в операционной системе установлена страна пребывания Россия (локализация самой Винды роли не играет). Но лучше все-таки использовать полную форму. Функция достаточно капризная. Это касается второго параметра. Некоторые значения, которые указаны в документации, могут на каких-то системах (компиляторах?) не работать. В качестве единственного параметра обеим функциям передается номер кодовой страницы. В нашем случае (кириллица) — это 1251. Этот способ работает и для Windows XP, и для Windows 7. Опробовано с Dev-C++ 5.6.3 (компилятор TDM-GCC 4.8.1 и MS Visual Studio 2012. Следующая тестовая программа демонстрирует вывод кириллицы на консоль, ввод кириллической строки с консоли, контрольный вывод введенной строки, сравнение введенной строки с эталонной и вывод введенной строки в файл. Исходный текст в кодировке cp1251: Эта программа также удобна для экспериментов с различными кодовыми таблицами и их сочетаниями. Для практических целей можно использовать шаблон: В Windows API есть две (а точнее, четыре пары) функции, осуществляющие перекодировку OEM ANSI (так сказано в документации). Проще говоря, в контексте рассматриваемого вопроса, это перекодировка между cp866 (OEM) и cp1251 (ANSI). «Опасные» функции без контроля длины строки: В качестве параметров получают указатели на входной и выходной буферы. Нулевой символ считается концом входной строки. «Безопасные» функции с контролем длины строки: В качестве параметров получают указатели на входной и выходной буферы и количество символов для входной строки. Нулевые символы не считаются концом строки. Преобразуется указанное количество символов. Также эти функции могут быть использованы перед выводом строки в файл или после ввода строки из файла, в случае, если кодировки не совпадают. P. S. Не судите строго — это мой первый опыт в написании статьи. Я так посмотрел, люди пишут, а чем я хуже? Тем более, что появилось чем поделиться. А оказалось, что это трудно. И написать, и ошибки проверить, и иллюстрации подготовить. На написание статьи меня сподвиг вопрос о «кракозябрах в XP». Под это дело из руин даже был извлечен старый комп с XP. И оказалось, что проблема действительно имеет место. Пришлось провести небольшое исследование, результаты которого я здесь и изложил. Также скомпилировал доступную информацию по этой теме из материалов сайта, что бы все было в одном месте. Насколько у меня это получилось — решать вам. Буду рад замечаниям и дополнениям в комментариях к статье. Sets the output code page used by the console associated with the calling process. A console uses its output code page to translate the character values written by the various output functions into the images displayed in the console window. wCodePageID [in] If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError. A code page maps 256 character codes to individual characters. Different code pages include different special characters, typically customized for a language or a group of languages. If the current font is a fixed-pitch Unicode font, SetConsoleOutputCP changes the mapping of the character values into the glyph set of the font, rather than loading a separate font each time it is called. This affects how extended characters (ASCII value greater than 127) are displayed in a console window. However, if the current font is a raster font, SetConsoleOutputCP does not affect how extended characters are displayed. To find the code pages that are installed or supported by the operating system, use the EnumSystemCodePages function. The identifiers of the code pages available on the local computer are also stored in the registry under the following key: However, it is better to use EnumSystemCodePages to enumerate code pages because the registry can differ in different versions of Windows. To determine whether a particular code page is valid, use the IsValidCodePage function. To retrieve more information about a code page, including its name, use the GetCPInfoEx function. For a list of available code page identifiers, see Code Page Identifiers. To determine a console’s current output code page, use the GetConsoleOutputCP function. To set and retrieve a console’s input code page, use the SetConsoleCP and GetConsoleCP functions. Данный материал не предлагает строгий алгоритм действий, а направлен на описание узловых проблем, с которыми неизбежно сталкивается разработчик локализованного консольного приложения, а также некоторые возможные пути их разрешения. Предполагается, что это позволит разработчику сформировать стратегию работы с локализованной консолью и эффективно реализовать существующие технические возможности, большая часть которых хорошо описана и здесь опущена. В общем случае функции консоли таковы: управление операционной системой и системным окружением приложений на основе применения стандартных системных устройств ввода-вывода (экран и клавиатура), использования команд операционной системы и/или собственно консоли; запуск приложений и обеспечение их доступа к стандартным потокам ввода-вывода системы, также с помощью стандартных системных устройств ввода-вывода. Отдельным видом консоли можно считать консоль отладки Visual Studio (CMD-D ). Совет 1. Выполнять разработку текстовых файлов (программных кодов, текстовых данных и др.) исключительно в кодировке UTF-8. Мир любит Юникод, а кроссплатформенность без него вообще невозможна. Совет 2. Периодически проверять кодировку, например в текстовом редакторе Notepad++. Visual Studio может сбивать кодировку, особенно при редактировании за пределами VS. Поскольку в консоли постоянно происходит передача управления от приложений к собственно командному процессору и обратно, регулярно возникает «конфликт кодировок», наглядно иллюстрируемый таблица 1 и 2, сформированных следующим образом: Команды и код приложения под катом > Echo ffffff фффффф // в командной строке PS> Echo ffffff фффффф // в PowerShell код тестового приложения: Командную часть задания все консоли локализовали практически без сбоев во всех кодировках, за исключением: в WPS неверно отображена русскоязычная часть команды во всех кодировках. Табл. 1. Результат выполнения команды консоли Echo ffffff фффффф Вывод тестового приложения локализован лишь в 50% испытаний, как показано в табл.2. Табл. 2. Результат запуска приложения LoggingConsole.Test Сoвет 3. Про PowerShell забываем раз и навсегда. Ну может не навсегда, а до следующей мажорной версии. По умолчанию Windows устанавливает для консоли кодовые страницы DOS. Чаще всего CP437, иногда CP866. Актуальные версии командной строки cmd.exe способны локализовать приложения на основе русифицированной кодовой страницы 866, но не 437, отсюда и изначальный конфликт кодировок консоли и приложения. Поэтому Отдельной опцией Visual Studio является встроенная односеансная консоль отладки, которая перехватывает команду Visual Studio на запуск приложения, запускается сама, ожидает компиляцию приложения, запускает его и отдает ему управление. Таким образом, отладочная консоль в течение всего рабочего сеанса находится под управлением приложения и возможность использования команд Windows или самой консоли, включая команду CHCP, не предусмотрена. Более того, отладочная консоль не воспринимает кодовую страницу по умолчанию, определенную в реестре, и всегда запускается в кодировке 437 или 866. Совет 6. Тестирование приложения целесообразно выполнять во внешних консолях, более дружелюбных к локализации. Ниже приведен пример вывода тестового приложения в консоль, иллюстрирующий изложенное. Метод Write получает номера текущих страниц, устанавливает новые кодовые страницы вводного и выводного потоков, выполняет чтение с консоли и записывает выводную строку, содержащий русский текст, в том числе считанный с консоли, обратно в консоль. Операция повторяется несколько раз для всех основных кодовых страниц, упомянутых ранее. приложение запущено в консоли с кодовыми страницами 1251 (строка 2); приложение меняет кодовые страницы консоли (current, setted); приложение остановлено в консоли с кодовыми страницами 1252 (строка 11, setted); Приложение адекватно локализовано только в случае совпадения текущих кодовых страниц консоли (setted 1251:1251) с начальными кодовыми страницами (строки 8 и 10). Код тестового приложения под катом Совет 7. Обязательный и повторный! Функции SetConsoleCP должны размещаться в коде до первого оператора ввода-вывода в консоль. Удалить приложение PowerShell (если установлено), сохранив Windows PowerShell; Установить в качестве кодовую страницу консоли по умолчанию CP65001 (utf-8 Unicode) или CP1251 (Windows-1251-Cyr), см. совет 5; Разработку приложений выполнять в кодировке utf-8 Unicode; Контролировать кодировку файлов исходных кодов, текстовых файлов данных, например с помощью Notepad++; Реализовать программное управление локализацией приложения в консоли, пример ниже под катом: Пример программной установки кодовой страницы и локализации приложения в консоли
получилось так что скомпилил и запустил программу со строкой
В общем, методом экспериментов можно сделать такой вывод:
1. SetConsoleOutputCP() устанавливает кодировку ВЫВОДА на консоль
2. SetConsoleCP() устанавливает кодировку ВВОДА из консоли И ИЗ РЕДАКТОРА КОДА
3. setlocale(LC_ALL,»1251″) проверяет, какая кодировка установлена сейчас, и если она не 1251, то меняет ее на 1251, а если уже 1251, то ничего не делает.
Поэтому, если уже установлена кодировка ввода ИЗ РЕДАКТОРА функцией SetConsoleCP(1251), то после нее setlocale() ничего менять не будет, и попросту выведет символы по нумерации CP866, решив, что они и так уже в windows 1251.
Если же уже выполнена функция SetConsoleOutputCP(1251), то setlocale() проверит, какая кодировка ввода установлена, и обнаружит, что кодировка ввода по прежнему CP866, поэтому она возьмет номера этих уже преобразованных символов (с помощью SetConsoleOutputCP(1251)), НО ИЗ кодовой таблицы cp866 и выведет символы с этими номерами из таблицы windows 1251.
то символика соответствует и выводу в файл ASCII
http://foxtools.ru/ASCII#1251Русский язык в консоли
6 ответов 6
Правильное, но сложное решение
Менее правильные, но пригодные решения
Методы, которые работают плохо (но могут помочь вам)
Символы кириллицы в консоли Windows
Самый простой (и самый неудобный) способ
Вывод на консоль Windows 7
Ввод и вывод на консоль
Функции перекодировки
SetConsoleOutputCP function
Syntax
Parameters
The identifier of the code page to set. For more information, see Remarks.Return value
Remarks
Гарантированная локализация/русификация консоли Windows
Введение
Виды консолей
Конфликт кодировок
Проблемы консолей Visual Studio
Локализация отладочной консоли Visual Studio
Стратегия локализации приложения в консоли