diff --git a/Presiseringer.docx b/Presiseringer.docx new file mode 100644 index 0000000000000000000000000000000000000000..aa0ed4237da4f672e592a60d623b0c05a3f9cff8 Binary files /dev/null and b/Presiseringer.docx differ diff --git a/RE_Testing_pdf.pdf b/RE_Testing_pdf.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b40329ba06a034fdfd73330f7bf25dcdfe7b0734 Binary files /dev/null and b/RE_Testing_pdf.pdf differ diff --git a/Stoppesteder.dta b/Stoppesteder.dta index d9f7a0708973299095803ab5648df510a36894d4..3ad17dd43641befbabec2f8bcb95c26a272aba9c 100644 --- a/Stoppesteder.dta +++ b/Stoppesteder.dta @@ -1,24 +1,16 @@ 10 Aa -1 -2 3 +0 Bb -2 -1 3 -3 5 +0 Cc -1 -2 5 +0 Dd -1 -5 3 +0 Ee -2 -4 3 -6 5 +0 Ff -1 -5 5 +0 Gg 0 Hh diff --git a/bane.cpp b/bane.cpp index 15dae3bbcb6d381d5a894f58f60c3b0dd40927e7..829b87f7cebffe9f9b8c980e4e8d52891456722d 100644 --- a/bane.cpp +++ b/bane.cpp @@ -1,6 +1,6 @@ /** * Kode-fil for bane-klassen - * + * * @file bane.cpp * @author Sondre Sand & Frederik Simonsen */ @@ -14,7 +14,7 @@ using namespace std; /** * Oppretter en ny Bane. Nullstiller alle dens datamedlemmer. * Faktisk innlesning av reelle verdier skjer i lesData() - * + * * @see Rute::Rute() */ Bane::Bane() { @@ -23,7 +23,7 @@ Bane::Bane() { /** * Oppretter en ny Bane fra fil. Leser inn dens datamedlemmer - * + * * @param inn Filen det leses fra * @see Rute::Rute(...) */ @@ -32,9 +32,16 @@ Bane::Bane(ifstream & inn) : Rute (inn) { inn >> antVogner >> lengde; inn.ignore(); // Forkaster '\n' } +/** + * Sletter minne allokert med en rute (virtuell) + */ +Bane::~Bane() { + +} + /** * Leser inn alle datamedlemmer for en bane (virtuell) - * + * * @see Rute::lesData() */ void Bane::lesData() { @@ -45,7 +52,7 @@ void Bane::lesData() { /** * Skriver ut all informasjon om en bane til bruker i run-time (virtuell) - * + * * @see Rute::skrivBeskrivelse() */ void Bane::skrivBeskrivelse() { @@ -56,7 +63,7 @@ void Bane::skrivBeskrivelse() { /** * Skriver ut rutetype (bane) til bruker (virtuell) - * + * * @see Rute::skrivData() */ void Bane::skrivData() const { @@ -75,7 +82,7 @@ void Bane::skrivKort() const { /** * Skriver ut alle datamedlemmer for en bane til fil (virtuell) - * + * * @param ut - Filen det skrives til * @see Rute::skrivTilFil(...) */ @@ -83,4 +90,4 @@ void Bane::skrivTilFil(ofstream & ut) { ut << "A\n"; // Skriver ut A for rutetype Bane Rute::skrivTilFil(ut); // Rute skriver egne data ut << antVogner << ' ' << lengde << '\n'; // Skriver egne data -} \ No newline at end of file +} diff --git a/bane.h b/bane.h index 03af3a5f0c1942df834ea1cf8405bef9b4844469..c9310cf55df401718de61744cdd145794e759cb5 100644 --- a/bane.h +++ b/bane.h @@ -20,6 +20,7 @@ class Bane : public Rute { public: Bane(); Bane(std::ifstream & inn); + virtual ~Bane(); virtual void lesData(); virtual void skrivBeskrivelse(); virtual void skrivData() const; diff --git a/buss.cpp b/buss.cpp index 6fac6403aeffaa555d1941836cec30df92052609..c6a4289b8f4f59d20adc9f6b43f6d96545e7268d 100644 --- a/buss.cpp +++ b/buss.cpp @@ -1,6 +1,6 @@ /** * Kode-fil for buss-klassen - * + * * @file buss.cpp * @author Sondre Sand & Frederik Simonsen */ @@ -14,7 +14,7 @@ using namespace std; /** * Oppretter en ny Buss, nullstiller alle dens datamedlemmer. * Faktiske reelle verdier knyttet til bussen, leses inn i lesData - * + * * @see Rute::Rute() */ Buss::Buss() { @@ -24,7 +24,7 @@ Buss::Buss() { /** * Leser inn en buss sine datamedlemmer fra fil - * + * * @param inn Filen det leses fra * @see Rute::Rute(...) */ @@ -33,9 +33,16 @@ Buss::Buss(ifstream & inn) : Rute(inn) { inn >> antSitt >> antStaa >> leddbuss; inn.ignore(); } +/** + * Sletter minne allokert for en rute (virtuell) + */ +Buss::~Buss() { + +} + /** * Leser inn alle datamedlemmer for en aktuell buss (virtuell) - * + * * @see Rute::lesData() */ void Buss::lesData() { @@ -44,12 +51,12 @@ void Buss::lesData() { antSitt = lesInt("Antall sitteplasser på bussen", MINSITT, MAXSITT); antStaa = lesInt("Antall ståplasser på bussen", MINSTAA, MAXSTAA); bussType = lesChar("Leddbuss? (J/N)"); - + while (bussType != 'J' && bussType != 'N') { // Looper ved ulovlig svar: cout << "\nUlovlig valg, prøv igjen.\n"; bussType = lesChar("Leddbuss? J eller N"); } - + if (bussType == 'J') { // Oppdaterer om faktisk leddbuss eller ei: leddbuss = true; } else if (bussType == 'N') @@ -59,7 +66,7 @@ void Buss::lesData() { /** * Skriver ut all informasjon om en buss til bruker (virtuell) - * + * * @see Rute::skrivBeskrivelse() */ void Buss::skrivBeskrivelse() { @@ -71,7 +78,7 @@ void Buss::skrivBeskrivelse() { /** * Skriver ut egen rutetype (buss) til bruker (virtuell) - * + * * @see Rute::skrivData() */ void Buss::skrivData() const { @@ -90,8 +97,8 @@ cout << "\nBussen har " << antSitt << " sitteplasser, " << antStaa /** * Skriver ut bussens datamedlemmer til fil (virtuell) - * - * @param ut Filen det skrives til + * + * @param ut Filen det skrives til * @see Rute::skrivTilFil(...) */ void Buss::skrivTilFil(ofstream & ut) { @@ -99,4 +106,4 @@ void Buss::skrivTilFil(ofstream & ut) { Rute::skrivTilFil(ut); // Rute skriver egne datamedlemmer ut << antSitt << ' ' << antStaa // Skriver egne datamedlemmer << ' ' << leddbuss << '\n'; // Leddbuss (1), ikke leddbuss (0) -} \ No newline at end of file +} diff --git a/buss.h b/buss.h index 082dbe36a17e2a5e25a78bfde5cd5671ff80d2d7..cfeb8bdba26647638b88631888c6c6bbb6bfe9f6 100644 --- a/buss.h +++ b/buss.h @@ -22,6 +22,7 @@ class Buss : public Rute { public: Buss(); Buss(std::ifstream & inn); + virtual ~Buss(); virtual void lesData(); virtual void skrivBeskrivelse(); virtual void skrivData() const; diff --git a/rute.cpp b/rute.cpp index a39a56ee1f5ba5707a7e6989d2521cee80095087..b9607b6f3e56e9ad904334f13cb29b8802f6d2c7 100644 --- a/rute.cpp +++ b/rute.cpp @@ -11,12 +11,14 @@ #include <fstream> #include "const.h" #include "rute.h" +#include "ruter.h" #include "stoppested.h" #include "stoppesteder.h" #include "LesData3.h" using namespace std; extern Stoppesteder gStoppestederBase; +extern Ruter gRuterBase; //********STOPP FUNKSJONER******************* @@ -87,6 +89,46 @@ Rute::Rute(ifstream & inn) { } } +/** + * Sletter alt minne allokert ifm. Rute-listen + */ +Rute::~Rute() { + for (auto it = stoppene.begin(); it != stoppene.end(); it++) + delete (*it); // Sletter det tilpekte + stoppene.clear(); // Tømmer listen for pekere +} + +/** + * Sjekker om et sluttsted ifm. smetting av stopper er før på ruten + * enn startstedet i intervallet for hvor stopper skal smettes + * + * @param s1 - Peker til startstopp i intervallet + * @param s2 - Peker til sluttstopp i intervallet + * @return true s2 er tidligere på ruten enn s1 + * @return false s1 er før s2 + */ +bool Rute::erForst(Stopp* s1, Stopp* s2) { + int fPos, // første posisjon + aPos; // andre posisjon + // finner posisjon i listen for startstopp i intervallet: + auto it = find(stoppene.begin(), stoppene.end(), s1); + if (it != stoppene.end()) { + fPos = distance(stoppene.begin(), it); + } + // Finner posisjon i listen for stoppsted i intervallet: + auto it2 = find(stoppene.begin(), stoppene.end(), s2); + if (it2 != stoppene.end()) { + aPos = distance(stoppene.begin(), it2); + } + // Hvis stoppsted faktisk er før startsted i intervall: + if (aPos < fPos) { + return true; + } + // Hvis startsted faktisk er før stoppsted i intervall: + return false; + +} + /** * Sjekker om en rute har mer enn en stopp (= gyldig rute) * @@ -100,6 +142,52 @@ bool Rute::erListeGyldig() { return false; } + +/** + * Sjekker om to stopp på en rute faktisk er nabo eller ei + * + * @param s1 - Peker til startstopp i intervallet + * @param s2 - Peker til sluttstopp i intervallet + * @return true Hvis stoppene er naboer + * @return false Hvis stoppene ikke er naboer + */ +bool Rute::erNabo(Stopp* s1, Stopp* s2) { + int fPos, // posisjon til første stopp i ruten + aPos, // posisjon til andre stopp i ruten + temp, // Hjelpevariabel for eventuelt bytte om fPos og aPos + avstand; // Avstand mellom stoppene på ruten (=1 hvis nabo) + + // Finner posisjon til første stopp i intervallet + auto it = find(stoppene.begin(), stoppene.end(), s1); + if (it != stoppene.end()) { // Funn av stoppNr + fPos = distance(stoppene.begin(), it); + } + // Finner posisjon til andre stopp i intervallet + auto it2 = find(stoppene.begin(), stoppene.end(), s2); + if (it2 != stoppene.end()) { // Funn av stoppNr + aPos = distance(stoppene.begin(), it2); + } + + if (fPos < aPos) { // Hvis første er før på ruten enn andre + avstand = aPos-fPos; // Setter avstand mellom stopp på ruten + // Hvis slutt stopp er før start stopp i intervallet, bytter plass: + } else if (fPos > aPos) { + temp = fPos; + fPos = aPos; + aPos = temp; + avstand = aPos-fPos; + // Hvis man sjekker om samme stopp er først og sist i intervall: + } else if (fPos == aPos) { // Skal ikke skje + cout << "\nHer er det noe alvorlig galt.\n\n"; + } + // Hvis stoppene i intervallet er naboer: + if (avstand == 1) { + return true; + } + // Stoppene er ikke naboer: + return false; +} + /** * Går gjennom et medsendt navn fra bruker, sjekker * alle tegn i strengen er tall eller ei @@ -148,7 +236,7 @@ bool Rute::gyldigTid(const int time, const int minutt) { /** * Finner antall minutter mellom et faktisk stopp på ruten * og startstoppestedet på ruten - * + * * @param nr - Et stoppesteds unike nummer * @param retning - Fram eller Tilbake (ulikt startsted) avhengig * av hvilken vei ruten går @@ -179,9 +267,24 @@ int Rute::finnDifferanse(const int nr, const Retning retning) { return -1; // Skal ikke skje } +/** + * Henter hvor et stopp er i rute listen stoppene. + * + * @param stoppNr + * @return int - returnerer hvor i lista stoppet er. + */ +int Rute::hentRuteIndeks(Stopp* p1) { + int indeks; + + auto it = find(stoppene.begin(), stoppene.end(), p1); + indeks = distance(stoppene.begin(), it); + return indeks; +} + + /** * Henter navn på startstasjonen på en rute - * + * * @param retning Om ruten er Fram (original) eller Tilbake ("baklengs") * @return Navnet på startstopp på rute avhengig av retning * @see Stoppesteder::hentNavnVhaIndeks(...) @@ -195,12 +298,153 @@ string Rute::hentNavn(const Retning retning) { startSted = gStoppestederBase.hentNavnVhaIndeks(stoppene.back()->hentNr()); return startSted; // Returnerer navnet på startstopp på ruten +} + +/** + * Sjekker om en stopp er på en aktuell rute + * + * @param nr - Stoppens unike nr + * @return Stopp* - Peker til stopp ved funn (er på ruta) + * @return nullptr - Hvis stoppen ikke er på aktuell rute + * @see Stopp::hentNr() + */ +Stopp* Rute::finnStopp(int nr) { + int nummer; + if (!stoppene.empty()) { // Hvis det finnes stopp på ruten: + // For alle stopp i ruten: + for (auto it = stoppene.begin(); it != stoppene.end(); it++) { + nummer = (*it)->hentNr(); // Henter stoppNr + if (nummer == nr) // Sammenligner + return (*it); // Funn, returnerer peker til rett stopp + } + } + return nullptr; // Ikke funn, returnerer nullptr +} + +/** + * Fjerner stopp på en bestemt rute mellom to stopp fra brukeren. + * Oppdaterer nabo og tid, hvis de stoppene som ender opp som naboer + * ikke er naboer fra før. + * + * @see Stoppesteder::byttBokstaver(...) + * @see Stoppesteder::finnesIndeks(...) + * @see Stoppesteder::hentIndeksVhaNavn(...) + * @see Stoppesteder::finnEntydig(...) + * @see Stoppesteder::hentIndeksVhaNavn(...) + * @see Rute::finnStopp(...) + * @see Rute::finnesStopp(...) + * @see Rute::hentRuteIndeks(...) + * @see Stoppesteder::finnDuplikat(...) + * @see Stoppested::finnesNabo(...) + * @see Stoppested::hentNaboTid(...) + * @see Stoppested::settNaboIndeks(...) + * @see Stoppested::settNaboTid(...) + * + */ +void Rute::fjernStopp() { + int sIndeks, lIndeks, sStoppNr, lStoppNr, //s=start, l=last + tid, //tid mellom naboer + tempI, //temp indeks for bytte + tempS; //temp stoppnummer for bytte + string navn, navn2, sNavn, lNavn, //start og last + tempN; //temp navn for bytte + Stopp* p1 = nullptr; //struct peker + Stopp* p2 = nullptr; //struct peker + Stoppested* sp1 = nullptr; //stoppested(vektor) peker + Stoppested* sp2 = nullptr; //stoppested(vektor) peker + + auto itS = stoppene.begin(); + cout << "\n\nMellom start\n" + << "Stoppested (entydig navn / tall / ENTER for å avslutte): "; + getline(cin, navn); + + if(navn.size() > 0){ + while (navn.size() > 0) { + navn = gStoppestederBase.byttBokstaver(navn); + if (erTall(navn)) { sIndeks = stoi(navn); + if (gStoppestederBase.finnesIndeks(sIndeks-1)) { //navn fra bruker + navn = gStoppestederBase.hentNavnVhaIndeks(sIndeks); } + } + sNavn = gStoppestederBase.finnEntydig(navn); + if (sNavn.size() > 0){ + sIndeks=gStoppestederBase.hentIndeksVhaNavn(sNavn); //finner indeks fra vektor. + p1 = finnStopp(sIndeks+1); + if (finnesStopp(sIndeks+1)){ //sjekker at stopp finnes på lista. + sStoppNr=hentRuteIndeks(p1); //henter hvor på lista stoppet er + navn = ""; //hopper ut av while. + }else { + cout << "\nStoppet finnes ikke på ruta!"; + cout << "\n\nMellom start\n" + << "Stoppested (entydig navn / tall / ENTER for å avslutte): "; + getline(cin, navn); + sNavn=""; + } + } + } + if(sNavn.size() > 0){ //hopper ut hvis brukeren tastet blank på første. + auto itL= stoppene.begin(); //setter slutt(last) stopper til start. + cout << "\n\nMellom slutt\nStopp kan ikke være nabo eller samme som start!" + << "Stoppested (entydig navn / tall / ENTER for å avslutte): "; + getline(cin, navn2); + while (navn2.size() > 0) { + navn2 = gStoppestederBase.byttBokstaver(navn2); + if (erTall(navn2)) { lIndeks = stoi(navn2); + if (gStoppestederBase.finnesIndeks(lIndeks-1)) { //navn fra bruker + navn2 = gStoppestederBase.hentNavnVhaIndeks(lIndeks); } + } + lNavn = gStoppestederBase.finnEntydig(navn2); + if (lNavn.size() > 0){ + lIndeks=gStoppestederBase.hentIndeksVhaNavn(lNavn); + p2 = finnStopp(lIndeks+1); + if (finnesStopp(lIndeks+1) && sNavn!=lNavn && !erNabo(p1, p2)){ + lStoppNr=hentRuteIndeks(p2); + navn2 = ""; + }else { + cout << "\nStoppet finnes ikke på ruta!"; + cout << "\nStopp kan ikke være nabo eller samme som start!"; + cout << "\n\nMellom slutt\n" + << "Stoppested (entydig navn / tall / ENTER for å avslutte): "; + getline(cin, navn2); + lNavn = ""; //hopper ut av while + } + } + if(p1 > p2 && p2!=nullptr){ + auto temp = itS; itS = itL; itL= temp; //bytter om iteratoren + tempI = sIndeks; sIndeks = lIndeks; lIndeks = tempI; //bytter indeks + tempN = sNavn; sNavn=lNavn; lNavn = tempN; //bytter navn + tempS = sStoppNr; sStoppNr = lStoppNr; lStoppNr = tempS; //bytter stoppnr + } + if(lNavn.size() > 0){ + advance (itS, sStoppNr+1); //setter iterator start til en forbi stoppet + advance (itL, lStoppNr); //fordi advance tar med selv stoppet det starter på, så må en forbi + stoppene.erase(itS, itL); //fjerner alt mellom bruker start og slutt. + sp1 = gStoppestederBase.finnDuplikat(sNavn); //setter peker til vektoren på start navn + sp2 = gStoppestederBase.finnDuplikat(lNavn); //setter peker til vektoren på slutt navn + if(sp2->finnesNabo(sIndeks+1)){ //hvis de er naboer + tid = sp2->hentNaboTid(sIndeks); //hent tiden + p2->minutter=tid; //oppdater tiden i structen + cout << "Tiden mellom stoppestedene er allerede registrert som " + << tid << "minutter."; + }else{ //hvis de ikke er naboer + tid=lesInt("Tid til fra forrige stopp", 1, 10); //leser inn tid mellom stopp + p2->minutter=tid; //oppdaterer tiden i struct + sp1->settNaboIndeks(lIndeks); //start stopp er nabo med slutt stopp + sp1->settNaboTid(tid); //oppdaterer tiden + sp2->settNaboIndeks(sIndeks); //slutt stopp er nabo med start stopp + sp2->settNaboTid(tid); //oppdaterer tiden + } + skrivKort(); + skrivRute(Fram); //skriver ut oppdatert rute. + } + } + } + } } /** * Leser inn og oppretter en rutetabell for et gitt stoppested på en rute * med utgangspunkt i omregning fra et startsted på ruten - * + * * @param diff - differanse mellom startsted og aktuelt stoppested i minutter * @param start - faktisk startstedsnavn på ruten * @param stSted - faktisk navn på aktuellt stoppested @@ -232,12 +476,12 @@ void Rute::ruteTabell(const int diff, const string start, const string stSted) { startTid = (startT*60)+startM; // Regner ut første avgangstid // Sørger for at starttid er gyldig, samt ikke senere enn 23:53 (1433) - while (!gyldigTid(startT, startM) || startTid > 1433) { + while (!gyldigTid(startT, startM) || startTid > 1433) { cout << "\nUlovlig klokkeslett. Prøv igjen (tt mm): "; cin >> startT >> startM; cin.ignore(); startTid = (startT*60)+startM; } - + while (startT != 0 || startM != 0) { // Så lenge bruker ikke taster 0 0 avgangsTid = startTid+diff; // Må ha en sjekk her for lang tid mellom stoppesteder, som @@ -245,13 +489,13 @@ void Rute::ruteTabell(const int diff, const string start, const string stSted) { // så man ikke får output med et klokkeslett 25:xx f.eks. if (avgangsTid < 1440) { // < 24:00 avgangstider.push_back(avgangsTid); // Legger første avgang - // i vector + // i vector } else { // Omregning av hva som skal i vector, for spesielle // tilfeller, unngå 25:xx f.eks.: avgangstider.push_back(avgangsTid%1440); } - - + + // Leser tid mellom avganger: // Ny sjekk her for å sørge for riktig output til bruker // basert på valgt "fra"-tid. Godtar ikke 6-120 min for @@ -302,7 +546,7 @@ void Rute::ruteTabell(const int diff, const string start, const string stSted) { startTotal = (startT*60)+startM; // Omregning // Sørger for ny lovlig starttid: while ((!gyldigTid(startT, startM) || startTotal <= sluttTotal) - && (startT != 0 || startM != 0)) { + && (startT != 0 || startM != 0)) { cout << "\nUlovlig klokkeslett. Prøv igjen (tt mm): "; cin >> startT >> startM; cin.ignore(); startTotal = (startT*60)+startM; // Omregning @@ -310,10 +554,10 @@ void Rute::ruteTabell(const int diff, const string start, const string stSted) { startTid = (startT*60)+startM; // Omregning } else { // Avslutter innlesning fra bruker hvis slutttid er 23:53 // eller senere (da det må være +1 min minimum til neste - // avgang). + // avgang). startT = 0; startM = 0; // Sørger for stopp av innlesning } - + } cout << "\n\nRutetabell for stoppested: " << stSted << "\n\n"; // Sorterer vektoren, slik at man ikke får duplikat utskrift av @@ -333,7 +577,7 @@ void Rute::ruteTabell(const int diff, const string start, const string stSted) { } else { // Hvis time er mer enn 24 (skjer ved stor avstand) // mellom stoppesteder på en rute, gjør modulo // slik at det ikke skrives ut 25:xx f.eks.: - cout << '\n' << ((timer%24 < 10) ? "0" : "") << timer%24 + cout << '\n' << ((timer%24 < 10) ? "0" : "") << timer%24 << ": " << ((minutter < 10) ? "0" : "") << minutter; } @@ -410,6 +654,353 @@ void Rute::slettData(){ stoppene.clear(); // Tømmer listen for stopp } +/** + * Smetter inn stoppesteder mellom et intervall hvis mulig + * Skal godta tall, navn så fort entydig, hoppe ut ved enter + * Skal sjekke at det kun går ann å smette inn mellom faktiske + * naboer på en rute (uavhengig av hvilken "vei" bruker har + * tastet inn disse) osv. + * + * @see Stoppesteder::byttBokstaver(...) + * @see Rute::erTall(...) + * @see Stoppesteder::finnesIndeks(...) + * @see Stoppesteder::hentNavnVhaIndeks(...) + * @see Stoppesteder::finnEntydig(...) + * @see Stoppesteder::hentIndeksVhaNavn(...) + * @see Rute::finnesStopp(...) + * @see Stoppesteder::finnDuplikat(...) + * @see Rute::finnStopp(...) + * @see Rute::erNabo(...) + * @see Rute::erForst(...) + * @see Stoppested::finnesNabo(...) + * @see Stoppested::hentNaboIndeks(...) + * @see Stoppested::hentNaboTid(...) + * @see Stopp::Stopp(...) + * @see Stoppested::settNaboIndeks(...) + * @see Stoppested::settNaboTid(...) + * @see Rute::skrivRute(...) + */ +void Rute::smettStopp() { + string navn, // Hjelpevariabel for å lese brukerinput + fNavn, // Forrige stoppesteds navn + aNavn, // Siste stoppesteds navn i intervall + nNavn, // Nåværende stoppesteds navn + tempNavn; // Hjelpevariabel for evt. å endre rekkefølge + int stoppNr, // Hjelpevariabel for å lese brukerinput + fStoppNr, // Forrige stoppesteds unike nr + aStoppNr, // Siste stoppesteds unike nr i intervall + nStoppNr, // Nåværende stoppesteds unike nr + tempStoppNr, // Hjelpevariabel for evt. å endre rekkefølge + indeks, // Hjelpevariabel for å lese bruker input + naboIndeks, // Nabostopp sin indeks + fIndeks, // Forrige stoppested sin indeks + aIndeks, // Siste stoppested sin indeks i intervall + tempIndeks, // Hjelpevariabel for evt. å endre rekkefølge + tid, // antall minutter mellom stopp + storrelse = stoppene.size(); // Hjelpevariabel for å se om ruten har blitt lengre + Stopp* fStopp = nullptr; // Peker til forrige stopp-struct + Stopp* aStopp = nullptr; // Peker til siste stopp-struct i intervall + Stopp* nStopp = nullptr; // Peker til nåværende stopp-struct + Stopp* tempStopp = nullptr; // Hjelpevariabel for evt. å endre rekkefølge + Stoppested* fStoppested = nullptr; // Peker til forrige stoppested i vector + Stoppested* aStoppested = nullptr; // Peker til siste stoppested i vector fra intervall + Stoppested* nStoppested = nullptr; // Peker til nåværende stoppested i vector + Stoppested* tempStoppested = nullptr; // Hjelpevariabel for evt. å endre rekkefølge + + cout << "\n\nMellom start\n" + << "Stoppested (entydig navn / tall / ENTER for å avslutte): "; + getline(cin, navn); // Leser navn fra bruker + + while (navn.size() > 0) { // Så lenge ikke skrevet enter: + navn = gStoppestederBase.byttBokstaver(navn); // fjerner æøåÆØÅ + + if (erTall(navn)) { // Sjekker om input kun er tall + stoppNr = stoi(navn); // Hvis kun tall, gjør om til int + // Hvis tallet er et faktisk stoppested: + if (gStoppestederBase.finnesIndeks(stoppNr-1)) { + // Henter det faktiske navnet + navn = gStoppestederBase.hentNavnVhaIndeks(stoppNr); + } + } + + fNavn = gStoppestederBase.finnEntydig(navn); // Sjekker entydighet + + if (fNavn.size() > 0) { // Hvis entydig navn: + // Henter et stoppesteds faktiske indeks + fIndeks = gStoppestederBase.hentIndeksVhaNavn(fNavn); + fStoppNr = fIndeks+1; // Setter eget stoppNr + + if (finnesStopp(fStoppNr)) { // Hvis stoppen finnes på ruta + // Henter peker til eget stoppested i vectoren + fStoppested = gStoppestederBase.finnDuplikat(fNavn); + // Henter peker til eget stopp i listen + fStopp = finnStopp(fStoppNr); + // Finne riktige pekere til stoppested og stopp + // Starte på neste while for å finne andre stopp? + navn = ""; // Sørger for at man kommer seg ut av whilen + } else { + fNavn = ""; // Må være her hvis neste input er ENTER + cout << "\nStoppen finnes ikke på denne ruten.\n" + << "\nStoppested (entydig navn / tall / ENTER" + << " for å avslutte): "; + getline(cin, navn); + //send inn i while igjen, stopp er ikke på ruta + } + } else { + fNavn = ""; // må være her hvis neste input er ENTER + cout << "\nIngen entydig stopp funnet.\n" + << "\nStoppested (entydig navn / tall / ENTER" + << " for å avslutte): "; + getline(cin, navn); + //send inn i while igjen, ikke entydig + } + } + + if (fNavn.size() > 0) { // Hvis suksessfull funn av startsted + cout << "\n\nMellom slutt\n" + << "Stoppested (entydig navn / tall / ENTER for å avslutte): "; + getline(cin, navn); // Leser navn fra bruker + + while (navn.size() > 0) { // Så lenge ikke skrevet enter: + navn = gStoppestederBase.byttBokstaver(navn); // fjerner æøå + + if (erTall(navn)) { + stoppNr = stoi(navn); // Hvis kun tall, konverter til int + // Hvis tallet er et faktisk stoppested: + if (gStoppestederBase.finnesIndeks(stoppNr-1)) { + // Henter det faktiske navnet: + navn = gStoppestederBase.hentNavnVhaIndeks(stoppNr); + } + } + // Sjekker entydighet: + aNavn = gStoppestederBase.finnEntydig(navn); + + if (aNavn.size() > 0) { // Hvis entydig navn: + // Henter faktisk indeks for stoppested: + aIndeks = gStoppestederBase.hentIndeksVhaNavn(aNavn); + aStoppNr = aIndeks+1; // Setter eget stoppNr + + if (aStoppNr != fStoppNr) { // Hvis ikke samme stopp 2x på rad + // Hvis stopp finnes på ruten: + if (finnesStopp(aStoppNr)) { + // Henter peker til egen stopp: + aStopp = finnStopp(aStoppNr); + // Sjekker om stoppene er nabo på ruta: + if (erNabo(fStopp, aStopp)) { + // Henter peker til eget stoppested i vector + aStoppested = gStoppestederBase.finnDuplikat(aNavn); + // Hvis sluttsted er før startsted, bytt alt: + if (erForst(fStopp, aStopp)) { + tempNavn = fNavn; + fNavn = aNavn; + aNavn = tempNavn; + tempIndeks = fIndeks; + fIndeks = aIndeks; + aIndeks = tempIndeks; + tempStoppNr = fStoppNr; + fStoppNr = aStoppNr; + aStoppNr = tempStoppNr; + tempStoppested = fStoppested; + fStoppested = aStoppested; + aStoppested = tempStoppested; + tempStopp = fStopp; + fStopp = aStopp; + aStopp = tempStopp; + + tempNavn = ""; + tempIndeks = -1; + tempStoppNr = -1; + tempStoppested = nullptr; + tempStopp = nullptr; + } + navn = ""; // Sørger for at man kommer seg ut av while + } else { + aNavn = ""; // må være her hvis neste input er ENTER + // Stoppene er ikke naboer på ruta + cout << "\nStoppene er ikke naboer på ruten.\n" + << "\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + } + + } else { + aNavn = ""; // må være her hvis neste input er ENTER + // stoppen er ikke på ruta + cout << "\nStoppen er ikke på ruten.\n" + << "\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + } + + } else { + aNavn = ""; // må være her hvis neste input er ENTER + // andre stopp er samme som første stopp + cout << "\nStart- og sluttstopp kan ikke være lik.\n" + << "\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + } + + } else { + aNavn = ""; // Må være her hvis neste input er ENTER + // Navnet er ikke entydig: + cout << "\nIngen entydig stopp funnet.\n" + << "Stoppested (entydig navn / tall / ENTER" + << " for å avslutte): "; + getline(cin, navn); + } + } + } + + if (aNavn.size() > 0) { // Hvis suksessfullt funn av stoppsted + cout << "\n\nNye stoppested(er) etter " << fNavn + << " og før " << aNavn << ":\n" + << "Stoppested (entydig navn / tall / ENTER): "; + getline (cin, navn); // Leser navn fra bruker + + while (navn.size() > 0) { // Så lenge ikke tastet enter: + navn = gStoppestederBase.byttBokstaver(navn); // Fjerner æøå + + if (erTall(navn)) { // Sjekker om navn kun består av tall + stoppNr = stoi(navn); // Hvis kun tall, gjør om til int + // Hvis faktisk stoppested: + if (gStoppestederBase.finnesIndeks(stoppNr-1)) { + // Henter navn + navn = gStoppestederBase.hentNavnVhaIndeks(stoppNr); + } + } + // Sjekker for entydighet: + nNavn = gStoppestederBase.finnEntydig(navn); + + if (nNavn.size() > 0) { // Hvis entydig navn + // Henter egen indeks + indeks = gStoppestederBase.hentIndeksVhaNavn(nNavn); + nStoppNr = indeks+1; // Setter eget stoppNr + // Hvis ikke stoppen er en av de som skal smettes inn mellom: + if (nStoppNr != aStoppNr && nStoppNr != fStoppNr) { + // Hvis stoppen ikke finnes på ruta fra før: + if (!finnesStopp(nStoppNr)) { + // Finner peker til eget stoppested i vector + nStoppested = gStoppestederBase.finnDuplikat(nNavn); + + // Hvis nabo finnes fra før: + if (nStoppested->finnesNabo(fStoppNr)) { + // Henter naboens indeks: + naboIndeks = nStoppested->hentNaboIndeks(fStoppNr); + // Henter tid til nabo: + tid = nStoppested->hentNaboTid(naboIndeks); + // Oppretter nytt stopp på ruten: + nStopp = new Stopp(nStoppNr, tid); + // Sørger for at stopp blir smettet inn på rett sted: + auto it = find(stoppene.begin(), stoppene.end(), aStopp); + stoppene.insert(it, nStopp); // Settes inn foran + // slutt stopp i intervall + // Oppdaterer peker, indeks og stoppNr for videre bruk: + fStoppNr = nStoppNr; + fStoppested = nStoppested; + fIndeks = indeks; + cout << "\nTiden mellom stoppestedene er allerede" + << " registrert som " << tid + << " minutter.\n" + << "\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + + } else { // Hvis nabo ikke finnes fra før + // Leser tid mellom stopp + tid = lesInt("Tid fra forrige stopp", 1, 10); + // Oppdaterer forrige stopps nabovektor + fStoppested->settNaboIndeks(indeks); + // Oppdaterer forrige stopps tid til nabo vektor + fStoppested->settNaboTid(tid); + // Oppdaterer egen stopps nabovektor + nStoppested->settNaboIndeks(fIndeks); + //Oppdaterer nåværende stopps tid til nabo vektor + nStoppested->settNaboTid(tid); + // Oppretter ny stopp på ruten + nStopp = new Stopp(nStoppNr, tid); + // Setter inn på rett sted (1 foran bakerst i intervall): + auto it = find(stoppene.begin(), stoppene.end(), aStopp); + stoppene.insert(it, nStopp); + // Oppdaterer variabler for videre bruk: + fStoppNr = nStoppNr; + fStoppested = nStoppested; + fIndeks = indeks; + + cout << "\n\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + } + } else { + // Stoppen finnes allerede på ruten: + nNavn = ""; // Må være her hvis neste input er ENTER + cout << "\nStoppet finnes allerede på ruten.\n" + << "\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + + } + } else { + // Stoppen er en av de som skal smettes inn mellom: + nNavn = ""; // Må være her hvis neste input er ENTER + cout << "\nStoppet finnes allerede på ruten.\n" + << "\nStoppested (entydig navn / tall / " + << "ENTER for å avslutte): "; + getline(cin, navn); + + } + + } else { + // Stopp er ikke entydig: + nNavn = ""; // Må være her hvis neste input er ENTER + cout << "\nIngen entydig stopp funnet.\n" + << "Stoppested (entydig navn / tall / ENTER" + << " for å avslutte): "; + getline(cin, navn); + } + } + } + // Hvis minimum et nytt stopp lagt til på ruten: + if (stoppene.size() > storrelse) { + cout << "\n\nFra " << nNavn << " til " << aNavn << ":\n"; + // Hvis nabo finnes fra før: + if (aStoppested->finnesNabo(nStoppNr)) { + // Henter nabo sin indeks og allerede registrert tid: + naboIndeks = aStoppested->hentNaboIndeks(nStoppNr); + tid = nStoppested->hentNaboTid(naboIndeks); + aStopp->minutter = tid; // oppdaterer tid til forrige nabo på ruten + cout << "\nTiden mellom stoppestedene er allerede " + << "registrert som " << tid << " minutter.\n\n"; + + skrivRute(Fram); // Skriver oppdaterte ruten forlengs + + } else { // Nabo finnes ikke fra før: + // Leser tid mellom stopp + tid = lesInt("Tid fra forrige stopp", 1, 10); + // Oppdaterer forrige stopps nabovektor + nStoppested->settNaboIndeks(aIndeks); + // Oppdaterer forrige stopps tid til nabo vektor + nStoppested->settNaboTid(tid); + // Oppdaterer egen stopps nabovektor + aStoppested->settNaboIndeks(indeks); + // Oppdaterer egen stopps tid til nabo vektor + aStoppested->settNaboTid(tid); + aStopp->minutter = tid; // oppdaterer tid til forrige nabo + cout << '\n'; + skrivRute(Fram); // skriver oppdatert rute forlengs + } + } else { // Ikke lagt til stopp på ruten pga sent uthopp: + delete fStopp; // Sletter evt. allokert minne: + delete aStopp; + delete nStopp; + delete tempStopp; + delete fStoppested; + delete aStoppested; + delete nStoppested; + delete tempStoppested; + } +} + /** * Leser og oppretter stopp for en ny rute, så lenge bruker ønsker * eller det finnes stopp som ikke allerede eksisterer @@ -431,7 +1022,7 @@ void Rute::slettData(){ */ void Rute::lesData() { string navn, - fNavn; + fNavn; // faktisk navn (entydig) int stoppNr = 0, indeks = 0, naboIndeks = 0, @@ -460,13 +1051,13 @@ void Rute::lesData() { // Henter et stoppesteds faktiske indeks i vector: indeks = gStoppestederBase.hentIndeksVhaNavn(fNavn); // Hvis stopp ikke finnes fra før på ruten: - if (!finnesStopp(indeks+1)) { - + if (!finnesStopp(indeks+1)) { + if (stoppene.size() > 0) { // Hvis ikke første stopp på ruten // Henter peker til eget stoppested: nStopp = gStoppestederBase.finnDuplikat(fNavn); // Hvis nabo finnes fra før: - if (nStopp->finnesNabo(naboIndeks+1)) { + if (nStopp->finnesNabo(naboIndeks+1)) { // Henter naboens indeks naboIndeks = nStopp->hentNaboIndeks(naboIndeks+1); // Henter tid til naboen: @@ -475,7 +1066,7 @@ void Rute::lesData() { nyStopp = new Stopp(indeks+1, tidTilF); stoppene.push_back(nyStopp); // Legges i lista // Oppdaterer naboindeks for videre bruk: - naboIndeks = indeks; + naboIndeks = indeks; cout << "\nTiden mellom stoppestedene er allerede" << " registrert som " << tidTilF << " minutter.\n"; @@ -510,11 +1101,11 @@ void Rute::lesData() { // forrige nabo å være 0, da første stopp på ruten stoppene.push_back(nyStopp); // Legges til ruten // Oppdaterer naboindeks for videre bruk - naboIndeks = indeks; + naboIndeks = indeks; } // Setter peker til forrige stopp til å peke på riktig // stoppested for videre bruk: - fStopp = nStopp; + fStopp = nStopp; } else // Stoppet finnes allerede på ruten: cout << "\nStoppet er allerede registrert på ruten!\n"; } else { // Hvis ikke entydig: diff --git a/rute.h b/rute.h index 7bbc43d1dd0a9454d2610e49dda4557c66919789..77b589e38a7e92c9e98ac57e27a2ccb4d9ddc20a 100644 --- a/rute.h +++ b/rute.h @@ -35,24 +35,31 @@ class Rute { public: Rute(); Rute(std::ifstream & inn); + virtual ~Rute(); + bool erForst(Stopp* s1, Stopp* s2); bool erListeGyldig(); + bool erNabo(Stopp* s1, Stopp* s2); bool erTall(std::string nvn); bool finnesStopp(const int nr); bool gyldigTid(const int time, const int minutt); int finnDifferanse(const int nr, const Retning retning); + int hentRuteIndeks(Stopp* p1); std::string hentNavn(const Retning retning); + Stopp* finnStopp(int nr); + void fjernStopp(); void ruteTabell(const int diff, const std::string start, const std::string stSted); void skrivRetninger() const; void skrivRute(const Retning retning); void slettData(); + void smettStopp(); virtual void lesData(); virtual void skrivBeskrivelse(); virtual void skrivData() const; virtual void skrivKort() const; virtual void skrivTilFil(std::ofstream & ut); - - + + }; diff --git a/ruter.cpp b/ruter.cpp index 28347c6ae3c4a26f6ac2f1897efc9a629f4d6714..cf90a169b08a8748c37b2842bb2fe29a0bc16aa2 100644 --- a/ruter.cpp +++ b/ruter.cpp @@ -18,6 +18,14 @@ using namespace std; extern Stoppesteder gStoppestederBase; // Henter inn globalt objekt +/** + * Sletter allokert minne i Ruter-mappet + */ +Ruter::~Ruter() { + for (auto it = rutene.begin(); it != rutene.end(); it++) + delete it->second; // Sletter det tilpekte + rutene.clear(); // Tømmer mappet for pekere +} /** * Sjekker om et gitt ruteNr finnes i datastrukturen @@ -34,7 +42,34 @@ bool Ruter::ruteNrFinnes(const int ruteNr) { * endreRute() */ void Ruter::endreRute() { + int ruteNr; + char valg; + + if (!rutene.empty()) { // Hvis det finnes ruter registrert: + ruteNr = lesInt("Rutenr", MINRUTER, MAXRUTER); + if (ruteNrFinnes(ruteNr)) { // Hvis rutenummeret finnes: + auto ruten = rutene.find(ruteNr); // Iterator til rett rute + ruten->second->skrivKort(); // Skriver egen info + ruten->second->skrivRute(Fram); // Skriver ruta + cout << '\n'; + // Leser valg fra bruker: + valg = lesChar("F(jerne intervall) eller S(mette inn)"); + // Looper til lovlig valg fra bruker: + while (valg != 'F' && valg != 'S') { + cout << "\nUgyldig valg, prøv igjen. F og S er gyldig\n"; + valg = lesChar("F(jerne intervall) eller S(mette inn)"); + } + + switch (valg) { // Sender til rett funksjon etter brukervalg: + case 'F': ruten->second->fjernStopp(); break; + case 'S': ruten->second->smettStopp(); break; + } + + } else // Rutenummeret finnes ikke: + cout << "\nIngen ruter registrert med dette nummeret.\n\n"; + } else // Ingen ruter registrert: + cout << "\nIngen ruter registrert i programmet.\n\n"; } /** @@ -129,8 +164,10 @@ void Ruter::nyRute() { rutene[ruteNr] = nyRute; // Lagrer ruten cout << "\nNy rute er lagt til:\n"; ruteBeskrivelse(ruteNr); // Skriver ut ruten - } else + } else { nyRute->slettData(); // <1 stopp, sletter ruten + delete nyRute; // Sletter peker, ved ugyldig rute + } } else // Rutenummer er duplikat: cout << "\nRutenummeret finnes fra før. Kan ikke legge til rute.\n\n"; @@ -266,13 +303,17 @@ void Ruter::ruteTabell() { * @see Rute::skrivData() */ void Ruter::skrivAlle() { - cout << "\nFølgende ruter finnes:\n"; - for (const auto & [ruteNr, rute] : rutene) { // For hver rute: - cout << ruteNr << ' '; // Skriver rutenr - rute->skrivData(); // Ruten skriver egne data + if (!rutene.empty()) { // Så lenge det er ruter registrert: + cout << "\nFølgende ruter finnes:\n"; + for (const auto & [ruteNr, rute] : rutene) { // For hver rute: + cout << ruteNr << ' '; // Skriver rutenr + rute->skrivData(); // Ruten skriver egne data + cout << '\n'; + } cout << '\n'; + } else { + cout << "\nIngen ruter registrert i datastrukturen.\n\n"; } - cout << '\n'; } /** diff --git a/ruter.dta b/ruter.dta index 21ea244e6eecbfc25cb6651b58741da5d93b9266..c227083464fb9af8955c90d2924774ee50abb547 100644 --- a/ruter.dta +++ b/ruter.dta @@ -1,13 +1 @@ -2 -1 U -3 -1 0 -2 3 -3 5 -50 10 0 -2 A -3 -4 0 -5 3 -6 5 -5 50 \ No newline at end of file +0 \ No newline at end of file diff --git a/ruter.h b/ruter.h index 744747db7e23b9734799ed5888294e6a0478aef7..ab4a8d23f197fe54901f2fafff3a6c00b4342102 100644 --- a/ruter.h +++ b/ruter.h @@ -17,6 +17,7 @@ class Ruter { private: std::map <int, Rute*> rutene; public: + ~Ruter(); bool ruteNrFinnes(const int ruteNr); void endreRute(); void handling(); diff --git a/stoppested.cpp b/stoppested.cpp index 8f36ae473630acae8b3d24dfe8877a11770ce65b..07073aea7925072cc2bb1aaa222c44a8022bda25 100644 --- a/stoppested.cpp +++ b/stoppested.cpp @@ -52,6 +52,14 @@ Stoppested::Stoppested(const std::string nvn, ifstream & inn) { inn.ignore(); // Forkaster enter hvis det finnes naboer } +/** + * Tømmer et stoppesteds vektorer for innhold + */ +Stoppested::~Stoppested() { + nabostopper.clear(); // Tømmer vektor med nabostopp nummere + tidtilnabo.clear(); // Tømmer vektor med tid til de ulike naboene +} + /** * Sjekker om et Stoppested har en gitt nabo * @@ -127,7 +135,8 @@ void Stoppested::settNaboTid(const int nr) { * Formaterer utskrift til å skrive navn på 20 "plasser" */ void Stoppested::skrivData() { - cout << setw(20) << navn; + cout << left << setw(20) << navn; + cout << right; } /** diff --git a/stoppested.h b/stoppested.h index 360b0cd127d7e47055f91d8305e4e435285c3fb5..c3f394cc26643ed6a552e1b8b94dbd980cb076c4 100644 --- a/stoppested.h +++ b/stoppested.h @@ -24,6 +24,7 @@ class Stoppested { public: Stoppested(const std::string nvn); Stoppested(const std::string nvn, std::ifstream & inn); + ~Stoppested(); bool finnesNabo(const int nr); int hentNaboIndeks(const int nr); int hentNaboTid(const int nr); diff --git a/stoppesteder.cpp b/stoppesteder.cpp index 5585a51374a487f489eb8baa578d905e6b0e1f5f..7587911e0b2a17bd4c2d715c533aad2733c55018 100644 --- a/stoppesteder.cpp +++ b/stoppesteder.cpp @@ -15,6 +15,15 @@ #include "stoppesteder.h" using namespace std; +/** + * Sletter minne allokert med Stoppesteder + */ +Stoppesteder::~Stoppesteder() { + for (int i = 0; i < stopper.size(); i++) + delete stopper[i]; // Sletter det tilpekte + stopper.clear(); // Tømmer vektor for pekere +} + /** * Sjekker om en stoppesteds indeks finnes i vektoren * diff --git a/stoppesteder.h b/stoppesteder.h index e7b1ac27d1893db4ae7c7da81a89f26fc9fbbdc8..d462067bcf8fb59aa920368cf79b70e44827ae2b 100644 --- a/stoppesteder.h +++ b/stoppesteder.h @@ -19,6 +19,7 @@ class Stoppesteder { private: std::vector <Stoppested*> stopper; public: + ~Stoppesteder(); bool finnesIndeks(const int nr); bool ikkeHarTall(const std::string nvn); bool tom(); diff --git a/~$_Testing.docx b/~$_Testing.docx new file mode 100644 index 0000000000000000000000000000000000000000..6ca643c1f9374108814cb8d1dd4584cfa21e0dde Binary files /dev/null and b/~$_Testing.docx differ