Vaikka C++:sta löytyykin hyvä merkkijonoluokka <string>, niin joudumme silti tutustumaan myös puhtaan C- kielen merkkijonoihin. Miksikö? Koska esimerkiksi sijoituksessa
cpp_jono = "Kissa";
sijoitetaan tosiasiassa C- merkkijono C++:n merkkijonoon. Lisäksi valtava määrä valmiista aliohjelmista haluaa parametrikseen nimenomaan C- merkkijonon tai palauttaa C- merkkijonon. Itse asiassa C++:n merkkijonojen käyttö on vielä tänä päivänä (2002) ei ole yleistä edes kaikissa C++:n omissakaan funktiokirjastoissa.
Tämä on sääli, sillä suurin osa C:n "huonoudesta" johtuu nimenomaan aloittelijoiden (ja kokeneidenkin) käsissä VAARALLISISTA merkkijonoista. Valtava määrä UNIXeistakin löytyvistä tietoturva- aukoista perustuu väärin käytettyihin merkkijonoihin! Näytimmekin jo aikaisemmin valmiiden olioluokkien kohdalla muutamia asioita, joita EI voi tehdä C- merkkijonoilla, tai jotka näyttävät hyvältä, mutta toimivat väärin. Nyt tutustumme vähän tarkemmin ongelmien syihin ja siihen miten niitä voidaan välttää.
Vinkki
A
Varaa tila myös loppumerkille
C- kielen merkkijonot eivät ole mitään muuta kuin taulukoita kirjaimista. Merkkijonoista on kuitenkin sovittu, että merkkijonon lopuksi taulukossa on merkki jonka koodi on 0 (NUL, '\0'). Siis merkkijono täytyy muistaa varata yhtä alkiota isommaksi , kuin aiottu merkkien maksimimäärä.
Huomattakoon, ettei ole olemassa valmista NUL- vakiota, vaan pitää käyttää joko muotoa 0 tai ' \0'.
string.h- kirjastosta löytyy iso kasa merkkijonojen käsittelyyn tarkoitettuja aliohjelmia. Esimerkiksi sijoitus
elain = "Kissa"
ei onnistu (tai onnistuu, muttei kopioi merkkejä "Kissa" taulukkoon elain), vaan on käytettävä jotakin funktioita (esimerkiksi huippuvaarallista strcpy funktiota):
char elain[12]; strcpy(elain,"Kissa"); /* VAARALLINEN!!! Tässä toimii!!! */ ... Seuraavassa koodit on esitetty heksana ja ? tarkoittaa ettei muistipaikan arvoa tunneta. elain | 0 1 2 3 4 5 6 7 8 9 10 11 | +-----------------------------------+ +--->|4B|69|73|73|61|00| ?| ?| ?| ?| ?| ?| +-----------------------------------+ K i s s a NUL ? ? ? ? ? ?
Merkkijonon pituus voitaisiin laskea seuraavalla aliohjelmalla:
int pituus(const char jono[]) { int i; for (i=0; jono[i]; i++); return i; } /* Tai: */ int pituus(const char jono[]) /* const char [] ei char [] */ { /* koska jonoa ei muuteta */ char *p; for (p=jono; *p; p++); return p- jono; }
Tosin string.h:sta löytyy funktio strlen, joka tekee täsmälleen saman asian.
Funktio pituus voitaisiin aivan yhtä hyvin esitellä:
int pituus(const char *jono)