Miten saan luettua tekstitiedostossa jokaisen omalla rivillään olevan sanan muuttujaan, niin, että niitä olisi helppo järjestää pituuden ja aakkosten mukaan? Ja toinen kysymys onkin sitten, että miten niitä voi järjestellä aakkosten mukaan?
strcmp taitaa olla vastaus aakkosjärjestykseen ainakin.
Tässä tulee C-kielinen esimerkki, joku muu osaa ehkä laatia vastaavan C++-ohjelman.
Funktion strcmp avulla merkkijonot saa tosiaan kätevästi aakkosjärjestykseen, kun käytetään lisäksi qsort-funktiota.
#include <stdio.h> #include <stdlib.h> #include <string.h> /* tähän mahtuu 1000 alle 30-kirjaimista sanaa */ char sanat[1000][30]; /* tässä säilytetään sanojen määrää */ int maara = 0; /* tämän avulla käsitellään tiedostoa */ FILE *tiedosto; int main(void) { int i; /* luetaan sanat tiedostosta taulukkoon */ tiedosto = fopen("sanat.txt", "r"); while (!feof(tiedosto)) { fscanf(tiedosto, "%s", sanat[maara]); maara++; } fclose(tiedosto); /* järjestetään sanojen taulukko */ qsort(sanat, maara, sizeof(char) * 30, strcmp); /* tulostetaan järjestetyt sanat */ for (i = 0; i < maara; i++) { printf("%i: %s\n", i + 1, sanat[i]); } return 0; }
Kiitos paljon jälleen Antti :)
Mutta iskee varotusta kääntäessä: "tiedosto.c: In function ‘main’:
tiedosto.c:26: warning: passing argument 4 of ‘qsort’ from incompatible pointer type
"
EDIT: mutta ei tuo mitään taida haitata kun oikein toimii kumminkin.
Varoituksen saa pois muuttamalla qsort-riviä näin:
qsort(sanat, maara, sizeof(char) * 30, (int (*)(const void *, const void *))strcmp);
Minusta kuitenkin alkuperäinen koodi on luettavampi.
Mitenkäs sitten pituuksilla vertailu?
Siihen voi tehdä oman vertailufunktion:
int omaver(char *a, char *b) { if (strlen(a) == strlen(b)) return strcmp(a, b); return strlen(a) - strlen(b); }
Vielä pitää muuttaa qsort-riviä:
qsort(sanat, maara, sizeof(char) * 30, omaver);
Nyt sanat järjestetään ensisijaisesti pituuden mukaan, mutta jos sanat ovat yhtä pitkiä, ne järjestetään aakkosjärjestyksen mukaan.
C++-ohjelmana:
// Laajeneva taulukko #include <vector> // Luokka tekstiä varten #include <string> // Tiedosto- ja standardivirrat #include <fstream> #include <iostream> // Mm. lajittelualgoritmi #include <algorithm> using namespace std; // Vertailufunktio pituusjärjestystä varten, huomaa const-avainsanat ja valinnaisesti optimointia auttavat viittaukset (&) ja inline-sana. inline bool pidempi(string const& a, string const& b) { return a.length() > b.length(); } // Tulostusfunktio vektorin tulostamista varten, parametreina tulostusvirta ja vektorillinen tekstejä void tulosta(ostream& out, vector<string> const& vektori) { vector<string>::const_iterator i; for (i = vektori.begin(); i != vektori.end(); ++i) { out << *i << endl; } } int main() { ifstream ifs; string rivi; vector<string> rivit; // Avataan tiedosto, luetaan rivit ja suljetaan tiedosto. ifs.open("sanat.txt"); while (getline(ifs, rivi)) { // Tai vain yhtä sanaa varten (ifs >> sana) rivit.push_back(rivi); } ifs.close(); // Normaali järjestys string-tyypin <-operaattorilla sort(rivit.begin(), rivit.end()); cout << "Normaali järjestys:\n"; tulosta(cout, rivit); // Pituusjärjestys omalla vertailufunktiolla: sort(rivit.begin(), rivit.end(), pidempi); cout << "Pituusjärjestys:\n"; tulosta(cout, rivit); return 0; }
C++:n sort-funktio on yleensä nopeampi kuin C:n qsort, koska kääntäjä pystyy optimoimaan sen juuri tuohon tilanteeseen sopivaksi. Normaaleilla C:n taulukoilla sitä käytetään näin:
TYYPPI taulukko[KOKO]; sort(taulukko, taulukko + KOKO); // Ja valinnaisesti vertailufunktio
Ensimmäinen parametri siis osoittaa ensimmäiseen lajiteltavaan alkioon ja toinen parametri alkioon, jota ei lajitella ja jota ei edes välttämättä ole oikeasti olemassa.
Metabolix kirjoitti:
C++:n sort-funktio on yleensä nopeampi kuin C:n qsort, koska kääntäjä pystyy optimoimaan sen juuri tuohon tilanteeseen sopivaksi.
Nopeuseroon on muitakin syitä. Siinä missä qsort-funktio käyttää nimensä mukaisesti quicksort-algoritmia, on c++:n sort-funktion pohjalla introsort-algoritmi (joka tosin osin hyödyntää quicksortin ideaa, mutta on kuitenkin eri algoritmi).
Aihe on jo aika vanha, joten et voi enää vastata siihen.