Vinnaren i pepparkakshustävlingen!
  • 1
  • 2
2019-08-27, 20:01
  #1
Medlem
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

Kod:
#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;
}
Citera
2019-08-27, 20:21
  #2
Medlem
Trollfeeders avatar
Citat:
Ursprungligen postat av keysersozeswe
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

Kod:
#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;
}


Jag kan bara se att du deklarerar operatorn, ska du inte definiera om den?
Citera
2019-08-28, 13:57
  #3
Moderator
Protons avatar
C#, VB.NET och .NET Framework --> C, C++ och assembler
/Moderator
Citera
2019-08-28, 20:03
  #4
Medlem
Större delen av programmet låter du ju oss inte se koden till.

Krasch vid avslut är ofta t ex dubbelt frisläppande av minne, eller skrivning till redan frisläppt minne.

Kan vi inte se alla konstruktorer/destruktorer/assignment-operatorer respektive all kod som leker med pekare så blir det lättare sagt än gjort att spåra var det går fel.

Hobbyhackar du, eller går du någon kurs? Du programmerar rätt old-style C++ utan att använda godsakerna från STL - inga smart pointers, containers, ...
Citera
2019-08-29, 17:44
  #5
Medlem
Citat:
Ursprungligen postat av cellplast
Större delen av programmet låter du ju oss inte se koden till.

Krasch vid avslut är ofta t ex dubbelt frisläppande av minne, eller skrivning till redan frisläppt minne.

Kan vi inte se alla konstruktorer/destruktorer/assignment-operatorer respektive all kod som leker med pekare så blir det lättare sagt än gjort att spåra var det går fel.

Hobbyhackar du, eller går du någon kurs? Du programmerar rätt old-style C++ utan att använda godsakerna från STL - inga smart pointers, containers, ...

Jag kan posta hela koden i två delar. Jag går en sommarkurs med gamla böcker som kursmaterial. 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

https://pastebin.com/ZgCkZzpA
__________________
Senast redigerad av keysersozeswe 2019-08-29 kl. 17:50.
Citera
2019-08-29, 20:04
  #6
Medlem
Citat:
Ursprungligen postat av keysersozeswe
Jag kan posta hela koden i två delar. Jag går en sommarkurs med gamla böcker som kursmaterial. 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

https://pastebin.com/ZgCkZzpA

Över lag bör du sätta upp en notis-lapp att titta på STL - Standard Template Library.

En bra del att titta på där är containers - listor/vektorer/... som är lämpliga för att t ex lagra dina personer.

En annan bra del att titta på är smart pointers - en C++ klass som låtsas vara en pekare men som t ex kan bjuda på automatiskt frisläppande av minnet där "pekaren" går ur scope. Eller som kan frisläppa gammalt innehåll om du tilldelar ett nytt objekt till "pekaren".

Men viktigt att du rätt tidigt tittar på färskare C++ och inte fastnar i en över 15 år gammal version av C++-standarden. Lär du dig att koda "klassisk" C++ så är det lätt att bli fast och tänka i de tankebanorna.
Citera
2019-08-29, 20:32
  #7
Medlem
Har inte tid att gå igenom all kod men bara lite snabba noteringar nedan.

Kod:
class Person {
public:
    Person (string n, double b, double s);

private:
    string namn;
    int betalat_andras{0};      <== sätt default-värde på attribut utan att behöva använda konstruktor
    int skyldig{0};
};

Person::Person (string n, double b, double s)   <== notera att du har double - men i klassen är de int
: namn{n}               <== initiera inte i body när du kan initiera i initieringslistan
, betalat_andras{b}
, skydlig{s}
{}

Notera att std::string som datatyp är en klass med egen konstruktor/destruktor.
Dvs har du ett attribut av datatypen std::string behöver klassens konstruktor inte göra name="" - det sker automatiskt då std::string vet hur den skall skapa sig själv som tom.

Kod:
Person *temp_pers = 0;
temp_pers = new Person[antal_personer + 1];

Varför onödig assign av initialt värde som direkt skrivs över?
Kod:
Person *temp_pers = new Person[antal_personer + 1];

Tänk på ordningen du gör saker så du slipper göra extra-arbete i efterhand:
Kod:
antal_personer++;
pers[antal_personer - 1] = pny;
jämfört med:
Kod:
pers[antal_personer++] = pny;

"const" är bra att lära sig använda - metoden ändrar inte någonting i objektet så varför inte berätta det?
Kod:
double
Person::haemta_betalat ()
{
  return betalat_andras;
}

