Обычно для работы с кириллицей мне всегда хватало следующего способа
Суть которого была в том, что мы впихиваем хеадер locale и прописываем в начале программы setlocale(LC_ALL,"Russian"). Недостаток этого метода в том, что на cout всё и заканчивается. Этот метод не дает корректной работы с вводом кириллических символов из консоли и недаёт их корректного сохранения в файл.
Но тут мне неожиданно сорвало крышу и я решил немного углубиться в эту тему. Различные CharToOem, OemToChar мне как-то не пришлись по душе. И тут я узнал о такой прекрасной вещице как широкие (wide) потоки. Это потоки, которые работают с широкими символами (тот самый wchar_t).
Ближе к сути, пример кода поддерживающего кириллицу:
#include "stdafx.h"
#include <iostream>
#include <locale>
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL,"Russian");
std::cout<<"Проверка на поддержку кириллицы\n";
system("pause");
return 0;
}
Суть которого была в том, что мы впихиваем хеадер locale и прописываем в начале программы setlocale(LC_ALL,"Russian"). Недостаток этого метода в том, что на cout всё и заканчивается. Этот метод не дает корректной работы с вводом кириллических символов из консоли и недаёт их корректного сохранения в файл.
Но тут мне неожиданно сорвало крышу и я решил немного углубиться в эту тему. Различные CharToOem, OemToChar мне как-то не пришлись по душе. И тут я узнал о такой прекрасной вещице как широкие (wide) потоки. Это потоки, которые работают с широкими символами (тот самый wchar_t).
Ближе к сути, пример кода поддерживающего кириллицу:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string> //если нужны строки string
int _tmain(int argc, _TCHAR* argv[])
{
//проверим консольный ввод вывод
//а также хранение кириллицы в расширенных строках
std::wcout.imbue(std::locale("rus_rus.866"));
std::wcin.imbue(std::locale("rus_rus.866"));
std::wcout<<L"Тест вывода кириллицы в консоль\n\n";
std::wcout<<L"Введите что-либо по-русски:";
std::wstring str=L"";
std::wcin>>str;
std::wcout<<L"Вы ввели: "<<str<<L"\n";
//проверим файловые потоки
std::wfstream fout;
fout.open(L"тест-файл.txt",std::ios::out);
if(fout.is_open())
{
fout.imbue(std::locale("rus_rus.1251"));//а здесь, кодировка 1251
fout << L"Тест на поддержку кириллицы\n";
std::wcout<<L"\nТакже проверьте файл тест-файл.txt\n";
fout.close();
}
system("pause");
return 0;
}
Как видите, с помощью расширенных потоков решаются все проблемы локализации. Сама установка языка и кодировки происходит (барабанная дробь) с помощью потокового метода imbue(std::local("language_country")).
Давайте посмотрим, что за строку мы помещаем. В строке "rus_rus.866" первое вхождение rus устанавливает поддержку русского языка, второе вхождение rus означает страну, где всё это мы собираемся использовать.Число строка ".866" - кодировка. Заметьте что для вывода на консоль мы используем кодировку 866, а для вывода в файл кодировку 1251. Таким образом, если бы мы были французами и нам было бы нужно обеспечит поддержку французского языка, а по поводу кодировки вообще бы не парились, тогда бы мы прописали следующий параметр locale( "french_france" ).
Перед каждой строкой стоит специальный модификатор L"некая строка". И если где-либо появились кракозябры, то в первую очередь следует посмотреть наличие этого модификатора.
Теперь о самих потоках. Для работы с консолью, вместо привычных cout и cin здесь используются wcout и wcin. Приставка w от англ. wide - широкий, означает что эти операторы предназначены для работы с широкими символами. Для работы с файлами, потоки, к примеру можно задать следующими способами:
std::wfstream fout;//просто файловый поток
std::wifstream fout;//входной файловый поток(для чтения из файла)
std::wofstream fout;//выходной файловый поток
std::wofstream fout("файл.txt");//тот же выходной поток, но с привязкой к файлу
Как видите, правила использования широких потоков такие же что и для использования обычных.
Итак, мы получаем метод
- который является чистым с++-методом
- а значит, уменьшается вероятность аппаратных неурядиц, характерных для чистого си.
- который элегантен, в отличие от различного рода CharToOem и т.д.
- который является универсальным, вотличие от setlocale()
- и является по сути использованием готового решения, а значит меньше отвлекаться от основной задачи
Для более подробного ознакомления рекомендую:
http://www.rsdn.ru/forum/cpp/1854733.1.aspx