Здравствуйте, Аноним, Вы писали:
А>Собственно как можно сделать так что бы в string a хранились символы в кириллицы а не ироглифами.
Вот набросал примерчик, в результате которого и сам разобрался, и вам, надеюсь, поможет понять, что к чему.
#include <iostream>
#include <locale>
#include <sstream>
#include <string>
std::string narrow(std::wstring const & wstr, std::locale const & loc, char def = '?')
{
if (wstr.empty())
return std::string();
std::string ret;
ret.resize(wstr.length());
std::use_facet<std::ctype<wchar_t> >(loc).narrow(&wstr[0], &wstr[0] + wstr.length(), '?', &ret[0]);
return ret;
}
std::wstring widen(std::string const & str, std::locale const & loc)
{
if (str.empty())
return std::wstring();
std::wstring ret;
ret.resize(str.length());
std::use_facet<std::ctype<wchar_t> >(loc).widen(&str[0], &str[0] + str.length(), &ret[0]);
return ret;
}
std::string to1251(std::string const & cp866)
{
std::string ret;
ret.reserve(cp866.length());
for (std::size_t i = 0, e = cp866.length(); i < e; ++i)
{
wchar_t wide = std::use_facet<std::ctype<wchar_t> >(std::locale(".866")).widen(cp866[i]);
ret.push_back(std::use_facet<std::ctype<wchar_t> >(std::locale(".1251")).narrow(wide, '?'));
}
return ret;
}
int main(int argc, char* argv[])
try
{
std::string cp866;
std::cin >> cp866; // Кодировка в консоли — CP866
std::string cp1251 = to1251(cp866); // Преобразуем в CP1251
std::locale::global(std::locale("")); // Устанавливаем текущую локаль (русскую)
// можно также russian_russia, russian_russia.866, russian_russian.1251, .866, .1251
// В данном случае установлена .1251 == russian_russia.1251
std::cin.imbue(std::locale(".866")); // Почему-то влияния не имеет. Если напишу .1251, ничего не изменится
std::cout.imbue(std::locale()); // На вывод ставим текущую локаль
std::wcin.imbue(std::locale(".866")); // А здесь всё ок
std::wcout.imbue(std::locale()); // Аналогично
std::cout << cp1251 << std::endl; // Выводим строку в CP1251. Будут крокозябры, если текущая локаль не .1251
std::cin >> cp1251; // Читается всё равно в CP866
std::cout << cp1251 << std::endl; // Соот-но тут будут крокозябры, если текущая локаль не .866
std::wstring wtest;
std::wcin >> wtest;
std::wcout << wtest << std::endl;
std::string test;
std::wcin >> wtest;
test = narrow(wtest, std::locale(".1251")); // Преобразуем в CP1251
wtest = widen(test, std::locale(".1251")); // Обратно, неясно только куда обратно? Видимо, в глобальную локаль,
// ибо последующий вывод срабатывает как при .866, так и при .1251
std::cout << test; // Будут крокозябры, если локаль не .1251
std::wcout << wtest << std::endl;
return 0;
}
catch (std::exception const & e) // Конструкторы std::locale кидают исключения на неверное имя
{
std::cerr << e.what() << std::endl;
return -1;
}
Неясно только, почему локали .866 .1251 не имеют действия на ctype<char> и std::cin/cout.
Т.е. если в функции to1251 поменять wchar_t на char, то работать не будет.