Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Taulukon tyhjäys / poisto

Sivun loppuun

alottelijaa [01.05.2008 22:54:44]

#

Olen tekemässä dvd tietokantaa johon mahtuu 10 dvd:ta. niitä voi sitten lisäillä ja poistaa, mutta ei voi kirjottaa toisten DVD:en päälle. Onko mahdollista tyhjentää/poistaa tietueita jotka ovat taulukossa? tietueen rakenne on:

struct DVD
{
string nimi, nimi2, nimi3, nimi4, nimi5, maa;
char kesto2;
int vuosi, kesto, kesto3;

};

DVD elokuvat[10]; // <- Tämä

Eli onko mahdollista tyhjätä tietyn "solun" arvoa tai poistaa ko. solun kokonaan?

hunajavohveli [01.05.2008 23:03:48]

#

Taulukosta ei voi varsinaisesti poistaa alkioita, mutta voit esimerkiksi kopioida taulukon viimeisen alkion poistettavan alkion päälle. Kopioidun alkion tiedot ovat nyt taulukossa kaksi kertaa, joten samalla täytyy vähentää yhdellä jotain laskuria, joka kertoo taulukon viimeisen alkion indeksin. Yksityiskohdat riippuvat toteutuksestasi ja siitä, miten alkion poistamisen ylipäänsä pitäisi vaikuttaa ohjelman toimintaan.

Gaxx [01.05.2008 23:15:03]

#

Kun kerta c++ on käytössä niin käytä staattisten taulukoiden sijaan vektoreita.

Esimerkkejä tutkimalla pääset varmasti selville, kuinka niitä käytetään.

alottelijaa [01.05.2008 23:17:27]

#

Tähän mennessä olen saanut koodia tämän verran, mutta osassa koodia on varmasti huonoja/käyttökelvottomia ideoita :P Onnistuisiko esim. että laitan poisto funktioon jonkun muuttujan switch..caseen ja sitten kun menee lisäysfunktioon tietyssä alkiossa olevat tiedot voisi kirjoittaa uudelleen riippuen muuttujan arvosta? Sori jos on vähän epäselvää, olen aloitteleva ohjelmoija.

#include <iostream>

using namespace std;

struct DVD      //luodaan tietue
{
       string nimi, nimi2, nimi3, nimi4, nimi5, maa;
       char kesto2;
       int vuosi, kesto, kesto3;

};

int Lisays(DVD elokuvat[], int i);
int Poisto(DVD elokuvat[]);

int main()
{

    DVD elokuvat[10];
    char a=0;
    int i=0;
    while (i < 10){
    if (a == 'a' || a =='A'){i++;} //jos elokuva lisätään i nousee yhellä
    cout << "*************************************" << endl;
    cout << "* a) Elokuvan lis\x84\x84minen            *" << endl;
    cout << "*                                   *" << endl;
    cout << "* b) Elokuvan poistaminen           *" << endl;
    cout << "*                                   *" << endl;
    cout << "* c) Elokuvan tietojen muokkaaminen *" << endl;
    cout << "*                                   *" << endl;
    cout << "* s) Lopetus                        *" << endl;
    cout << "*               (c) aaaaa aaaaaa\x84aa *" << endl;
    cout << "*************************************" << endl;

    cin >> a;

    switch (a)
    {
           case 'a': case 'A':
           {
                if(i < 10){
                Lisays(elokuvat, i);
                break;}

           }

           case 'b': case 'B':
           {
                Poisto(elokuvat);
                break;
           }

           case 'c': case 'C':
           {
                cout << ":P" << endl;
                break;
           }

           case 's': case 'S': cout << "Kiitos k\x84ynnist\x84!" << endl;
           system("PAUSE");
           return EXIT_SUCCESS;

           default: cout << "Anna joku noista kirjaimista\n";
    }
                    }
    system("pause");

    return EXIT_SUCCESS;
}

int Lisays(DVD elokuvat[], int i)
{
    int sana;



        cout << "Montako sanaa elokuvan nimess\x84 on? ";
        cin >> sana;

        if (sana == 1)
        {
        cout << "Anna elokuvan nimi: ";
        cin >> elokuvat[i].nimi;
        }

        if (sana == 2)
        {
          cout << "Anna elokuvan nimi: ";
          cin >> elokuvat[i].nimi >> elokuvat[i].nimi2;
        }

        if (sana == 3)
        {
          cout << "Anna elokuvan nimi: ";
          cin >> elokuvat[i].nimi >> elokuvat[i].nimi2 >> elokuvat[i].nimi3;
        }

        if (sana == 4)
        {
          cout << "Anna elokuvan nimi: ";
          cin >> elokuvat[i].nimi >> elokuvat[i].nimi2 >> elokuvat[i].nimi3 >> elokuvat[i].nimi4;
        }

        if (sana == 5)
        {
        cout << "Anna elokuvan nimi: ";
        cin >> elokuvat[i].nimi >> elokuvat[i].nimi2 >> elokuvat[i].nimi3 >> elokuvat[i].nimi4 >> elokuvat[i].nimi5;
        }

        cout << "Anna elokuvan kesto muodossa tt:mm ";
        cin >> elokuvat[i].kesto >> elokuvat[i].kesto2 >> elokuvat[i].kesto3;

        cout << "Anna elokuvan ilmestymisvuosi: ";
        cin >> elokuvat[i].vuosi;

        cout << "Anna elokuvan maa: ";
        cin >> elokuvat[i].maa;







}

int Poisto(DVD elokuvat[])     //tässä tulostetaan elokuvien nimet ja voi valita jos haluaa poistaa jonkun
{



    cout << "Mink\x84 DVD:n haluat poistaa?" << endl;
    if (elokuvat[0].nimi !="")
    cout << "1. " << elokuvat[0].nimi << " " << elokuvat[0].nimi2 << " " << elokuvat[0].nimi3 << " " << elokuvat[0].nimi4 << " " << elokuvat[0].nimi5 << endl;
    if (elokuvat[1].nimi !="")
    cout << "2. " << elokuvat[1].nimi << " " << elokuvat[1].nimi2 << " " << elokuvat[1].nimi3 << " " << elokuvat[1].nimi4 << " "<< elokuvat[1].nimi5 << endl;
    if (elokuvat[2].nimi !="")
    cout << "3. " << elokuvat[2].nimi << " " << elokuvat[2].nimi2 << " " << elokuvat[2].nimi3 << " " << elokuvat[2].nimi4 << " "<< elokuvat[2].nimi5 << endl;
    if (elokuvat[3].nimi !="")
    cout << "4. " << elokuvat[3].nimi << " " << elokuvat[3].nimi2 << " " << elokuvat[3].nimi3 << " " << elokuvat[3].nimi4 << " "<< elokuvat[3].nimi5 << endl;
    if (elokuvat[4].nimi !="")
    cout << "5. " << elokuvat[4].nimi << " " << elokuvat[4].nimi2 << " " << elokuvat[4].nimi3 << " " << elokuvat[4].nimi4 << " "<< elokuvat[4].nimi5 << endl;
    if (elokuvat[5].nimi !="")
    cout << "6. " << elokuvat[5].nimi << " " << elokuvat[5].nimi2 << " " << elokuvat[5].nimi3 << " " << elokuvat[5].nimi4 << " "<< elokuvat[5].nimi5 << endl;
    if (elokuvat[6].nimi !="")
    cout << "7. " << elokuvat[6].nimi << " " << elokuvat[6].nimi2 << " " << elokuvat[6].nimi3 << " " << elokuvat[6].nimi4 << " "<< elokuvat[6].nimi5 << endl;
    if (elokuvat[7].nimi !="")
    cout << "8. " << elokuvat[7].nimi << " " << elokuvat[7].nimi2 << " " << elokuvat[7].nimi3 << " " << elokuvat[7].nimi4 << " "<< elokuvat[7].nimi5 << endl;
    if (elokuvat[8].nimi !="")
    cout << "9. " << elokuvat[8].nimi << " " << elokuvat[8].nimi2 << " " << elokuvat[8].nimi3 << " " << elokuvat[8].nimi4 << " "<< elokuvat[8].nimi5 << endl;
    if (elokuvat[9].nimi !="")
    cout << "10. " << elokuvat[9].nimi << " " << elokuvat[9].nimi2 << " " << elokuvat[9].nimi3 << " " << elokuvat[9].nimi4 << " "<< elokuvat[9].nimi5 << "\n" << endl;

}

EDIT: en huomannut tuota viestiä kun kirjoitin omaani. Katson tuota sivua huomenna. Kiitos vastanneille!

