Siirry sisältöön

C/Merkkijonot

Wikikirjastosta
< C

Tämä luku kertoo C:n merkkijonoista.

C-kielessä ei varsinaisia merkkijonoja ole, vaan merkkijonona käytetään char- eli merkkitaulukkoa. Merkkijono päätetään normaalisti nollamerkillä, joka esitetään \0. Kyseinen merkki ei ole suinkaan numeron 0 merkki, vaan se merkki, jonka koodi on 0. Se on ehtolauseessa ainoa epätosi merkki.

Merkkijonon lopun ilmaisee täysin kyseinen nollamerkki. Jos se puuttuu, merkkijono voi 'jatkua' hamaan ikuisuuteen, ellei sen pituutta ilmaista jotenkin muuten.

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. Huomaathan kuitenkin, että funktioiden parametreissa taulukoista tulee osoittimia, jolloin tämä ei enää toimi. const char *:sta ei saa merkkijonon pituutta mitenkään sizeof-operaattorilla.

Merkkijonon ei tarvitse olla const-osoitin, 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 on muistisegmentissä, johon prosessilla on vain lukuoikeus).

const yleensä puuttuu vain, jos merkkijonoa halutaan muokata. Jos merkkijonoa täytyy pystyä muokkaamaan, tulee se varata joko keosta (str3), tai pinosta (str4).

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

Pinossa olevan merkkijonon voi myös alustaa (str5), mutta se tulee tehdä str2:n tavoin (str1:n tapa ei sovi tähän yhteyteen).

char str5[] = { 'M', 'e', 'r', 'k', 'k', 'i', 'j', 'o', 'n', 'o', '\0' };

Merkkijono keossa, tai alustamattomana pinossa, pitää alustaa itse. Siihen voidaan kopioida esim. merkkijonovakio merkkijonon kopiointiin käytettävillä funktioilla. Sijoitusoperaattoria = ei voi käyttää merkkijonon kopiointiin, koska se ainoastaan sijoittaa osoitteen, ei varsinaista sisältöä. Näin tehtyyn kopioon tehty muutos vaikuttaa myös alkuperäiseen merkkijonoon. Siksi yleensä halutaankin käyttää varsinaisia kopiointifunktioita (ks. string.h):

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 on kirjoitettavissa oleva muistialue, johon merkkijonon tulee mahtua kokonaisuudessaan, loppuun tuleva nollamerkki mukaan lukien. Funktio palauttaa dest:n arvon. Funktio ei tarkista, onko dest:ssä riittävästi tilaa, joten se ei ole erityisen turvallinen.

Jälkimmäinen tarkistaa myös, että dest-alueelle kirjoitetaan korkeintaan n merkkiä. Jos tila ei riitä, kopiointi loppuu kesken kaiken ja kopion loppuun ei lisätä nollamerkkiä. 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 ajaa puskurin yli (engl. buffer overflow), joka on yleisin tietoturva-aukkojen syy.

Merkkijonoja ei voi myöskään vertailla ==-operaattorilla, sillä se vertailee osoitteita eikä niiden sisältöä; C-merkkijonothan ovat osoittimia. 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 nollamerkin, eivätkä yritä jatkaa lukemista sen jälkeen.

Erikoismerkit

[muokkaa | muokkaa wikitekstiä]

Merkkijonoliteraaleissa voi olla erilaisia erikoismerkkejä, jotka ilmaistaan kenoviivalla (\).

Esitysmuoto Selitys
\\ Kenoviiva (jotta sen voi kirjoittaa literaaleihin sellaisenaan)
\0 Nollamerkki, merkkijonon päättävä loppumerkki, jonka koodi on 0.

Tätä ei tarvitse kirjoittaa itse merkkijonoliteraalin loppuun, sillä se lisätään automaattisesti.

\a Hälytysmerkki, soittaa esim. äänimerkin
\b Siirtää kohdistinta yhden merkin taaksepäin
\f Siirtää kohdistimen seuraavalle sivulle (päätteessä yleensä vain rivin alaspäin)
\n Rivinvaihto; teknisesti siirtää kohdistinta rivin alaspäin
\r Rivinvaihdon alkuosa joillain järjestelmillä, esim. Windows, jossa kokonainen rivinvaihto on \r\n.

Teknisesti siirtää kohdistimen rivin alkuun.

C-kirjasto kuitenkin kääntää rivinvaihdot automaattisesti oikeaan muotoon tekstiä tulostaessa.

\t Sarkainmerkki; siirtää kohdistinta eteenpäin
\v Siirtää kohdistinta alas ohi sivun ylämarginaaliin (päätteessä yleensä vain rivin alaspäin)
\' Merkkiliteraali: puolilainausmerkki, esim. '\''
\" Merkkijonoliteraali: kokolainausmerkki, esim. "\"sana\" lainausmerkeissä"

Jos kenoviivaa seuraa 0 ja numeroita 1-7 (korkeintaan kolme), silloin merkki ilmaistaan koodillaan oktaalilukuna; esim. koodi 39 (heittomerkki tai puolilainausmerkki) on oktaalina 47, joten \047 tai \0047 vastaa sitä.

Jos kenoviivaa seuraa x, seuraavat kaksi merkkiä 0-F tulkitaan heksadesimaalilukuna ja lukua vastaava merkki ilmaistaan koodillaan. Leveissä merkeissä heksadesimaalinumeroita voi olla useampi; esim. koodi 39 on heksadesimaalina 27, joten \x27 vastaa merkkiä 39, eli heittomerkkiä tai puolilainausmerkkiä.

C-ohjelmointikieli

EtusivuHistoriaTyökalut


Yksinkertainen C-kielinen ohjelmaMuuttujatOperaattoritKommentitOhjausrakenteetFunktiotOsoittimetDynaaminen muistinvarausTaulukotMerkkijonotTietueetEsikääntäjäOtsikkotiedostot


C-kielen varatut sanatStandardikirjastoAiheesta muualla