Кодировки в Windows
В данной статье пойдёт речь о кодировках в Windows. Все в жизни хоть раз использовали и писали консольные приложения как таковые. Нету разницы для какой причины. Будь-то выбивание процесса или же просто написать «Привет. Я не могу сделать кодировку нормальной, поэтому я смотрю эту статью!».
Тем, кто ещё не понимает, о чём проблема, то вот Вам:
А тут было написано:
Но никто ничего не понял.
В любом случае в Windows до 10 кодировка BAT и других языков, не использует кодировку поддерживающую Ваш язык, поэтому все русские символы будут писаться неправильно.
1. Настройка консоли в батнике
Сразу для тех, кто пишет chcp 1251 лучше написать это:
Первый способ устранения проблемы, это Notepad++. Для этого Вам нужно открыть Ваш батник таким способом:
Не бойтесь, у Вас откроется код Вашего батника, а затем Вам нужно будет сделать следующие действия:
Если Вам ничего не помогло, то преобразуйте в UTF-8 без BOM.
2. Написание консольных программ
Нередко люди пишут консольные программы(потому что на некоторых десктопные писать невозможно), а кодировка частая проблема.
Первый способ непосредственно Notepad++, но а если нужно сначала одну кодировку, а потом другую?
Сразу для использующих chcp 1251 пишите это:
Второй способ это написать десктопную программу, или же использовать Visual Studio. Если же не помогает, то есть первое: изменение кодировки вывода(Пример на C++).
Если же не сработает:
3. Изменение chcp 1251
Если же у Вас батник, то напишите в начало:
Теперь у Нас будет нормальный вывод в консоль. На других языках (С++):
4. Сделать жизнь мёдом
При использовании данного способа Вы не сможете:
Языковые настройки и локализация
Я зыковой стандар т — это уникальная комбинация языка (соглашения о форматировании текста и данных), локальные соглашения региона\страны (локаль) и кодовой страницы (стандарт\название таблицы кодировки).
Кодовая страница — это набор символов, который может содержать числа, знаки пунктуации и другие глифы. Кодовая страница для языкового стандарта "C" (кодовая страница "C") соответствует кодировке ASCII.
Локаль — набор параметров, определяющий региональные настройки пользовательского интерфейса, такие как язык, страна, часовой пояс, набор символов, формат вывода даты, времени, используемая денежная единица.
Структура программы на языке Си
Программа на языке Си состоит из одной или более подпрограмм, называемых функциями .
Язык Си является блочно-структурированным. Каждый блок заключается в фигурные скобки <> .
Основным блоком в программе консольного приложения на языке Си является главная функция, имеющая имя main() .
Каждое действие в языке Си заканчивается символом «точка с запятой» — ; . В качестве действия может выступать вызов функции или осуществление некоторых операций.
Имя функции — это коллективное имя группы описаний и операторов,
заключенных в блок (фигурные скобки). За именем функции в круглых скобках указываются параметры функции.
Комментарии в языке Си
В языке Си для комментариев используются символы
/* — начало комментария;
*/ — конец комментария.
Вся последовательность, заключенная между этими символами, является комментарием.
Это удобно для написания многострочных комментариев:
Многострочные комментарии также удобно использовать при отладке для сокрытия от выполнения части кода.
В дополнение к этому, для написания коротких комментариев могут использоваться символы // . При этом комментарием является все, что расположено после символов // и до конца строки:
Главная функция
При выполнении консольного приложения, написанного на языке Си, операционная система компьютера передаёт управление функции с именем main() . Функцию main() нельзя вызывать из других функций программы, она является управляющей.
Следующие за именем функции круглые скобки предназначены для указания параметров (аргументов), которые передаются в функцию при обращении к ней. В данном случае операционная система не передаёт в функцию main() никаких аргументов, поэтому список аргументов в круглых скобках пустой.
Главную функцию можно записать по-разному:
- int main()
- void main() .
Перед именем функции указывается тип возвращаемого значения. При обращении к главной функции значение возвращается операционной системе. Последняя запись не будет возвращать значения. Однако void main() — не совсем корректная запись, так как сообщает компилятору, что функция main() не возвращает никакого значения.
При этом запись int main() сообщает компилятору о возвращении целочисленного значения, которое необходимо операционной системе и сообщает ей о том, что программа завершилась корректно. Если же это значение не возвращено, то операционная система понимает, что программа завершилась в аварийном режиме.
Для возврата целочисленного значения перед завершением функции добавляется строка
В фигурные скобки заключены описания и операторы.
В общем случае программа может содержать несколько функций. Каждая функция имеет список передаваемых в нее параметров, указанный в круглых скобках, и набор операций, заключенных в блок, ограниченный фигурными скобками.
Пример: Вывод на экран сообщения "Hello, world!" .
Результат работы программы:
Теперь попробуем написать текст на русском языке.
Результат работы программы:
Проблема русского языка в консольных приложениях заключается в том, что консоль и редактор кода Microsoft Visual Studio поддерживают разные кодовые страницы. Для того, чтобы увидеть русские символы в консоли необходимо поменять кодовую страницу в консоли, чтобы она соответствовала кодовой странице редактора (1251). С этой целью вызывается функция system( "chcp 1251" ) с соответствующей командной строкой. Прототип функции system() содержится в библиотеке <stdlib.h> .
При этом текст программы будет выглядеть следующим образом:
Результат работы программы:
Russian in the console
I am learning C++ from Stroustrup’s book, Russian characters are not displayed.
Here is the code:
“Duplicate word:” – displayed fine thanks to setlocale.
What is after – kryakozyably, although repeating words are found.
setlocale tried different (0, “”), “”, “Rus”, etc.
Everything works in Code :: Blocks even without crackers. Even without setlocale.
Answer 1, authority 100%
There are many solutions for this task. If you need a fast and not necessarily a universal solution so you don’t have to go through too much trouble, scroll down to Less valid but useful solutions .
Correct but difficult solution
For starters, the problem with the Windows console is that its default fonts do not show all characters. You should change the console font to Unicode, this will even work on English Windows. If you want to change the font only for your program, in its console click on the icon in the upper left corner → Properties → Font. If you want to change for all future programs, the same, just go to Defaults, not Properties.
Lucida Console and Consolas handle everything but hieroglyphs. If your console fonts allow, you can also output 猫 , if not, then only those characters that are supported.
Further consideration concerns only Microsoft Visual Studio. If you have a different compiler, use the suggested ones at your own risk, there is no guarantee.
Now, the encoding of the compiler input files. The Microsoft Visual Studio compiler (at least 2012 and 2013 versions) compiles the sources in single-byte encodings as if they were actually in ANSI encoding, that is, for the Russian system – CP1251. This means that CP866 source encoding is incorrect. (This is important if you are using L «. » -strings.) On the other hand, if you store the sources in CP1251, then the same sources will not build normally on non-Russian Windows. Therefore, it is worth keeping the sources in Unicode (for example, UTF-8).
Having set up the environment, let’s move on to solving the actual problem.
The correct solution is to get away from single-byte encodings and use Unicode in the program. In this case, you will receive the correct output not only of the Cyrillic alphabet, but also support for all languages (the image of the characters missing in the fonts will be absent, but you will be able to work with them). For Windows, this means moving from narrow strings ( char * , std :: string ) to wide ones ( wchar_t * , std :: wstring ), and use UTF-16 encoding for strings.
(Another problem that the use of wide strings solves: when compiling, narrow strings are encoded into a single-byte encoding using the current system code page, that is, ANSI encoding. If you compile your program on English Windows , this will lead to obvious problems.)
You need _setmode (_fileno (. ), _O_U16TEXT); to switch console mode:
This should work correctly with input and output, filenames, and stream redirection.
Important note: I / O streams are either “wide” or “narrow” – that is, they output either only char * , or only wchar_t * . Switching is not always possible after the first output. Therefore, this code:
may well not work. Use only wprintf / wcout .
If you really do not want to switch to Unicode, and use a single-byte encoding, problems will arise. To begin with, characters that are not included in the selected encoding (for example, for the case of CP1251 – basic English and Cyrillic), will not work, instead of them gibberish will be entered and displayed. In addition, narrow string constants are ANSI-encoded, which means that Cyrillic string literals on a non-Russian system will not work (they will have a system-locale-dependent gibberish). With these issues in mind, we move on to the next series of solutions.
Less correct, but suitable solutions
Anyway, put a unicode font in the console. (This is the first paragraph of the “hard” solution.)
Make sure your sources are in CP 1251 encoding (this does not go without saying, especially if you have a non-Russian Windows locale). If, when adding Russian letters and saving, Visual Studio swears that it cannot save characters in the desired encoding, choose CP 1251.
(1) If the computer is yours, you can change the code page of the console programs on your system. To do this, do this:
- Start Regedit.
- To be on the safe side, export the registry somewhere (for some reason everyone skips this step, so when everything breaks, we warned you).
- In the HKEY_CURRENT_USER \ Console section, find the CodePage key (if not, create a key with this name and DWORD type).
- Set the value by key (left key / change / Number system = decimal) to 1251.
- Don’t forget to reboot after changing the registry.
Advantages of this method: examples from books will start working out of the box. Disadvantages: changing the registry can cause problems, the console encoding changes globally and permanently – this can affect other programs to break. Plus the effect will only be on your computer (and on others that have the same console encoding). Plus common problems with non-Unicode methods.
Note: Setting the global console codepage via the HKEY_CURRENT_USER \ Console \ CodePage registry entry does not work on Windows 10, it will use the OEM codepage instead – presumably bug in conhost . However, setting the console codepage at the application-specific level ( HKEY_CURRENT_USER \ Console \ (application path) \ CodePage ) works.
(2) You can only change the encoding of your program. To do this, you need to change the console encoding programmatically. As a courtesy to other programs, do not forget to put the encoding back in place later!
This is done either by calling functions
at the beginning of the program, or by calling an external utility
(That is, you should end up with something like
and then ordinary program code.)
You can wrap these calls in a class to take advantage of the automatic lifetime management of C++ objects.
(if you are performing a task from Stroustrup, you can insert it at the end of the std_lib_facilities.h header file)
If you do not need Russian, but some other language, just replace 1251 with the identifier of the required encoding (the list is indicated below in the file), but, of course, performance is not guaranteed.
There are still methods that are also common, we present them for completeness.
Techniques that don’t work well (but might help you)
The commonly recommended method is to use the setlocale (LC_ALL, «Russian») construct; This option (at least in Visual Studio 2012) has a mountain of problems. First, there is a problem with entering Russian text: the entered text is transferred to the program incorrectly! Non-Russian text (for example, Greek) is not entered from the console at all. Well, common to all non-Unicode solutions to the problem.
Another non-Unicode method is using the CharToOem and OemToChar functions. This method requires re-encoding each of the lines in the output, and (it seems) is weakly amenable to automation. It also suffers from disadvantages common to non-Unicode solutions. In addition, this method will not work (not only with constants, but also with runtime strings!) On non-Russian Windows, since there the OEM encoding will not match CP866. In addition, we can also say that these functions are not supplied with all versions of Visual Studio – for example, some versions of VS Express simply do not have them.
- unfortunately, the author of that question used the MinGW compiler for Cygwin and WinXP, which makes most of the modern solutions inapplicable.
Answer 2, authority 5%
Therefore, it is worth keeping the sources in Unicode (for example, UTF-8).
And it should be saved with the signature
The situation is partially saved by re-saving the sources in UTF-8 encoding with a mandatory BOM character, without which Visual Studio begins to interpret “wide” strings with Cyrillic in a very peculiar way. However, by specifying the BOM (Byte Order Mark) of the UTF-8 encoding – a character encoded with three bytes 0xEF, 0xBB and 0xBF, we get recognition of the UTF-8 encoding on any system
Answer 3, authority 5%
Something worth clarifying for those looking for the correct answer about the setlocale function:
A commonly recommended method is to use the setlocale (LC_ALL, “Russian”) construct; This option (at least in Visual Studio 2012) has a mountain of problems. First, there is a problem with entering Russian text: the entered text is not passed to the program correctly! Non-Russian text (for example, Greek) is not entered from the console at all. Well, common to all non-Unicode solutions to the problem.
I will add more information on this method: It is generally not recommended correctly!
Let’s start with the first: In the second parameter, the function does not accept the name of the country or language, although in some cases it will work, but the language identifier, according to ISO 3166-1. Therefore, it is correct and correct to indicate: “ru-RU”.
Now the second: the documentation for this function is written in black and white: “If execution is allowed to continue, the function sets errno to EINVAL and returns NULL.” This is literally interpreted: when an error occurs, the function sets the value of the errno variable to EINVAL and returns NULL.
In the event of an error, errno will always be EINVAL, which means: not a valid argument. Therefore, it makes no sense to check it, but the execution of the function must be checked. Therefore, the correct call to the setlocale function looks like this:
And don’t forget that setlocale sets the local table for ANSI encoding only, so Greek, Spanish, Chinese and even Japanese characters will not be displayed.
For the Russian language this will be table number 1251.
And it is important: why this function is more reliable than direct installation of the symbol table via SetConsoleCP, because it switches all internal add-ons specifically for the layout for the language. Starting from the date display standard, ending with separator characters.
And yes, you should not install the language index in the form “ru”, because depending on the assembly of the axis itself and the available language packs, ru-BY, ru-UA, ru-MO and other language standards that differ significantly from ru-RU. And categorically it is impossible to indicate “Russia”, “Russian”, “Russian Federation” (yes, I’ve already met such an orgy a couple of times). Although the function also checks by the name of the region, this is not always indicated in the localization table, or it may be indicated “Russia” or “Russian” already on our layout. This is the main mistake that often causes setlocale to fail.
And yes, for an application that is running in unique mode , the _wsetlocale function should be used. It is identical and also sets the basic localization settings. In addition, if the application project in Visual Studio is configured in Unicode mode, then only _wsetlocale will work, since setlocale, according to the documentation, is not adapted to work with Unicode at all.
UPD.
I completely forgot to indicate that the setlocale and _wsetlocale function, if successful, will return the region identifier. That is, in our case the line “ru_RU \ 0”.
Answer 4, authority 4%
Cygwin – when installing in the package selection, you need to find and mark all sorts of cmake , GDB and others that someone recommended for installation.