Mod. lisäsi kooditagit

Wezmel [02.05.2008 09:31:50]

#

Nopeasti vilkaistuna tuli mieleen muutama asia.

1. Kannattaisi varmaan käyttää cin.getline() metodia elokuvan nimen lukemiseen, niin ei tarvitse käyttää kuin yhtä muuttujaa.

2.

alottelijaa kirjoitti:

if (a == 'a' || a =='A'){i++;} //jos elokuva lisätään i nousee yhellä

Tuo indeksin kasvattaminen olisi mielestäni loogisemmassa paikassa Lisays-funktiossa.

3. Poisto-funktiossa elokuvien nimien tulostaminen kannattaisi ajaa luupissa.

4. DVD:n voisi toteuttaa ennemmin luokkana kuin structina. Silloin Lisäys- ja Poisto-funktiot voisivat olla DVD-luokan metodeja.

moptim [02.05.2008 09:56:23]

#

OBTI MOITU poistofunktio:

int Poisto(DVD elokuvat[])     //tässä tulostetaan elokuvien nimet ja voi valita jos haluaa poistaa jonkun
{
   cout << "Mink\x84 DVD:n haluat poistaa?" << endl;
    for(int i = 0; i <= 9; i++)
        if (elokuvat[i].nimi !="")
            cout << (char*) i + 1 <<" " << elokuvat[i].nimi << " " << elokuvat[i].nimi2 << " " << elokuvat[i].nimi3 << " " << elokuvat[i].nimi4 << " " << elokuvat[i].nimi5 << endl;
}

Taino tiiä onko optimoitu, silmukkahan hidastaa. :D

ed: Niin ja ei kai toi alkuperäinen esimerkki käänny, eiks sen pitäis olla typedef struct { ... } DVD; tai sit määrittelyssä jotain struct DVD munkiekko; (kiva jos saatte tosta selityksestä selvää ^_^)

alottelijaa [02.05.2008 12:03:13]

#

Juu taisin olla vähän väsynyt eilen kun tota kirjotttelin. koitan noita

Tumpelo [02.05.2008 12:34:59]

#

Kannattaa todellakin kokeilla vektoreiden käyttöä. Tässä pieni esimerkki:

using namespace std;

struct Auto
{
  int Teho;
  int Paino;
  string Merkki;
};

vector<Auto> Tietokanta;  // Tekee Auto-tietueista vektorin, joka on tässä vaiheessa tyhjä.

// Matin auto
Auto aMatti;
aMatti.Teho = 100;
aMatti.Paino = 800;
aMatti.Merkki = "Mazda";

// Mikon auto
Auto aMikko;
aMikko.Teho = 150;
aMikko.Paino = 1200;
aMikko.Merkki = "Saab";

// Tallennetaan tiedot tietokantaan
Tietokanta.push_back(aMatti); // Matin auto sijaitsee kohdassa Tietokanta[0]
Tietokanta.push_back(aMikko); // Mikon auto kohdassa Tietokanta [1]

... Siirrytään vaikka eri funktioon tai jtn ...

// Nyt halutaan lukea Matin auton tiedot jonka jälkeen Matti poistetaan :>
Auto aMatti;
aMatti = Tietokanta.at(0); // Tai Tietokanta[0] mutta se on huonompi tapa

//Jos halutaan vain teho talteen niin:
int Teho;
Teho = Tietokanta.at(0).Teho;

// Poistetaan Matti
Tietokanta.erase(Tietokanta.begin()); // Poistaa ensimmäisen elementin. Jos halutaan poistaa vaikka kolmas elementti niin: Tietokanta.erase(Tietokanta.begin() + 2)

// Nyt Mikko on kohdassa Tietokanta.at(0)
// Tietokannan perään voidaan taas lisätä tietoa push_back() komennolla

Sanokaa jos tuohon jäi aivopieruja.

alottelijaa [02.05.2008 17:21:54]

#

Tumpelo kirjoitti:

Kannattaa todellakin kokeilla vektoreiden käyttöä. Tässä pieni esimerkki:

(Mod. ihmettelee, miksi lainasit kaiken, kun tuossahan se päällä lukee.)

Kiitos tuo selkeytti asioita :D

alottelijaa [02.05.2008 18:31:11]

#

En tiedä, sori olin vähän kiireessä :/

