C- kielen char jono[10] on todellinen aikapommi, jonka aukkoisuuteen perustuu vielä tänäkin päivänä useat hakkereiden kikat murtautua vieraisiin tietojärjestelmiin. Katsotaanpa ensin mitä C- merkkijonoille voi/ei voi tehdä:
char s1[10],s2[5],*p; p = "Kana" // Toimii! p[0] = 'S'; // Toimii! Mutta jatkossa käy huonosti... s1 = "Kissa"; // ei toimi! strcpy(s2,"Koira"); // Huonosti käy! Miksi? Älä käytä koskaan... if ( s1 < s2 ) ... // Sallittu, mutta tekee eri asian kuin lukija arvaakaan... gets(s1); // Itsemurha, tämä on eräs kaikkein hirveimmistä funktioista // lukee päätteeltä rajattomasti merkkejä ... fgets(s1,sizeof(s1),stdin); // Oikein! Tosin rivinvaihto jää jonoon jos syöte // on lyhyempi kuin printf(s1); // Ohohoh! Tämä jopa toimii!!! cout << s1; // Ja jopa tämäkin!!! cin >> s1; // Taas itsemurha ....Palaamme myöhemmin monisteessa C:n merkkijonoihin, ja siihen miten niitä voidaan kohtuullisen turvallisesti käyttää.
Onneksi C++:aan on tulossa kohtuullinen merkkijonoluokka. Nyt jo! Yli 10 vuotta kielen kehittämisen jälkeen...
Merkkijonoluokalla voi tehdä mm. seuraavia:
#include <iostream.h> #include <string> using namespace std; int main(void) { string mjono1 = "Ensimmainen"; string mjono2 = "Toinen"; string mjono; // syotto ja tulostus cout << "Anna merkkijono > "; getline(cin,mjono,'\n'); cout << "Annoit merkkijonon : " << mjono << endl; // kasittely merkeittain mjono[0] = mjono1[4]; mjono[1] = mjono2[1]; mjono[2] = 't'; mjono[3] = '\0'; // Laitonta jos merkkijono ei ole nain iso! // Ei vaikuta! cout << mjono << endl; // tulostaa: mot ...+jotakin // sijoitukset mjono = mjono1; cout << mjono << endl; // Ensimmainen mjono = "Eka"; cout << mjono << endl; // Eka // katenointi mjono = mjono1 + mjono2; cout << mjono << endl; // EnsimmainenToinen mjono = mjono1 + "Toka"; cout << mjono << endl; // EnsimmainenToka mjono = "Eka" + mjono2; cout << mjono << endl; // EkaToinen // vertailut if (mjono1 == mjono2) cout << "1 on 2" << endl; // ei tulosta if (mjono1 == "Apua") cout << "1 on Apua" << endl; // ei tulosta if ("Apua" == mjono2) cout << "Apua on 2" << endl; // ei tulosta if (mjono1 != mjono2) cout << "1 ei ole 2" << endl; // 1 ei ole 2 if (mjono1 != "Apua") cout << "1 ei ole Apua" << endl; // 1 ei ole Apua if ("Apua" != mjono2) cout << "Apua ei ole 2" << endl; // Apua ei ole 2 if (mjono1 < mjono2) cout << "1 pienempi kuin 2" << endl; // 1 pienempi ku if (mjono1 < "Apua") cout << "1 pienempi kuin Apua" << endl; // ei tulosta if ("Apua" < mjono2) cout << "Apua pienempi kuin 2" << endl; // Apua pienempi if (mjono1 > mjono2) cout << "1 suurempi kuin 2" << endl; // ei tulosta if (mjono1 > "Apua") cout << "1 suurempi kuin Apua" << endl; // 1 suurempi ku if ("Apua" > mjono2) cout << "Apua suurempi kuin 2" << endl; // ei tulosta // nama eivat valttamattomia, mutta jollekin voi tulla mieleen kayttaa... if (mjono1 <= mjono2) cout << "1 pienempi tai yhtasuuri kuin 2" << endl; if (mjono1 >= mjono2) cout << "1 suurempi tai yhtasuuri kuin 2" << endl; // Vastaavat vakiomerkkijonoilla EI onnistu, koska vakiomerkkijonot ovat // OSOITTIMIA! #if 0 // Seuraavat jos linkittaa: mjonot.c ja string.cpp mjono1.remove(4,2); cout << mjono1 << endl; // Ensiainen mjono1.insert(4,"mm"); cout << mjono1 << endl; // Ensimmainen #endif return 0; }Luokan string pitäisi tulla nykyisten C++- kääntäjien mukana. Se saadaan käyttöön lisäämällä koodin alkuun:
#include <string> // Otetaan standardiehdotelman merkkijonoluokka using namespace std; // nyt ei tarvitse kirjoittaa std::stringJos koneessa on niin vanha kääntäjä, ettei uudet luokat käänny sillä (ei esim. poikkeutusten käsittelyä), voi käyttää \kurssit\c\ali hakemistosta löytyvää "lasten" vastinetta, string, eli em. testiohjelma toimii jos otsikkotiedostojen hakupolkuun lisätään mainittu ali- hakemisto.
// Taydenna ja korjaile. Mista puuttuu virtual? Mista const? // Mita metodeja viela puuttuu? #include <iostream.h> #include <string> using namespace std; class cHenkilo { string nimi; int ika; double pituus_m; public: cHenkilo(string inimi="???",int iika=0,int ipituus=0) {} void tulosta() {} void kasvata(double cm) {} }; class cOpiskelija : public cHenkilo { double keskiarvo; public: cOpiskelija(string inimi="???",int iika=0, int ipituus=0, int ikarvo=0.0) : cHenkilo(inimi,iika,ipituus), keskiarvo(ikarvo) {} }; int main(void) { cHenkilo Kalle("Kalle",35,1.75); Kalle.tulosta(); Kalle.kasvata(2.3); Kalle.tulosta(); cOpiskelija Ville("Ville",21,1.80,9.9); Ville.tulosta(); return 0; }