Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: järjestys

cloudi [20.12.2003 14:46:26]

#

Voisko joku jelpsiä, miten tää ois järkevin. yritin pilkotella tätä jutskaa osiin, mut eips sitte tulosta-homma onnista.

#include <iostream>
#include <string>

using namespace std;
const string erottimet = " ,.\"\n";                	// Sanojen erotinmerkit
const int max_sanoja = 1000;                        // Sanojen maksimimäärä
void tulosta(string *psanat,int sanaLkm);


void lue(string teksti)
{
	// Luetaan merkkijono näppäimistöltä
  cout << endl << "Syötä merkkijono, # lopettaa:" << endl;
  getline(cin, teksti, '\n');

}

int sana_irrotus(string teksti)
{
	 // Otetaan tekstin kaikki sanat erilleen
  int alku = teksti.find_first_not_of(erottimet);		// Sanan alkuindeksi
  int loppu = 0;                                        // Loppuerotinmerkin indeksi
  int sanaLkm = 0;

 string sanat[max_sanoja];                             	// Sanojen taulukko
   string* psanat[max_sanoja];                     	// osoitintaulukko sanoihin

//yksitt. sanojen irrottaminen mjonosta ja tallett. taulukkoon silmukalla
  while(alku != string::npos && sanaLkm < max_sanoja)
  {
    loppu = teksti.find_first_of(erottimet, alku + 1);
    if(loppu == string::npos)                               	//  erotinmerkki?
      loppu = teksti.length();                               	// Ei löytynyt

    sanat[sanaLkm] = teksti.substr(alku, loppu - alku); 	// Talletetaan sana
    psanat[sanaLkm] = &sanat[sanaLkm];             	        // Talletetaan osoitin
    sanaLkm++;                                        		// kasvatetaan lukumäärää

    // Etsitään seuraavan sanan ensimmäinen merkki
    alku = teksti.find_first_not_of(erottimet, loppu + 1);
  }
	return sanaLkm;
}

void lajittele(string teksti, int sanaLkm)
{

//  pitää kirjaa "pienimmän" sanan indeksistä lajittelun aikana:
  string* psanat[max_sanoja];                     	// osoitintaulukko sanoihin

  int pienin = 0;                                   // Pienimmän sanan indeksi

  for(int j = 0; j < sanaLkm - 1; j++)
  {
    pienin = j;                                     // Asetetaan pienin

//Tarkistetaan nykyinen sana kaikkiin muihin sen jäljessä oleviin sanoihin
    for(int i = j + 1 ; i < sanaLkm ; i++)
      if(*psanat[i] < *psanat[pienin])              // Nykyinen on pienin?
        pienin = i;

    if(pienin != j)
    {                                               //Vaihdetaan osoittimet
      string* papu = psanat[j];                     //
Talletetaan nykyinen
      psanat[j] = psanat[pienin];                   // Pienin nykyiseen
      psanat[pienin] = papu;                        // Palautetaan nykyinen
    }

  }

  //return !(int)psanat;
}

void tulosta(string *psanat ,int sanaLkm)
{

//psanat-taulukon alkiot osoittavat sanoihin nous.järjestyksessä.
// Tulostetaan sanat nousevassa järjestyksessä
 for(int  i = 0 ; i < sanaLkm ; i++)
    cout << endl << psanat[i]  ;      //EI TULOSTA VAAN EI

}


int main()
{
	 int lkm=0;
 	string teksti;           // Lajiteltava merkkijono


  lue(teksti);
  sana_irrotus(teksti);
  lajittele(teksti,lkm);
  tulosta(teksti,lkm );


  cout << endl;
  return 0;
}

Meca [20.12.2003 21:03:30]

#

Voisit ensin vaikka kertoa mitä ohjelman olisi tarkoitus tehdä, auttaisi vähän jyvälle pääsemisessä.

Muutamia huomioita ohjelmastasi:

Lue()-funktio ei palauta luettua merkkijonoa mitenkään. Voit joko muuttaa teksti-muuttujan pointteriksi näin:

lue(string *teksti) //Funktion esittely
getline(cin, *teksti, '\n'); //luetaan syöte
lue(&teksti); //Funktion kutsu pääohjelmassa

...tai muuttaa lue()-funktio string-tyyppiseksi, jolloin voit palauttaa muuttujan return-lauseella.

Sama juttu on sana_irrotus()-funktiossa. Se kyllä palauttaa lukumäärän, mutta sitä ei lueta pääohjelmassa mihinkään.
Niinpä seuraavaksi lajittele()-funktiolle välittyy lukumääräksi 0. Lukumäärän saat talteen muuttamalla pääohjelmaa näin:
lkm=sana_irrotus(teksti);
En oikein päässyt jyvälle pitäisikö tämän funktion palauttaa jokin sanataulukko, joka on tarkoitus tulostaa, vai mikä on idea?

cloudi [21.12.2003 16:32:48]

#

olis tarkotus et nousevaan järjestykseen sanat tulostaa. ja kyllähän se niin tekis oikeesti, mut jos osasiks laittaa niin eips sitte niin helppoo ookkaa! ja mä täs lähin niinku mahollisimman helppo? void-tyylillä.. mutta olisi ihanteellista jos return-systeemillä olisi.

Meca [22.12.2003 11:09:58]

#

Näin sen voi ainakin tehdä:

#include <iostream>
#include <string>

using namespace std;
const string erottimet = " ,.\"\n";     // Sanojen erotinmerkit
const int max_sanoja = 1000;            // Sanojen maksimimäärä
string lue();
int sana_irrotus(string , string []);
void lajittele(string[], int);
void tulosta(string[], int);

string lue()
{
    string teksti;
   // Luetaan merkkijono näppäimistöltä
  cout << endl << "Syötä merkkijono, # lopettaa:" << endl;
  getline(cin, teksti, '\n');
  return teksti;
}

int sana_irrotus(string teksti, string sanat[max_sanoja])
{
     // Otetaan tekstin kaikki sanat erilleen
  int alku = teksti.find_first_not_of(erottimet);        // Sanan alkuindeksi
  int loppu = 0;                                        // Loppuerotinmerkin indeksi
  int sanaLkm = 0;

//yksitt. sanojen irrottaminen mjonosta ja tallett. taulukkoon silmukalla
  while(alku != string::npos && sanaLkm < max_sanoja)
  {
    loppu = teksti.find_first_of(erottimet, alku + 1);
    if(loppu == string::npos)                                   //  erotinmerkki?
      loppu = teksti.length();                                   // Ei löytynyt

    sanat[sanaLkm] = teksti.substr(alku, loppu - alku);     // Talletetaan sana
    sanaLkm++;                                                // kasvatetaan lukumäärää
    // Etsitään seuraavan sanan ensimmäinen merkki
    alku = teksti.find_first_not_of(erottimet, loppu + 1);
  }
    return sanaLkm;    //Palautetaan sanojen lukumäärä
}

void lajittele(string sanoja[max_sanoja], int sanaLkm)
{
  int pienin = 0;                                   // Pienimmän sanan indeksi
  for(int j = 0; j < sanaLkm - 1; j++)
  {
    pienin = j;                                     // Asetetaan pienin

    //Tarkistetaan nykyinen sana kaikkiin muihin sen jäljessä oleviin sanoihin
    for(int i = j + 1 ; i < sanaLkm ; i++)
    {
      if(sanoja[i] < sanoja[pienin])              // Nykyinen on pienin?
        pienin = i;
    }

    if(pienin != j)
    {
      string papu = sanoja[j];                     // Talletetaan nykyinen
      sanoja[j] = sanoja[pienin];                   // Pienin nykyiseen
      sanoja[pienin] = papu;                        // Palautetaan nykyinen
    }
  }
}

void tulosta(string sanoja[max_sanoja] ,int sanaLkm)
{

//psanat-taulukon alkiot osoittavat sanoihin nous.järjestyksessä.
// Tulostetaan sanat nousevassa järjestyksessä
 for(int  i = 0 ; i < sanaLkm ; i++)
    cout << endl << sanoja[i]  ;      //PITÄISI TULOSTAA
}


int main()
{
     int lkm=0;
     string teksti,sanoja[max_sanoja];
     teksti=lue();                          //Funktio palauttaa syötetyn tekstin
     lkm=sana_irrotus(teksti,sanoja);  /*Funktio palauttaa sanojen määrän ja
      taulukkoon luetut sanat. Taulukon kanssa ei tarvitse käyttää pointterimerkkiä * koska
      taulukon nimi itsessään on osoite muistipaikkaan. */

     lajittele(sanoja,lkm); //Välitetään sanataulukko ja lukumäärä
     tulosta(sanoja,lkm ); //Välitetään sanataulukko ja lukumäärä
     cout<<endl;
     system("PAUSE");
     return 0;
}

Tuota voi tietysti viilata monella tapaa paremmaksikin. Lajittelufunktio on mahdollista tehdä tehokkaammin ja sen lajitteluun on olemassa valmiita kirjastofunktioita kuten qsort. Lisäksi talukon voisi tehdä dynaamisesti, niin ei haaskattaisi muistitilaa, mutta noin pienessä ohjelmassa sillä ei käytännössä ole merkitystä.

cloudi [22.12.2003 12:12:12]

#

jees toimii. pitäs kyl opiskella tota muisti-jutskaa!

Vastaus

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

Tietoa sivustosta