alottelijaa [03.05.2008 13:51:53]

#

Muutin koodia jonkin verran ja sain pari uutta ongelmaa:

- jostain syystä poisto() funktiossa näkyy nimet vain kymmenennestä merkistä eteenpäin, ja jos laitan sinne esim.

tk[0+10].nimi

nimen tilalla näkyy jotain ihme merkkejä.

- jos koittaa kirjoittaa lyhyen nimen lisays() funktiossa nimi ei aina tallennu vaan pitää lisätä merkkejä.

- Onko mitään keinoa millä saisin lisättyä ominaisuuden joka poistaisi kaikki elokuvat? Koitin

tk.clear();

mutta se vasta ohjelmaa sekoittikin.

Olenko tehnyt jotain väärin vai mistä kiikastaa?

PS: älkää välittäkö ulkoasusta, voi sen siistiä myöhemminkin :)

#include <iostream>
#include <vector>

using namespace std;

struct DVD      //tietue DVD
{
       char nimi[25], kesto[6], maa[20];
       int vuosi;

};

vector<DVD> tk(10);   //luodaan vektori johon mahtuu 10 elokuvaa

int Lisays(DVD elokuvat,int i);
int Poisto(DVD elokuvat);

int main()
{

    DVD elokuvat;
    char a=0;
    int i=0;
    while (i < 10){

    if (a == 'a' || a =='A'){i++;} //jos lisätään elokuva i nousee yhdellä
    else if (a == 'b' || a == 'B'){i--;} //jos vähennetään i laskee yhdellä

    cout << "*************************************" << endl;
    cout << "* a) Elokuvan lis\x84\x84minen            *" << endl;
    cout << "*                                   *" << endl;
    cout << "* b) Elokuvan poistaminen           *" << endl;
    cout << "*                                   *" << endl;
    cout << "* c) Elokuvan tietojen muokkaaminen *" << endl;
    cout << "*                                   *" << endl;
    cout << "* s) Lopetus                        *" << endl;
    cout << "*                                   *" << endl;
    cout << "*************************************" << endl;

    cin >> a;

    switch (a)
    {
           case 'a': case 'A':
           {

                Lisays(elokuvat,i);
                break;

           }

           case 'b': case 'B':
           {
                Poisto(elokuvat);
                break;
           }

           case 'c': case 'C':   //ei vielä mitään
           {
                cout << "jotain viela" << endl;
                break;
           }

           case 's': case 'S': cout << "Kiitos k\x84ynnist\x84!" << endl;  //ohjelma loppuu
           system("PAUSE");
           return EXIT_SUCCESS;

           default: cout << "Anna joku noista kirjaimista\n";
    }
                    }

           system("PAUSE");

           return EXIT_SUCCESS;
}

int Lisays(DVD elokuvat, int i)
{





        cout << "Anna elokuvan nimi: ";

        cin.ignore('\n');                     //ei oteta huomioon rivinvaihtoa että getline toimii
        cin.getline(tk[i].nimi, 25);          //syötetään nimi
        tk.push_back(elokuvat);               // kannattaako tiedot tallentaa jokaisen kohdan jälkeen vai

        cout << "Anna elokuvan kesto muodossa tt:mm ";
        cin.getline (tk[i].kesto, 6);

        cout << "Anna elokuvan ilmestymisvuosi: ";
        cin >> elokuvat.vuosi;

        cout << "Anna elokuvan maa: ";
        cin >> elokuvat.maa;

        tk.push_back(elokuvat);     //vain kerran?





}

int Poisto(DVD elokuvat)
{

    char valinta = 0;





    cout << "Mink\x84 DVD:n haluat poistaa?\n" << endl;



    cout << "a) " << tk[0].nimi << endl;

    cout << "b) " << tk[1].nimi << endl;

    cout << "c) " << tk[2].nimi << endl;

    cout << "d) " << tk[3].nimi << endl;

    cout << "e) " << tk[4].nimi << endl;

    cout << "f) " << tk[5].nimi << endl;

    cout << "g) " << tk[6].nimi << endl;

    cout << "h) " << tk[7].nimi << endl;

    cout << "i) " << tk[8].nimi << endl;

    cout << "j) " << tk[9].nimi << "\n" << endl;



    cin >> valinta;

    switch (valinta)
    {
           case 'a':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin());                 //poistetaan elokuva
           break;
           case 'b':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 1);
           break;
           case 'c':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 2);
           break;
           case 'd':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 3);
           break;
           case 'e':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 4);
           break;
           case 'f':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 5);
           break;
           case 'g':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 6);
           break;
           case 'h':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 7);
           break;
           case 'i':
           cout << "\nelokuva on poistettu\n";
           tk.erase(tk.begin() + 8);
           break;
           case 'j':
           cout << "elokuva on poistettu\n";
           tk.erase(tk.begin() + 9);
           break;


           default: cout << "Vaan yll\x84 mainitut luvut kelpaa... ";
    }














}

os [03.05.2008 14:37:06]

#

cin.ignore('\n') ei varmasti tee sitä, mitä haluaisit. Se siis ei jätä rivivaihtoa (\n) huomiotta vaan poistaa virrasta '\n' = 10 ensimmäistä merkkiä.

Lisäksi merkkitaulukoiden, char[1234], tilalla kannattaa todellakin käyttää std::string-merkkijono-olioita

struct DVD {
   std::string nimi;
   // ...
};

Tällöin merkkitaulukko-getline pitää korvata string-getlinellä

DVD leffa;
//...
std::getline(std::cin, leffa.nimi);

Edit: Ja vaikka välttämättä haluaisit käyttää kirjaimia tuossa valinnassa, niin
niiden tulostamiseen kannattaa silti käyttää silmukkaa

std::vector<DVD> leffat;
// ...
for(unsigned i=0; i<leffat.size(); i++) // jos leffoja on korkeintaan 'z'-'a'+1 kpl
   std::cout << (char)('a'+i) << ") " << leffat[i].nimi << std::endl;

ja samoin lukeminen hoituu int numero = valinta-'a'; Ja "tietokannan" kokoa ei tietenkään kannata turhaan säätää valmiiksi kymmeneen leffaan, koska sen kokoa on helppo muuttaa.

Tumpelo [03.05.2008 14:40:40]

#

alottelijaa kirjoitti:

void Lisays()
{
        DVD sElokuvat;

        cout << "Anna elokuvan nimi: ";

        cin.getline(sElokuvat.nimi, 25);

        cout << "Anna elokuvan kesto muodossa tt:mm ";
        cin.getline (sElokuvat.kesto, 6);

        cout << "Anna elokuvan ilmestymisvuosi: ";
        cin >> sElokuvat.vuosi;

        cout << "Anna elokuvan maa: ";
        cin >> sElokuvat.maa;

        tk.push_back(sElokuvat);
}

Siinä tuo funktio korjattuna. Ensin siis täytetään väliaikainen DVD-structi tiedoilla ja lopuksi lisätään vektoriin se yksi tietue. Tietue lisätään aina vektorin loppuun, joten i-muuttujakin oli turha. Jätä lisäksi tuosta "vector<DVD> tk(10);" tuo koon määrittely pois, se on turha ja varmaankin aiheuttaa ongelman jota kuvailit.

alottelijaa [03.05.2008 16:52:59]

#

os kirjoitti:

cin.ignore('\n') ei varmasti tee sitä, mitä haluaisit. Se siis ei jätä rivivaihtoa (\n) huomiotta vaan poistaa virrasta '\n' = 10 ensimmäistä merkkiä.

ok, en ollut ihan varma mitä tuo teki. onko nimiavaruuksia olemassa muitakin kun standard kun sitä joka paikassa näkee?

Metabolix [03.05.2008 16:54:36]

#

alottelijaa kirjoitti:

onko nimiavaruuksia olemassa muitakin kun standard kun sitä joka paikassa näkee?

namespace oma {
  int pallo;
}

Nyt on.

void f1()
{
  oma::pallo = 10;
}

void f2()
{
  using oma::pallo;
  pallo = 12;
}

void f3()
{
  using namespace oma;
  pallo = 12;
}

alottelijaa [03.05.2008 17:01:50]

#

Ok :)

alottelijaa [03.05.2008 22:32:43]

#

Koitin tuota std::string ja std::getline() tapaa sekä tuota alempana olevaa, mutta ohjelma hyppää edelleen koko ajan nimen kysymisen yli suoraan seuraavaan kohtaan.
ideoita? :P

Tumpelo [04.05.2008 10:00:22]

#

cin >> sElokuvat.nimi;

Ja samalla tavalla muutkin.

os [04.05.2008 12:12:46]

#

DVD leffa;

std::cout << "Elokuvan nimi: ";
std::getline(std::cin, leffa.nimi);

std::cout << "Elokuvan kesto muodossa x:x:x : ";
std::getline(std::cin, leffa.kesto);

std::cout << "Elokuvan ilmestymisvuosi: ";
std::cin >> leffa.vuosi;

// tässä kohtaa pitää tarkistaa, että käyttäjä on syöttänyt "vuosi"-kohtaan pelkkiä numeroita, muuten ohjelma kaatuu tai tekee muuta ikävää

// ...

leffat.push_back(leffa);

Katso, että olet käyttänyt string-getlineä joka kohdassa. Jos luet useampisanaisia merkkijonoja näin:

Tumpelo kirjoitti:

cin >> sElokuvat.nimi;

niin vain ensimmäinen sana tallennetaan sinne mihin pitäisi. Loput sanat "hyppäävät" seuraaviin kenttiin. Jos esimerkiksi seuraavanlaiselle ohjelmalle:

std::cout << "Elokuvan nimi: ";
std::cin >> leffa.nimi;

std::cout << "Elokuvan kesto: ";
std::cin >> leffa.kesto;

syöttää elokuvan nimeksi "Terminator 2", niin tuloste näyttää tältä:

Elokuvan nimi: Terminator 2
Elokuvan kesto:

Jos leffan tiedot tämän jälkeen tulostaisi, niin nimi olisi "Terminator" ja kesto "2".

alottelijaa [04.05.2008 13:33:37]

#

Juuri noin tapahtuu

Metabolix [04.05.2008 17:37:23]

#

Tässä pieni testidata:

   1
  2
 3

Seuraavaksi muutama ohjelma ja niiden tulosteet testidatalla.

Kun käyttäjä syöttää rivin "   1<enter>" ja virrasta luetaan luku 1 (ja samalla sitä edeltävät välilyönnit), virtaan jää vielä <enter>. Kun tämän jälkeen luetaan getline-funktiolla, saadaan nollan merkin rivi, koska ensimmäinen lukematon merkki on rivinvaihto. Kas näin:

#include <string>
#include <iostream>

int main()
{
	std::string s;
	int i;
	std::cin >> i;
	std::cout << "Luku: '" << i << "'" << std::endl;
	for (i = 0; i < 3; ++i) {
		std::getline(std::cin, s);
		std::cout << "Rivi: '" << s << "'" << std::endl;
	}
}
/*
Luku: '1'
Rivi: ''
Rivi: '  2'
Rivi: ' 3'
*/

Usein on tarkoituksenmukaista getlinen yhteydessä lukea ensin puskurista tyhjät pois. Whitespace-merkit voi lukea pois std::ws-olion avulla: std::cin >> std::ws poistaa kaikki tyhjät merkit eli mm. välit, tabulaattorit ja rivinvaihdot. Tämä lukeminen siis myös odottaa siihen asti, että lukupuskuriin ilmestyy jotain muuta.

#include <string>
#include <iostream>

int main()
{
	std::string s;
	int i;
	std::cin >> i;
	std::cout << "Luku: '" << i << "'" << std::endl;
	for (i = 0; i < 2; ++i) {
		std::cin >> std::ws; // Hypätään tekstiin (2 tai 3)
		std::getline(std::cin, s);
		std::cout << "Rivi: '" << s << "'" << std::endl;
	}
}
/*
Luku: '1'
Rivi: '2'
Rivi: '3'
*/

Jos kuitenkin rivin alkuun kaivataan mahdollisesti välejä, rivin loppuun pääsee ignore-funktiolla.

#include <string>
#include <iostream>
#include <limits>

int main()
{
	std::string s;
	int i;
	std::cin >> i;
	std::cout << "Luku: '" << i << "'" << std::endl;

	// Jätetään luettavia merkkejä huomiotta (ignore)
	// enintään streamsize-tyypin maksimiarvon verran ("äärettömästi")
	// tai kunnes tulee rivinvaihto.
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	for (i = 0; i < 2; ++i) {
		std::getline(std::cin, s);
		std::cout << "Rivi: '" << s << "'" << std::endl;
	}
}
/*
Luku: '1'
Rivi: '  2'
Rivi: ' 3'
*/

