Обычно для работы с кириллицей мне всегда хватало следующего способа
Суть которого была в том, что мы впихиваем хеадер 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
В строке
ОтветитьУдалитьfout << L"Тест на поддержку кириллицы\n";
мы явно объявляем ту строку, которую хотим записать в файл. Как быть, если у меня необходимая информация хранится в переменной buff типа char?
fout<< buff; - не помогает. Заранее спасибо!