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?
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.
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.
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
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.
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ää ^_^)
Juu taisin olla vähän väsynyt eilen kun tota kirjotttelin. koitan noita
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.
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
En tiedä, sori olin vähän kiireessä :/
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... "; } }
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.
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.
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?
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; }
Ok :)
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
cin >> sElokuvat.nimi;
Ja samalla tavalla muutkin.
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 leffa
n tiedot tämän jälkeen tulostaisi, niin nimi
olisi "Terminator" ja kesto
"2".
Juuri noin tapahtuu
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.
Nyt toimii! Kiitos paljon :)
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;
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.
No en kyllä tiedä miten se tehdään, mutta kirjotin ohjelman uudestaan normaalina taulukkona. Nyt toimii.
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 }
Aihe on jo aika vanha, joten et voi enää vastata siihen.