Hjälp med en uppgift c++, programfel vid avslut

Permalänk

Hjälp med en uppgift c++, programfel vid avslut

Har fastnat totalt och irrat in mig i stora bärskogen med en uppgift.
Min körning fungerar bra men när man avslutar får man programfel.

Saknar en en överlagrad tilldelningsoperator för PersonLista men får inte rätt på det (rad 195)
Vet att jag behöver det men saknar sista pricken över i:et, eller just nu har jag inget i ens

#include <iostream> #include <string> #include <fstream> #include <iomanip> using namespace std; //Globala const int MAX_KOMPISAR = 10; const int MAX_TRANSAKTIONER = 30; const int MAX_PERSONER = 10; class Person { private: string namn; int betalat_andras; int skyldig; public: Person (); Person (string n, double b, double s); double haemta_betalat (); double haemta_skyldig (); string haemta_namn (); void skrivUt (); }; class PersonLista { private: int antal_personer; Person *pers; public: PersonLista (); ~PersonLista (); PersonLista (const PersonLista & p); void laggTillEn (Person pny); void skrivUtOchFixa (); double summaSkyldig (); double summaBetalat (); bool finnsNamn (string namnet); }; class Transaktion { private: string datum; string typ; string namn; double belopp; int ant_vanner; string *vanner; public: Transaktion (); ~Transaktion (); Transaktion & operator = (const Transaktion & tn); string haemta_namn (); double haemta_belopp (); int haemta_ant_vanner (); double haemta_skyldig (string namnet); bool finnsVan (string namnet); bool laesEnTrans (istream & is); void skrivEnTrans (ostream & os); }; class TransaktionsLista { private: Transaktion * trans; Transaktion tn; int antalTrans; public: TransaktionsLista (); ~TransaktionsLista (); void laesin (istream & is); void skrivut (ostream & os); void laggTill (Transaktion & tn); double totalkostnad (); double harLagtUt (string namnet); double aerSkyldig (string namnet); PersonLista FixaPersoner (); }; void Meny (TransaktionsLista & translista, PersonLista & perslista); void visaMeny (); int Val (); //Huvudprogram int main () { TransaktionsLista translista; PersonLista perslista; ifstream infil ("resa.txt"); translista.laesin (infil); infil.close (); Meny (translista, perslista); return 0; } void Meny (TransaktionsLista & translista, PersonLista & perslista) { Transaktion tn; Person pers; int antal = 0; string namnet; int val = -1; ifstream infil ("resa.txt"); ofstream utfil ("resa.txt", ios_base::app); while (val != 0) { visaMeny (); val = Val (); switch (val) { case 0: cout << "\nProgrammet avslutas. Tillagda transaktioner sparas." << endl; translista.skrivut (utfil); utfil.close (); break; case 1: tn.laesEnTrans (cin); translista.laggTill (tn); break; case 2: cout << "\nAntal trans = " << antal << endl; translista.skrivut (cout); cout << endl; break; case 3: cout << "\nAktivitetens totalkostnad: " << translista. totalkostnad () << " kr." << endl << endl; break; case 4: cout << "Ange namn: "; cin >> namnet; cout << namnet << " C$r skyldig: " << translista. aerSkyldig (namnet) << " kr." << endl << endl; break; case 5: cout << "Ange namn: "; cin >> namnet; cout << namnet << " ligger ute med: " << translista. harLagtUt (namnet) << " kr." << endl << endl; break; case 6: perslista = translista.FixaPersoner (); perslista.skrivUtOchFixa (); cout << endl; break; } } } // Funktion som skriver ut menyn void visaMeny () { cout << "-------------> V\x84lj funktion <-------------" << endl << endl; cout << "0. Avsluta. Alla transaktioner sparas p\x86 fil." << endl; cout << "1. L\x84s in en transaktion fr\x86n tangentbordet." << endl; cout << "2. Skriv ut information om alla transaktioner." << endl; cout << "3. Ber\x84kna totala kostnaden." << endl; cout << "4. Hur mycket \x84r en viss person skyldig?" << endl; cout << "5. Hur mycket ligger en viss person ute med?" << endl; cout << "6. Lista alla personer mm och FIXA!" << endl << endl; } int Val () { int val; cout << "V\x84lj \x94nskad funktion: "; cin >> val; return val; } Person::Person () { namn = ""; betalat_andras = 0; skyldig = 0; } Person::Person (string n, double b, double s) { namn = n; betalat_andras = b; skyldig = s; } // Selektorer double Person::haemta_betalat () { return betalat_andras; } double Person::haemta_skyldig () { return skyldig; } string Person::haemta_namn () { return namn; } // Skriver information om en given persons betalningar och skulder void Person::skrivUt () { if (betalat_andras > skyldig) { ///////////////////////////////////////////// cout << namn << " ligger ute med: " << betalat_andras << " och \x84r skyldig " << skyldig << ". Skall ha " << betalat_andras - skyldig << " fr\x86n potten!" << endl; } else { cout << namn << " ligger ute med: " << betalat_andras << " och \x84r skyldig " << skyldig << ". Skall l\x84gga " << skyldig - betalat_andras << " till potten!" << endl; } } PersonLista::PersonLista () { antal_personer = 0; pers = 0; } // Destruktor PersonLista::~PersonLista () { delete[]pers; pers = 0; } PersonLista::PersonLista (const PersonLista & pl): antal_personer (pl.antal_personer) { if (antal_personer > 0) { pers = new Person[antal_personer]; for (int i = 0; i < antal_personer; i++) { pers[i] = pl.pers[i]; } } else { pers = 0; } } void PersonLista::laggTillEn (Person pny) { Person *temp_pers = 0; temp_pers = new Person[antal_personer + 1]; for (int i = 0; i < antal_personer; i++) { temp_pers[i] = pers[i]; } delete[]pers; pers = temp_pers; antal_personer++; pers[antal_personer - 1] = pny; } // Skriver ut information om vaje person som ingår void PersonLista::skrivUtOchFixa () { for (int i = 0; i < antal_personer; i++) { pers[i].skrivUt (); } } // Summan för skyldig double PersonLista::summaSkyldig () { double skyldig = 0; for (int i = 0; i < antal_personer; i++) { skyldig += pers[i].haemta_skyldig (); } return skyldig; } // Summan av utläggen double PersonLista::summaBetalat () { double betalat = 0; for (int i = 0; i < antal_personer; i++) { betalat += pers[i].haemta_betalat (); } return betalat; } // Finns namnet? bool PersonLista::finnsNamn (string namnet) { for (int i = 0; i < antal_personer; i++) { if (pers[i].haemta_namn () == namnet) { return true; } } return false; } Transaktion::Transaktion () { datum = ""; typ = ""; namn = ""; belopp = 0; ant_vanner = 0; vanner = 0; } Transaktion & Transaktion::operator = (const Transaktion & tn) { if (this != &tn) { delete[]vanner; datum = tn.datum; typ = tn.typ; namn = tn.namn; belopp = tn.belopp; ant_vanner = tn.ant_vanner; vanner = new string[ant_vanner]; for (int i = 0; i < ant_vanner; i++) { vanner[i] = tn.vanner[i]; } } return *this; } // Destruktor Transaktion::~Transaktion () { delete[]vanner; vanner = 0; } // Selektorer string Transaktion::haemta_namn () { return namn; } double Transaktion::haemta_belopp () { return belopp; } int Transaktion::haemta_ant_vanner () { return ant_vanner; } double Transaktion::haemta_skyldig (string namnet) { double skuld = 0; for (int i = 0; i < ant_vanner; i++) { if (vanner[i] == namnet) { skuld = belopp / (ant_vanner + 1); } } return skuld; } // Ger true om namnet ligger i arrayen vanner bool Transaktion::finnsVan (string namnet) { for (int i = 0; i < ant_vanner; i++) { if (namnet == vanner[i]) { return true; } } return false; } //Transaktion bool Transaktion::laesEnTrans (istream & is) { delete[]vanner; is >> datum >> typ >> namn >> belopp >> ant_vanner; vanner = new string[ant_vanner]; for (int i = 0; i < ant_vanner; i++) is >> vanner[i]; return !is.eof (); } // Skriver ut transaktion void Transaktion::skrivEnTrans (ostream & os) { os << datum << "\t" << typ << "\t" << namn << "\t" << belopp << "\t" << ant_vanner << "\t"; for (int i = 0; i < ant_vanner; i++) { os << vanner[i] << "\t"; } os << endl; } //Transaktionslista TransaktionsLista::TransaktionsLista () { antalTrans = 0; trans = 0; } TransaktionsLista::~TransaktionsLista () { delete[]trans; trans = 0; } void TransaktionsLista::laesin (istream & is) { while (tn.laesEnTrans (is)) { laggTill (tn); } } void TransaktionsLista::skrivut (ostream & os) { for (int i = 0; i < antalTrans; i++) { trans[i].skrivEnTrans (os); } } void TransaktionsLista::laggTill (Transaktion & tn) { Transaktion *temp_trans = 0; temp_trans = new Transaktion[antalTrans + 1]; for (int i = 0; i < antalTrans; i++) { temp_trans[i] = trans[i]; } delete[]trans; trans = temp_trans; antalTrans++; trans[antalTrans - 1] = tn; } //Summering double TransaktionsLista::totalkostnad () { double totalkostnad = 0; for (int i = 0; i < antalTrans; i++) { totalkostnad += trans[i].haemta_belopp (); } return totalkostnad; } //Hur mycket pengar har en person lagt ut double TransaktionsLista::harLagtUt (string namnet) { double betalat = 0; for (int i = 0; i < antalTrans; i++) { if (trans[i].haemta_namn () == namnet) { betalat += (trans[i].haemta_belopp () - (trans[i].haemta_belopp () / (trans[i].haemta_ant_vanner () + 1))); } } return betalat; } //Ger hur mycket en person är skyldig double TransaktionsLista::aerSkyldig (string namnet) { double skyldig = 0; for (int i = 0; i < antalTrans; i++) { skyldig += trans[i].haemta_skyldig (namnet); } return skyldig; } //En persons transaktioner PersonLista TransaktionsLista::FixaPersoner () { PersonLista perslista = PersonLista (); string persnamn = ""; for (int i = 0; i < antalTrans; i++) { if (!perslista.finnsNamn (trans[i].haemta_namn ())) { persnamn = trans[i].haemta_namn (); Person nypers = Person (persnamn, harLagtUt (persnamn), aerSkyldig (persnamn)); perslista.laggTillEn (nypers); } } return perslista; }