Kod:
double Person::haemta_betalat() const {
    return betalat_andras;
}

Tänkt på teckenuppsättning - ställ in editorn till den teckenuppsättning du verkligen vill använda så du slipper lägga in hex-konstanter i strängen. Om konsollen printar iso-8859-1 så är det ju smidigt att redigera i iso-8859-1 och kunna skriva in åäö direkt i texten. Men normalt smidigast att se om du kan köra utf-8 hela vägen från kant-till-kants så får du tillgång till kyrilliska om nu någon önskar skriva sitt namn med kyrilliska.
Kod:
      cout << namn << " ligger ute med: " << betalat_andras <<
    " och \x84r skyldig " << skyldig << ". Skall ha " << betalat_andras -
    skyldig << " fr\x86n potten!" << endl;

Varför har TransaktionsLista ett attribut tn? Räcker väl att den har en lista. Behöver någon metod ett temporärt transaktionsobjekt (t ex när du läser in) är det väl bättre att de skapar ett sådant lokalt. Och många gånger behövs det inte för du kan använda någon av de te transaktioner som finns i din vektor.

Nedanstående är lite intressant. Du litar inte på default-konstruktor för PersonLista så i stället skapar du ett temporärobjekt av typen PersonLista (som initieras med default-konstruktorn) bara för att tilldela till din riktiga variabel...
Kod:
PersonLista TransaktionsLista::FixaPersoner () {
    PersonLista perslista = PersonLista ();  <== default-konstruktor + copy-konstruktor för att få tomt...
    ...
}

Du har en hel massa kod som leker med vektorer.
med std::vector<Person> kan du få så mycket enklare liv - tänk att lösa uppgiften att förlänga och tilldela nya personen genom att bara göra: persons.push_back(person);
Citera
2019-08-30, 13:15
  #8
Medlem
Super, stort tack för feedbacken! Fattar lite mer och ska ändra och förbättra

Dock kvarstår att läraren vill jag ska lägga in en överlagrad tilldelningsoperator på PersonLista, och hon säger att rad 195 inte utförs helt korrekt med djupkopiering.
I övrigt för jag ok, även om jag nu förstår där finns enorm förbättringspotential i övrigt
Citera
2019-08-30, 14:23
  #9
Medlem
Citat:
Ursprungligen postat av keysersozeswe
Super, stort tack för feedbacken! Fattar lite mer och ska ändra och förbättra

Dock kvarstår att läraren vill jag ska lägga in en överlagrad tilldelningsoperator på PersonLista, och hon säger att rad 195 inte utförs helt korrekt med djupkopiering.
I övrigt för jag ok, även om jag nu förstår där finns enorm förbättringspotential i övrigt

Jag har inte sett att du någonstans har publicerat någon kod på någon tilldelningsoperator för PersonLista. Den enda jag sett är:
Kod:
Transaktion & operator = (const Transaktion & tn);
Citera
2019-08-30, 15:27
  #10
Medlem
Jag testade med;
PersonLista & operator = (const PersonLista & p);

Då åker jag på:
290|error: definition of implicitly-declared 'PersonLista::PersonLista(const PersonLista&)'|

På följande rad:
PersonLista::PersonLista(const PersonLista & pl)
:antal_personer (pl.antal_personer)

Som sagt, jag är helt rookie på detta och verkligen sliter med att förstå, men framförallt så måste jag lämna in uppgiften men springer in i väggen hela tiden.

TACK för din tid och ditt tålamod!
Citera
2019-08-30, 15:49
  #11
Medlem
Citat:
Ursprungligen postat av keysersozeswe
Jag testade med;
PersonLista & operator = (const PersonLista & p);

Då åker jag på:
290|error: definition of implicitly-declared 'PersonLista::PersonLista(const PersonLista&)'|

På följande rad:
PersonLista::PersonLista(const PersonLista & pl)
:antal_personer (pl.antal_personer)

Som sagt, jag är helt rookie på detta och verkligen sliter med att förstå, men framförallt så måste jag lämna in uppgiften men springer in i väggen hela tiden.

TACK för din tid och ditt tålamod!

Har du kollat så att kompilatorn du använder faktiskt har stöd för C++11 och att du har slagit på det?
Citera
2019-08-30, 15:56
  #12
Medlem
Citat:
Ursprungligen postat av IngetNick2
Har du kollat så att kompilatorn du använder faktiskt har stöd för C++11 och att du har slagit på det?

Yes den har stöd för det och det är min lärare som säger PersonLista saknar en överlagrad tilldelningsoperator.
Citera
  • 1
  • 2

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback