crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в плавающий баг вывода utf8 на stdout
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
lrx2 Дата 24.2.2017, 0:07
  из setlocale завершаются нормально только:
setlocale(LC_ALL, 0) - возвращает "c", т.е. что установлена минимальная си-локаль.
setlocale(LC_ALL, "") - возвращает "cp1251".
Сдаюсь. Раз уж даже setlocale тупо не может установить локаль cp65001(возращает NULL), то и черт с ним.
Спасибо за потраченное время.

Итоговое (мож кому пригодится):
#include <QCoreApplication>
#include <QTextCodec>
#include <iostream>
#include <QDebug>
using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    //Источники:
        //http://blog.kislenko.net/show.php?id=1459
        //http://local.joelonsoftware.com/wiki/%D0%90%D0%B1%D1%81%D0%BE%D0%BB%D1%8E%D1%82%D0%BD%D1%8B%D0%B9_%D0%9C%D0%B8%D0%BD%D0%B8%D0%BC%D1%83%D0%BC,_%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B9_%D0%9A%D0%B0%D0%B6%D0%B4%D1%8B%D0%B9_%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA_%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%9E%D0%B1%D0%B5%D1%81%D0%BF%D0%B5%D1%87%D0%B5%D0%BD%D0%B8%D1%8F_%D0%9E%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE_%D0%94%D0%BE%D0%BB%D0%B6%D0%B5%D0%BD_%D0%97%D0%BD%D0%B0%D1%82%D1%8C_%D0%BE_Unicode_%D0%B8_%D0%9D%D0%B0%D0%B1%D0%BE%D1%80%D0%B0%D1%85_%D0%A1%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D0%BE%D0%B2
        //http://www.unn.ru/pages/e-library/vestnik/99999999_West_2011_3%282%29/47.pdf

    //текущий пример идет с учетом, что кодировка файла с исходным кодом UTF-8


    //все примеры собраны в одну функцию для компактности
    //если запускать все подряд, как есть, то результат не будет желаемым
    //т.е. до запуска и проб необходимо выбрать один вариант, а все остальные закомментировать


    //------------------------- 0 setlocale
    //чтобы остальные примеры работали нормально..
   // wcout<<"locale: " <<setlocale(LC_ALL,"")<<endl;//..<--эту строку неоьбходимо закомментировать
        //setlocale возвращает строку с именем локали
        //при неудаче вернет NULL
        //setlocale предоставляет преобразование строк только для вывода на консоль, но не для чтения с неё
        //подробнее http://www.unn.ru/pages/e-library/vestnik/99999999_West_2011_3%282%29/47.pdf
            //ЛОКАЛИЗАЦИЯ КОНСОЛЬНЫХ ПРИЛОЖЕНИЙ В ЯЗЫКЕ C++
            //© 2011 г. В.Л. Тарасов
            //Информационные технологии
            //Вестник Нижегородского университета им. Н.И. Лобачевского, 2011, № 3(2), с. 301–307
    wcout<<L"Привет, мир!"<<endl;


    //------------------------ 1 QTextCodec::setCodecForLocale -----------------------
    cout<<"\n\n----ver1 -----\n";
    QTextCodec *coding = QTextCodec::codecForName("866");
    QTextCodec::setCodecForLocale(coding);
    system("chcp 866"); //просто убедиться, что стоит кодировка 866 -- будет работать только в винде

    qDebug() << "qDebug(): русский текст -- ok";
    qWarning() << "qWarning(): русский текст -- ok";
    cout<<"cout: [русский текст] -- not ok\n";


    //------------------------- 2 QTextStream(std)+QTextCodec ----------------------
    cout<<"\n\n----ver2 -----\n";
    QTextStream co(stdout);

    co.setCodec(coding);
    co<<"new codec for locale: [" << QTextCodec::codecForLocale()->name() <<"]";
    co.flush();

    co<<QString::fromUtf8("\nver2: fromUtf8: [русский текст] -- ok\n");
    //с учетом, что кодировка файла должна быть utf-8,
    //да и с 2012 года по умолчанию считается таковой,
    //то можно сделать и просто:
    co<<QString("\nver2: QString(): [русский текст] -- ok\n");
    //QString строки внутри себя хранит в кодировке UTF16, который уже переводится в любую необходимую кодировку
    co<<"ver2: simple: [русский текст] -- not ok \n";
    co.flush();

        //------------ чтение-запись ------------

    co.setCodec("CP866");
    co<<QString("Введите ваше имя: ");
    co.flush();


    QTextStream ci(stdin);
    ci.setCodec("CP866");
    QString name;
    ci >> name;
    co << QString("Привет, ") <<
            name    <<
            "!"     << endl;


    //---------------------- 3 chcp 65001
    system("chcp 65001 > text"); // для utf-8, для преобразованного в юникод текста
        //+придется в свойствах консоли сменить шрифт на Lucide
        //system("chcp 1251"); // для cp1251, при это не надо преобразовывать выводимый текст в юникод
        //работает только для windows
        //не работает стабильно -- выводится только первая строка
            //после чего ни на что не реагирует и дальше не идет
    cout<<" русский 1. текст --ok"<<endl;
    cout<<" русский 2. текст --ok"<<endl;
    cout<<" русский 3. текст --ok"<<endl;

    //--------------------- 4 не работают, но должны
        //SetConsoleCP(CP_UTF8);
        //SetConsoleOutputCP(CP_UTF8);

    return a.exec();
}
lrx2 Дата 23.2.2017, 22:39
 