Permalänk
Medlem

Dina klasser som innehåller pekare bryter mot rule of three, en C++-regel så viktig att den har sin egen Wikipedia-artikel.

Förutom det så har du ett fel i case 6: av menyn, där du skriver perslista = translista.FixaPersoner();. TransaktionsLista::FixaPersoner() returnerar en ny PersonLista som ett värde, men det returnerade objektet destrueras direkt eftersom det bara är ett temporärt värde. Eftersom perslista är en referens så kommer objektet inte att kopieras (och PersonLista har ingen tilldelningsoperator, så det skulle bli fel ändå), utan perslista kommer istället peka på det redan frigjorda objektet som inte längre existerar.

Just nu använder du perslista lite underligt, du skapar den i main och skickar in den som referens till Meny, sen använder du den inte till något annat än att försöka skriva över den med listan som returneras av translista.FixaPersoner(). Så du kan helt enkelt ta bort den variabeln helt från programmet, och lagra listan du får från FixaPersoner() i en temporär variabel (efter att du fixat alla klasser så att de följer rule of three).

Permalänk
Medlem

Programmet skulle bli väldigt mycket effektivare om du använde containers. Som vector, map, länkade listor och liknande. Du skulle då helt kunna låta bli new. Och koden skulle bli enklare och risken för fel mindre. Är det ett krav att du inte får använda containers? Men du får använda string och streams. Verkar märkligt.

Visa signatur

Linux och Android

Permalänk

@Adoby: Jag är helt rookie på detta, och det är en sommarkurs. Finns garanterat 1.000.000 bättre lösningar men just nu försöker jag brandsläcka denna, även om koden inte är optimal