Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: tiedostosta kaikki sanat

Sivun loppuun

Hakoulinen [24.11.2007 21:56:15]

#

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.

Antti Laaksonen [24.11.2007 22:31:21]

#

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;
}

Hakoulinen [24.11.2007 22:37:07]

#

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.

Antti Laaksonen [24.11.2007 22:44:56]

#

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.

Hakoulinen [24.11.2007 22:54:51]

#

Mitenkäs sitten pituuksilla vertailu?

Antti Laaksonen [24.11.2007 23:04:32]

#

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.

Metabolix [25.11.2007 15:56:28]

#

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.

lukujenVihaaja [28.11.2007 12:46:46]

#

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).


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta