Блог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 :)

Вот как-то так.

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

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

#include <iostream>
#include <cstdlib>
#include <cctype>
#include <Windows.h>
using namespace std; 
 
int main()
{
   //setlocale(LC_ALL,"Rus");
   SetConsoleCP(1251);                
   SetConsoleOutputCP(1251);
 
   char ch;
   cin >> ch;
   if (isalpha((unsigned char)ch)) cout << "is alpha" << endl;
   else cout << "no alpha" << endl;
 
   system("pause");
   return 0;
}

Если же раскомментарить строчку с setlocale, то будет.

13.09.2015, 14:20 [65988 просмотров]


теги: c++ ошибка памятка символ studio

показать комментарии (1)