C/Merkkijonot

Wikikirjastosta
< C

Tämä luku kertoo C:n merkkijonoista.

C-kielessä ei varsinaisia merkkijonoja ole, vaan merkkijonona käytetään char-taulukkoa. Merkkijono päätetään normaalisti 0-merkillä, siis '\0'. Seuraavassa kaksi samanlaista merkkijonoa, joista ensimmäisessä käytetään kaksoislainausmerkkejä ja toinen puolestaan on kirjaimellisesti esitetty char-taulukkona. Tulos on kummassakin tapauksessa melkein sama. Ensimmäinen esimerkki tekee pointterin merkkijonovakioon, kun taas jälkimmäinen luo taulukon, jonka alkiot alustetaan merkkijonon merkeillä.

const char* str1 = "Merkkijono";
const char str2[] = { 'M', 'e', 'r', 'k', 'k', 'i', 'j', 'o', 'n', 'o', '\0' };

Yllä oleva merkkijono taulukossa näyttäisi tältä.

Merkkijono char-taulukossa.

Taulukkoluonteesta johtuen merkkijonoa voi käyttää aivan kuten taulukkoa ja sen käyttöä koskevat myös samat rajoitukset. Huomionarvoista on myös että sizeof()-operaattori palauttaa koon tavuina, jossa myös nollamerkki on huomioitu. Merkkijonon ei tarvitse olla const-pointteri, mutta merkkijonovakioita (lainausmerkit) käytettäessä on hyvän tavan mukaista menetellä näin. Kääntäjä ei yleensä anna virheilmoitusta merkkijonovakion const-määreen puuttumisesta tai sen puuttuessa vakion ylikirjoituksesta, mutta ohjelma todennäköisesti kaatuu siihen (jos merkkijono muistisegmentissä, johon prosessilla on vain lukuoikeus).

Jos merkkijonoa täytyy pystyä muokkaamaan, tulee se varata joko heapista (str3), tai stackista ilman alustusta (str4).

char* str3 = malloc(11);
char str4[11];

Tällöin olemassaoleva merkkijono (esim. merkkijonovakio) voidaan siihen kopioida merkkijonon kopiointiin käytettävillä funktioilla. Koska C-merkkijono on pointteri, ei sijoitusoperaattori = kopioi merkkijonoa, vaan sen osoitteen. Näin tehtyyn kopioon tehty muutos vaikuttaa myös alkuperäiseen merkkijonoon. Siksi yleensä halutaankin käyttää varsinaisia kopiointifunktioita:

char* strcpy(char* dest, const char* src);
char* strncpy(char* dest, const char* src, size_t n);

Ensimmäisessä funktiossa src on kopioitava merkkijono ja dest taasen on kirjoitettavissa oleva muistialue, johon merkkijonon tulee mahtua kokonaisuudessaan, mukaanlukien loppuun tuleva null-merkki. Funktio palauttaa dest:n arvon. Jälkimmäisessä erona on että dest-alueelle kirjoitetaan korkeintaan n merkkiä ja jos tila ei riitä, ei kopion loppuun tule null-merkkiä ja kopiointi loppuu kesken kaiken. Tässä tilanteessa on erittäin tärkeää ettet käytä kopion käsittelyyn pituusrajoittamattomia funktioita (niitä joiden nimessä ei ole ylimääräistä n-kirjainta), sillä ohjelmasi saattaa kaatua. Tästä pienestä rajoituksesta huolimatta kannattaa yleensä käyttää strncpy-versiota, koska toinen vaihtoehto on vähintään yhtä tuhoisa: kopiota kirjoitetaan yli sille varatun muistialueen ja syntyy nk. buffer overflow, joka on yleisin tietoturva-aukkojen syy.

Edelleen, koska C-merkkijono on pointteri arvokontekstissa, vertaa myös ==-operaattori merkkijonojen muistiosoitteita, eikä suinkaan merkkijonojen sisältöä. Sisällön vertailuun tulee käyttää seuraavia funktioita:

int strcmp(const char* s1, const char* s2);
int strncmp(const char* s1, const char* s2, size_t n);

Vertailufunktio palauttaa nollan jos merkkijonot ovat samanlaiset, negatiivisen arvon jos s1 on ASCII-aakkosissa ennen s2:a ja positiivisen jos s2 on ensin. Jälkimmäinen funktio vertaa korkeintaan ensimmäistä n:ää merkkiä (jos ne ovat samat, oletetaan merkkijonot samanlaisiksi). Erona myös taulukoiden kanssa toimivaan memcmp()-funktioon on että nämä funktiot tunnistavat merkkijonon lopettavan null-merkin, eivätkä yritä jatkaa lukemista sen jälkeen.

C-ohjelmointikieli

EtusivuHistoriaTyökalut


Yksinkertainen C-kielinen ohjelmaMuuttujatAritmeettiset operaatiotKommentitOhjausrakenteetFunktiotOsoittimetDynaaminen muistinvarausTaulukotMerkkijonotTietueet


C-kielen varatut sanatStandardikirjastoAiheesta muualla