• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

klasy Qt vs biblioteka standardowa ( kodownie znaków w obu przypadkach )

Object Storage Arubacloud
0 głosów
421 wizyt
pytanie zadane 12 lipca 2019 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)

Witam, kiedyś zadawałem dość podobne pytanie ale teraz skupiam się na nieco innym aspekcie, mam taki kod programu:

#include <QCoreApplication>
#include <QDebug>
#include <QString>
#include <iostream>
#include <string>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::string str;
    std::cin >> str;

    std::cout << str << "\n"; //ok
    std::cout << int(str[0]) << "\n"; //ok
    std::cout << char(-91) << "\n"; //ok

    char c = -91;
    qDebug() << c; //?

    QChar qc = -91;
    qDebug() << qc; //??
    qDebug() << qc.unicode(); //?!

    return a.exec();
}

Biorąc pod uwagę kodowanie konsoli windowsowej ( 852 OEM - Latin II) kod litery 'ą' zapisany zapisany w typie char wynosi -91. Wypisanie w ten sposób tej litery daje poprawny wynik:

std::cout << char(-91) << "\n"; //ok

gorzej kiedy chcę wypisać ten sam znak o tym samym kodzie w tym samym typie za pomocą qDebug() :

 char c = -91;
qDebug() << c; //?

dostaje wtedy na ekranie znak Y...

Moje pierwsze pytanie brzmi: Co strumień qDebug() robi z kodem mojego znaku?

Dalej wykorzystując typ QChar jest już całkowita masakra:

przecież to ten sam kod który powinien być przez windowsową konsole tak samo interpretowany. Dla pewności sprawdziłem jeszcze kod litery ą dla typu unsigned char i przypisałem do QChar:

wypisana wartość bzdurna ale chociaż kod liczbowy się zgadza ( czyli QChar przechowuje liczby unsigned )

tak dla ciekawostki, teraz:

unsigned char c = 165;
qDebug() << c; 

będę miał wypisaną nie literę ą ale jej kod czyli 165.

Co więc muszę zrobić żeby wypisać znak używając jego kodu wykorzystując narzędzia z Qt? Nie chodzi mi tu nawet o wyświetlanie polskich znaków w konsoli bo nie ma takiej potrzeby ( Qt to głównie GUI ). Po prostu totalnie nie rozumiem co QChar i qDebug() robi z moim kodem znaku...

z góry dziękuje za pomoc ;)

2 odpowiedzi

0 głosów
odpowiedź 12 lipca 2019 przez Bondrusiek Maniak (61,410 p.)

Witam,

jeśli chcesz używać Qt do wyświetlania takich samych wartości jak dla std::cout polecam użyć QTextStream. QTextStream jest strumieniem, który może pobierać bądź zwracać dane. Musisz również ustawić odpowiednie kodowanie ja ustawiłem na UTF-16.

Przykładowy program:

#include <QCoreApplication>
#include <QString>
#include <iostream>
#include <string>
#include <QTextCodec>
#include <QTextStream>


QTextStream _cout(stdout, QIODevice::WriteOnly);

int main (int argc, char **argv) {
    QCoreApplication app(argc, argv);
    //_cout.setCodec("IBM 850");

    _cout.setCodec("UTF-16");


    std::cout << " c++ " << std::endl;
    for(int i = -127; i < 255; ++i)
        std::cout << i << " " << char(i) << std::endl;

    std::cout << " qt " << std::endl;
    for(int i = -127; i < 255; ++i)
        _cout << i << " " << QChar(i) << endl;

    return app.exec();
}

 

komentarz 12 lipca 2019 przez j23 Mędrzec (194,920 p.)
Coś mi się wydaje, że to nie wyświetli poprawnie tekstu w kodowaniu cp852 (bo jeśli dobrze zrozumiałem OP, o to mu chodzi).
komentarz 12 lipca 2019 przez Jakub 0 Pasjonat (23,120 p.)

@Bondrusiek

Nie do końca poprawnie działa:

#include <QCoreApplication>
#include <QString>
#include <iostream>
#include <string>
#include <QTextCodec>
#include <QTextStream>


QTextStream _cout(stdout, QIODevice::WriteOnly);
QTextStream _cin(stdin, QIODevice::ReadOnly);

int main (int argc, char **argv) {
    QCoreApplication app(argc, argv);

    _cout.setCodec("IBM 850"); //cp852

    _cout << QChar(165) << endl; // ą
    QChar a;
    _cin >> a;
    _cout << a << endl;
    _cout << a.unicode() << endl;

    return app.exec();
}

W kodowaniu cp852 165 to znak 'ą', a tu wypisuje się 'ż'. Dla kodowania UTF-16 wypisywanie działa dobrze ale gorzej kiedy próbujemy wypisać znaki wczytane z klawiatury ( raz jest okej a raz głupota w zależności od znaku ).  Zrobiłem jeszcze tak:

_cin.setCodec("IBM 850");

ale efekt jest bzdurny:

*I tu jeszcze małe pytanie, dlaczego wypisując liczbę 209 mamy przerwy między cyframi??

komentarz 12 lipca 2019 przez Bondrusiek Maniak (61,410 p.)

@Jakub 0

*I tu jeszcze małe pytanie, dlaczego wypisując liczbę 209 mamy przerwy między cyframi??

Tak na pierwszy rzut oka nie wiem. Wydaje mi się powinieneś przeszukać dokumentacje klasy QTextStream: https://doc.qt.io/qt-5/qtextstream.html i znaleźć funkcje, która modyfikuje strumień. Pewnie rozpoczyna się na set...

komentarz 12 lipca 2019 przez Jakub 0 Pasjonat (23,120 p.)
Poszukam sobie...

Ale zastanawiam się czy najlepszym sposobem na mój problem nie będzie po prostu konwersja z QChar na unsigned char i używanie standardowych strumieni w C++...

myślisz że tak ujdzie czy mało profesjonalnie?

* wiem że typ QChar jest bardziej pojemny, ale do polskich znaków char wystarczy.
komentarz 12 lipca 2019 przez Bondrusiek Maniak (61,410 p.)
Wydaje mi się że to dobry pomysł unsigned char przechowuje wartość od 0 do 255.
0 głosów
odpowiedź 12 lipca 2019 przez mokrowski Mędrzec (156,140 p.)

Dla VS:

https://docs.microsoft.com/en-us/cpp/build/reference/execution-charset-set-execution-character-set?view=vs-2019

Jeszcze jest (nie wiem czy udokumentowana) pragma dla VS:

#pragma execution_character_set("utf-8") // Tu podstaw co tam chcesz ale nie daję głowy że będzie zawsze działać.

Dla gcc:

https://gcc.gnu.org/onlinedocs/cpp/Invocation.html opcje:

-finput-charset, -fexec-charset i -fwide-exec-charset

 

Poza tym od Win 7 (którejś rewizji), cmd obsługuje już kodowanie utf-8: https://stackoverflow.com/questions/388490/how-to-use-unicode-characters-in-windows-command-line/388500#388500 więc może nie kop się z koniem :)

Podobne pytania

0 głosów
0 odpowiedzi 144 wizyt
+1 głos
4 odpowiedzi 1,764 wizyt
pytanie zadane 20 grudnia 2019 w HTML i CSS przez BlvckFox Gaduła (4,240 p.)
0 głosów
1 odpowiedź 371 wizyt

92,654 zapytań

141,543 odpowiedzi

319,958 komentarzy

62,024 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...