Цитата(Iron Bug @ 23.2.2017, 5:19) *
попробуй инициализировать консоль так:
SetConsoleOutputCP(CP_UTF8);
_setmode(_fileno(stdout), _O_U8TEXT);


проверить не могу, у меня венды нет. но вроде должно работать.

в консоли вывода приложения в qt creator выводит: "Invalid parameter passed to C runtime function."
В консольку обычную ничего не пишет: просто курсор мигает и ни на что не реагирует.
Iron Bug Дата 23.2.2017, 5:19
  попробуй инициализировать консоль так:
SetConsoleOutputCP(CP_UTF8);
_setmode(_fileno(stdout), _O_U8TEXT);


проверить не могу, у меня венды нет. но вроде должно работать.
lanz Дата 22.2.2017, 14:15
  Unicode в cmd это магия.
set_locale(LC_ALL, "cp65001") должен сработать, но он очень ненадежный и требует настроек в винде.
http://stackoverflow.com/questions/388490/...ommand-line-how
lrx2 Дата 22.2.2017, 12:10
 
Цитата(Алексей1153 @ 22.2.2017, 8:05) *
lrx2, а если отбросить всю эту магию и применить QTextCodec ? QString - это юникод, а QTextCodec позволяет гонять из любой кодировки в юникод и наоборот


И так
system("chcp");
    QTextStream cout(stdout);

    cout.setCodec("CP866");
    cout<<QString::fromUtf8("Введите ваше имя: ");
    cout.flush();


    QTextStream cin(stdin);
    cin.setCodec("CP866");
    QString name;
    cin >> name;
    cout << QString::fromUtf8("Привет, ") <<
            name    <<
            "!"     << endl;

и сяк
QTextCodec *coding = QTextCodec::codecForName("866");
    QTextCodec::setCodecForLocale(coding);
    system("chcp 866");

    qDebug() << "qDebug(): русский текст -- ok";
    qWarning() << "qWarning(): русский текст -- ok";
    cout<<"cout: [русский текст] -- not ok\n";


    //------------------------- 2 ----------------------
    cout<<"\n\n----ver2 -----\n";
    QTextStream co(stdout);

    co.setCodec(coding);
    co<<"new codec for locale: [" << QTextCodec::codecForLocale()->name() <<"]";
    co.flush();

    co<<QString::fromUtf8("\nver2: fromUtf8: [русский текст] -- ok\n");
    co<<"ver2: simple: [русский текст] -- not ok \n";
    co.flush();

Работает.
Но локаль - это ж не магия :( Надо бы разобраться..
Алексей1153 Дата 22.2.2017, 8:05
  lrx2, а если отбросить всю эту магию и применить QTextCodec ? QString - это юникод, а QTextCodec позволяет гонять из любой кодировки в юникод и наоборот
lrx2 Дата 22.2.2017, 4:06
 
Цитата(Iron Bug @ 20.2.2017, 22:31) *
я уже давно не видела венду, но смутно помню, что ей надо было указать русскую локаль в каком-то месте, чтобы она вместо русских букв кракозябры не печатала. плюс для консоли нужно выбрать шрифт, который поддерживает юникод. например, Lucida.

шрифт выбран (Lucida).
setlocale(LC_ALL, "") или setlocale(LC_ALL, "Russian") или setlocale(LC_ALL, "Russian_Russia.1251") трактует строковые константы в коде программы как cp1251 (возвращает строку с именем локали - все хорошо). Кодировка самой консоли на ввод и вывод не меняется(866), судя по getConsoleCP.
(Делал преобразование в CP1251 кода - все выводится нормально)

Если setlocale(LC_ALL, "ru_RU.UTF-8"), то возвращает 0, т.е. - ошибка. В чем ошибка и куда о ней инфу выводить оно должно - не нашел :(
...
std::locale lc_utf8("ru_RU.1251");

выдаёт std::exception что на cp1251, что на utf-8.. не понятно.
------
Суть: setConsoleCP позволяет не только вывод на консоль преобразовывать, но и ввод, чего setlocale не делает.
Вот. Но если бы оно стабильно выводило крякозябры - проблемы бы не было.
Тут же: напечатал код - скомпилил - нормально. Добавил чтение с консоли - появилась мешанина на консоли (часть строки крякозябры-часть нормально-часть вообще из предыдущего cout). Убрал чтение с консоли - опять крякозябры и мешанина.
Возможно, конечно, что я все-таки какие-то мелочи при том упускаю, но пока такое впечатление, либо у меня с башней не особо, либо у компа.(стационар + на ноуте тоже не выходит)
Iron Bug Дата 20.2.2017, 22:31
  я уже давно не видела венду, но смутно помню, что ей надо было указать русскую локаль в каком-то месте, чтобы она вместо русских букв кракозябры не печатала. плюс для консоли нужно выбрать шрифт, который поддерживает юникод. например, Lucida.
lrx2 Дата 20.2.2017, 14:13
 
Цитата(Iron Bug @ 19.2.2017, 23:29) *
а сам код у тебя в UTF? константные строки кодируются как есть.

Да, utf-8.
Iron Bug Дата 19.2.2017, 23:29
  а сам код у тебя в UTF? константные строки кодируются как есть.
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2017, 2:20