Ongelma: seuraava koodinpätkä aiheuttaa virheen.
if (input[i] == 'ä') ...
warning: multi-character character constant warning: comparison is always false due to limited range of data type
Käytössä QtCreator (kääntäjä g++ 4.5.2)
Olen asettanut encodingin UTF-8:aan, mutten googlaamisesta huolimatta osaa hyödyntää sitäkään. Miten voin tarkistaa ääkköset merkkijonosta?
E: \x84 ja \x94 testattu, ei toimi ainakaan niillä encodingeilla mitä nyt on ollut käytössä. Mikähän on se asetus, jota Dev-C++ käyttää, jolla nuo toimii?
Mikä input on tyypiltään? Jos käytät char-tyyppiä (std::string-merkkijonoa), et voi tehdä noin. Yksi char käsittää yhden tavun, UTF-8-merkkijonossa yksi merkki voi olla useita tavuja pitkä. Jos käytät wchar_t-tyyppiä (std::wstring-merkkijonoa), merkin pitäisi olla L'ä'
.
Mihin yleensäkään tarvitset tällaista ominaisuutta? Voi olla, että lähestyt asiaa aivan väärältä kannalta.
Kyseessä on yksinkertainen chatbot, joka alussa siivoaa viestin erikoismerkeistä (jättää toki alkuperäisenkin version). Ääkköset pitäisi kuitenkin säästää.
input on std::string-tyyppinen.
tässä siivousfunktio:
Msg Bot::clean_msg(std::string input) { PRINT2("CLEANING MESSAGE..."); Msg clean; std::string cleanstr = ""; for (unsigned i = 0; i <= input.length(); i++) if ((input[i] >= 'A' && input[i] <= 'z') || input[i] == ' ' || (input[i] >= '0' && input[i] <= '9') || input[i] == '<' || input[i] == '>' || input[i] == '_') cleanstr.push_back(tolower(input[i])); clean = cleanstr; return clean; }
Ja tuonne pitäisi lisätä ääkkösten tarkistus.
Ja kyllä, saattaa olla rumaa koodia, toivottavasti silmänne eivät kuitenkaan pala tästä :)
Mites, eikö tämän tyyppiset jutut kannattaisi ratkaista säännöllisillä lausekkeilla? C++:ssaan on olemassa omia kirjastoja niiden tekemiseen.
Esim. http://developer.qt.nokia.com/doc/qt-4.8/qregexp.html
Edit. Apua! Ota heti pois tuo PRINT2-makro tuolta metodin sisältä :D
Metabolix kirjoitti:
--merkin pitäisi olla
L'ä'
.
Kaiken järjen mukaan kyllä, mutta silti seuraava koodinpätkä ei toimi, niin kuin olettaisi:
wchar_t wchar; for (unsigned i = 0; i < str.length(); i++) { wchar = str[i]; if (wchar == L'ä') str.replace(i, 2, "ä "); ...
Ohjelma ei tunnista ä-kirjainta. Missä menee vikaan?
Edit. str on siis std::string-tyyppinen. Sen pitäisi varmaan olla std::wstring-tyyppiä? Pitänee ensi kerralla suunnitella projekti vähän paremmin :D
Edit2. seuraavakaan viritelmä ei printtaa "Match!":
std::wstring string2wstring(std::string str) { std::wstring wstr(str.length(),L' '); std::copy(str.begin(),str.end(),wstr.begin()); return wstr; } int main() { std::string str ("Miäs"); std::wstring wstr (string2wstring(str)); for (unsigned i = 0; i < wstr.length(); i++) if (wstr[i] == L'ä') std::cout << "Match!"; return 0; }
Mutta "Match!" tulee, jos wstr:n alustaa näin:
std::wstring wstr (L"Miäs");
Mitenhän saisin muunnettua stringin wstringiksi niin, että ne ääkköset sun muut löytyvät sieltä vertailussa?
Minusta se toimii aivan täsmälleen oletusten mukaan: väärin. Viitsisitkö nyt tajuta edes sen perusasian, että UTF-8-enkoodattu "ä" on sama kuin "\xc3\xa4"? Et siis voi mitenkään käsitellä sitä tavu kerrallaan, koska saat silloin vain tavun '\xc3' tai '\xa4' eikä kummastakaan voi yksinään tunnistaa ä-kirjainta. Kaikki viritelmäsi tekevät aivan täsmälleen saman virheen.
Wikipedian UTF-8-artikkelissa on selvä kuvaus merkkien koodauksesta. Voit tehdä sen pohjalta funktion, joka erottelee yksittäiset UTF-8-merkit, jotka siis ovat usean tavun mittaisia. Voit siis sijoittaa yhden merkin yhteen std::string-muuttujaan ja tehdä vertailun normaaliin tapaan merkkijonoilla: merkki == "ä". Halutessasi voit muuttaa yksittäiset UTF-8-merkit (tavujonot) vielä wchar_t-merkeiksi eli yksittäisiksi Unicode-arvoiksi.
Lyhyesti sanottuna kelvollinen UTF-8-merkki on tavu, jossa ylin bitti on nolla ((x & 0x80) == 0), tai tavujono, jonka ensimmäisen tavun ylimmät bitit ovat 11 ((x & 0xc0) == 0xc0) ja jossa on yhtä monta tavua kuin ykkösbittiä ensimmäisen tavun alussa.
Metabolix kirjoitti:
Viitsisitkö nyt tajuta edes sen perusasian, että UTF-8-enkoodattu "ä" on sama kuin "\xc3\xa4"?
Viitsisin. Kiitos.
Aihe on jo aika vanha, joten et voi enää vastata siihen.