érdekes Unicode viselkedés - furcsa karakterek

 ( wowbagger | 2008. szeptember 19., péntek - 2:40 )

Egy feladatomban Qt4-ben kell egy alkalmazást megírnom.
A program konzolban fut majd, azonban megfelelően kell paraméterezni.
Megírtam a részeket, amik ellenőrzik a paraméreket, azonban egy furcsa jelenségre lettem figyelmes.
Az OS Ubuntu 7.10, UTF-8-as magyar locale-val.
A program nevét az argv[0]-ból venném ki, de ilyenkor mindig kell egy basename-szerű függvényt hívni, hogy az elérési utat levágjuk.
A jelenség az, hogy olyan karakterek jelennek meg a programom kimenetében, amiket a parancssorban nem adtam meg, illetve olyanok eltűnnek, amelyeket pedig igen.

janos@janos-virtual:~/Desktop/dev$ export LANG="hu_HU.UTF-8"
janos@janos-virtual:~/Desktop$ ./dev/skype-­bridge 
Usage:   "skype­bridge"  --server << server_name >> --­­port << port >>
 
janos@janos-virtual:~/Desktop$ export LANG="en_US"
janos@janos-virtual:~/Desktop$ ./dev/skype-­bridge 
Usage:   "skypebridge"  --server << server_name >> --port << port >>
 
janos@janos-virtual:~/Desktop$ 

/ A programfájl neve skype-bridge, és ahogy a fenti kimenetet bemásoltam a firefox-ba, úgy a bemásolás után is másként nézett ki a szöveg, mint eredetileg (a program futtatásakor skype-bridge helyett skypebridge lett) (kijavítottam arra, amit a konzolban látok) /
Nem tudom, hogy miért van ez így, és hogyan kényszeríthetném helyes működésre a programomat.
A forrás itt található.

szerk: továbbá az sem világos számomra, hogy a program nevének kiírásakor miért jelennek meg idézőjelek, mikor én azt a kódba nem írtam bele...

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

lehet, hogy hülyeséget kérdezek, de nem lehet, hogy a c++ forrásfájlod véletlenül UTF-8 -as lett?

A program neve string ekkor UTF-8-as editorral így néz ki:
printf("skype-bridge");

de valójában a kötőjel nem az ascii kötőjel, hanem egy spéci 2 byte-os kóddal leírt UTF8-as "hosszú kötőjel".

Meg kéne nézni egy pure ascii fájlnézegetővel.

+1, hogy utf-8-ban spéci kötőjelek vannak. Ezt erősíti, hogy az en_US kimeneten ki is hagyja a kötőjelet. Ha a latin1-es sima kötőjel lenne, akkor odarakná.

"Jegyezze fel a vádhoz - utasította Metcalf őrnagy a tizedest, aki tudott gyorsírni. - Tiszteletlenül beszélt a feljebbvalójával, amikor nem pofázott közbe."

Ha ez a gond, akkor egy megoldás lehet:

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

(Lehetőleg a main-be a QApplication után.)

Egyébként szerintem nem a forrás lesz UTF-8-as, hanem a fájlnév...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

nem, az biztos nem, mert
- direkt elmentettem az adott forrásfájlt iso8859-2-es kódolással is.
- az appname nincs belekódolva, azt mindig az argv[0]-ból bányássza elő.
__________________________________________________________
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.3-janos

Félig Off:

Nem ezt kerested?
http://doc.trolltech.com/4.4/qfileinfo.html#fileName

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Nulla QT tapasztalatokkal tippelek egyet az extra idézőjelekre. Nekem a qDebug a gyanús. Simán lehet hogy ő teszi oda. Nem értem, miért ezt a függvényt használod. Neve alapján ez debug üzenetek, vagyis programozók számára szóló, fejlesztést segítő üzenetek kiírására való. A felhasználó tájékoztatására sima szövegkiíró cuccot használnék: printf, cout, vagy nem tudom van-e QT megfelelőjük.

Természesen a qDebug teszi oda az "-jelet a stringek köré.

Használj QTextStream-et:

QString str("Blabla");
QTextStream out(stdout);

out << str << endl;

A cout használata macerásabb:

std::cout << str.toLocal8Bit().data() << std::endl;

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

a helyzet az, hogy egy skype példaprogram alapján dolgozom, amiben a qDebuggal oldották meg a kiíratást, ezért használtam én is ezt. de igazad van. átírom, így mindenképpen tisztább lesz.
__________________________________________________________
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.3-janos

Ezeket próbálnám:

20. sor: QString appname = QString::fromUtf8(filename(argv[0]));
//QString fromUtf8 ( const char * str, int size = -1 )

kiiratásoknál: appname.toAscii() az appname helyett!

Sőt:

QStringList QCoreApplication::arguments()

http://doc.trolltech.com/4.4/qcoreapplication.html#arguments

Elvileg ez megcsinálja helyetted az esetleges codepage konverziókat.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

köszönöm a sok jótanácsot, igyekeztem megfogadni őket.
az elsődleges probléma megoldódott, azonban felbukkant egy másik.
a jelenlegi változat így néz ki.
az a helyzet, hogy ha a programnak mondjuk a --server localhost kapcsolót adom, akkor rögtön hanyattvágja magát, segfaulttal.
a valós funkcionalitásból még nincs megírva semmi, így aztán akkor dobja fel a bakancsot, amikor arg_server-hez hozzárendelem az új értéket.
miért van ez? (a portszámot szépen elrendezi, azzal nincs gond.)
mit rontottam el? mire nem figyeltem? (késő van, lassan fog az agyam.)

__________________________________________________________
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.3-janos

Ollalaaa.
Azt írja az általam linkelt leírás az arguments fv-re:
"Calling this function is slow - you should store the result in a variable when parsing the command line."

Ebből (és egyébként is) elég egyértelmű, hogy minden hívásra egy új QStringList-et ad vissza.

Te elindítasz egy ciklust a QCoreApplication::arguments().constBegin()-től, majd az iterátort többször összehasonlítod a QCoreApplication::arguments().constEnd()-del, a baj csak az, hogy ez minden alkalommal egy új QStringList constEnd()-je.
Valahogy így kéne:

...
    if (QCoreApplication::arguments().count() == 1) {
                output << "Usage:\t" << appname << " --server <> --port <>\n";
        return err::NO_ARGS;
    }
    QStringList arguments(QCoreApplication::arguments());
    for (QList::const_iterator i=arguments.constBegin(); i!=arguments.constEnd(); ++i) {
...

(Persze később is cseréld a fv hívást a változóra.)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

igazad van, köszöm a segítséget.
__________________________________________________________
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.3-janos