Vielä selvennyksenä std::numeric_limits<std::streamsize>::max() pienempinä palasina:
numeric_limits eli luvun raja-arvot,
streamsize eli virran (cin tms.) merkkimäärää kuvaava tyyppi (usein sama kuin int),
numeric_limits <streamsize> eli tämän lukutyypin raja-arvot,
max() eli maksimiarvo.

alottelijaa [04.05.2008 18:27:39]

#

Nyt toimii! Kiitos paljon :)

alottelijaa [04.05.2008 20:56:26]

#

Moi taas :P kaikki on varmaan ihan kyllästyneitä minuun mutta tämä on (toivottavasti) viimeinen ongelma. Eli ohjelmaan pitäisi saada mahdollisuus muokata jo olemassa olevien elokuvien tietoja. Onko tämä mahdollista? Koitin jo tällaista mutta ohjelma kaatuu aina kun arvo pitäisi tallentaa:

int Muokkaus(int valinta2)
{


    cout << "Mink\x84 elokuvan tietoja haluat muokata? Takaisin p\x84\x84set painamalla q\n";

    for(unsigned i=0; i < tk.size(); i++)
    {
      cout << (1+i) << ") " << tk[i].nimi << std::endl;
    }

    cin >> valinta2;

    switch (valinta2)
    {
           case 1:
           cout << "Anna uusi nimi: ";
           cin >> tk[valinta2].nimi;                                           //kaatuu tän jälkeen
           break;

progo [05.05.2008 13:46:55]

#

Enpä mene ihan varmaksi sanomaan (tullut koodattua liikaa javaa, joten C++ saattaa tehdä asian eri tavalla), mutta vektorista pitää kaivaa se haluttu olio ulos väliaikaisolioksi. Sitten siihen väliaikaisolioon tehdään muutokset normaaliin tapaan ja lopuksi se lisätään takaisin vektoriin.

alottelijaa [05.05.2008 15:41:31]

#

No en kyllä tiedä miten se tehdään, mutta kirjotin ohjelman uudestaan normaalina taulukkona. Nyt toimii.

os [06.05.2008 14:09:07]

#

alottelijaa kirjoitti:

No en kyllä tiedä miten se tehdään, mutta kirjotin ohjelman uudestaan normaalina taulukkona. Nyt toimii.

Olisi varmaan itsellesi paljon hyödyllisempää, jos tekisit tuon kunnolla vektoreilla. Onnistuminen ei ilmeisesti ollut kovin kaukana.

C++:ssa ei tässä tarvita mitään väliaikaisolioita. Tuon viimeksi lähettämäsi koodin ei pitäisi kaatua jos syötät vain yksisanaisia nimiä. Muussa tapauksessa pitäisi käyttää getlineä, eli (kuten Metabolix korjasi)

std::cout << "Uusi nimi: ";
std::cin >> std::ws;
std::getline(std::cin, tk[valinta].nimi);

Valinnan tulkitsemisessa ei tarvita mitään switch-case-rakenteita, vaan numeron oikeellisuus kuuluu tarkistaa etukäteen, esimerkiksi näin:

// Valinta luetaan väliaikaiseen paikalliseen muuttujaan
unsigned valinta;

std::cout << "Numero: ";

while(!(std::cin >> valinta) || valinta >= tk.size())
// toistetaan niin kauan, kunnes käyttäjä on syöttänyt oikeasti numeron,
// joka vastaa oikeaa vektorin alkiota (valinta < tk.size())
{
   // jos käyttäjä on syöttänyt esim. kirjaimia, niin cin-virta on virhetilassa
   std::cin.clear(); // poistetaan virhetila
   // siivotaan virrasta kaikki syötetyt merkit rivivaihtoon asti
   std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
   // pyydettään syöttämään uusi numero
   std::cout << "Virheellinen valinta!\nAnna uusi numero: ";
}

Valinnan ei kuulu olla funktion parametrina (void Muokkaus(int valinta)), jos sitä ei edes anneta funktiolle. Muokkausfunktion kuuluu siis näyttää ennemminkin tältä:

void muokkaus()
{
   // Vaihtoehtojen tulostus

   unsigned valinta;
   // ... Listaus 2

   // Listaus 1
}

Sivun alkuun

Vastaus

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

Tietoa sivustosta