Baza danych zbudowana na klasach

Odpowiedz Nowy wątek
2013-04-20 14:15
0
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>

using namespace std;

class produkt
{
      //friend class warzywo; // deklaracja przyjaŸni, aby mo¿liwy by³ dostêp do pó³ privat w nowej klasie pochodnej
      protected:              // zaprzyjaŸnienie zamienione na rozwi¹zanie z polami protected
         int lp;
         string name;  // nazwa produktu
         double count;   // liczba produktów
         string unit;   // jednostka miary
         double prize;   // cena netto 1 sztuki
         double vat;     // wartoϾ podatku VAT
      public:
         produkt();                   // konstruktor
         produkt(int Nlp, string Nname, double Ncount, string Nunit, double Nprize, double Nvat);                   // konstruktor
         void wypelnij(void);
         void pokaz(void);
         //virtual void wypelnij(void);
         //virtual void pokaz(void);
         produkt(produkt &l);     // konstruktor kopiujacy
         ~produkt();                  // destruktor
         int pole_lp(void);
         void pole_lp(int);
};

produkt::produkt(int Nlp, string Nname, double Ncount, string Nunit, double Nprize, double Nvat)
{
        lp=Nlp;
        name=Nname;
        count=Ncount;
        unit=Nunit;
        prize=Nprize;
        vat=Nvat;
}
produkt::produkt()
{
        lp = 0;
}

produkt::produkt(produkt &l)
{
        lp=l.lp;
        name=l.name;
        count=l.count;
        unit=l.unit;
        prize=l.prize;
        vat=l.vat;
}

produkt::~produkt()
{
 ;
}

void produkt::wypelnij(void)
{
 cout << "Podaj nazwe:\n";
 cin >> name;
 cout << "Podaj ilosc:\n";
 cin >> count;
 cout << "Podaj jednostke miary:\n";
 cin >> unit;
 cout << "Podaj cene:\n";
 cin >> prize;                        // UWAGA obowi¹zuje notacja z kropk¹ .
 cout << "Podaj stawke VAT:\n";
 cin >> vat;

}
void produkt::pokaz(void)
{
        cout << endl;
        cout << lp << "\t";
        cout << name << "\t";
        cout << count << "\t";
        cout << unit << "\t";
        cout << prize << "\t";
        cout << vat << endl;
}
int produkt::pole_lp(void)
{
 return(lp);
}
void produkt::pole_lp(int x)
{
 lp = x;
}

class wezel {
public:
    wezel *nastepny;
    produkt *zawartosc;
    int indeks;
};

class baza {
    wezel *pierwszy, *ostatni;
    int licznik;
public:
    baza();
    ~baza();
    void dodaj(produkt *prod);
    void wyswietl();
    void usun(int idx);
    void zapisz();
    void wczytaj();
};

baza::baza() {

    pierwszy = ostatni = NULL;
    licznik = 0;

};

baza::~baza() {

    wezel *p;

    while(pierwszy)
    {
        p = pierwszy -> nastepny;
        delete pierwszy;
        pierwszy = p;
    }

}

void baza::dodaj(produkt *prod) {

wezel *p = new wezel;

   if(ostatni)
    {
       ostatni->nastepny = p;
       p->zawartosc = prod;
    }
       p->nastepny = NULL;
       ostatni = p;
    if(!pierwszy)
    {
        pierwszy = ostatni;
    }
    licznik++;
};

void baza::usun(int idx) {

};

void baza::wyswietl() {

wezel *p = new wezel;

      if(!pierwszy) cout << "Lista jest pusta." << endl;
      else
      {
        p = pierwszy;
        while(p)
        {
        p->zawartosc->pokaz();
        p = p->nastepny;
        }
        cout << endl;
      }
};

int main(void)
{
        baza db1;
        produkt *p1 = new produkt(5, "maslo", 10, "sztuk", 1.00, 0.07);
        db1.dodaj(p1);
        db1.wyswietl();
        return 0;
}

Mam za zadanie napisać bazę danych na klasach(jak widać wyżej). Na samym początku walczę z problemem naruszenia pamięci. Chcę dodać nowy produkt i wyświetlić bazę wszystkich dodanych produktów. Jak na razie ni w ząb mi to wychodzi. Pewnie coś namieszałem ze wskaźnikami znając życie.

Później mam dodać jeszcze klasy pochodne do produktu, ale najpierw muszę pozbyć się pierwszego problemu. Gdzie robię błąd?

Pozostało 580 znaków

2013-04-20 15:17
1

Błąd masz tutaj:

   if(ostatni)
    {
       ostatni->nastepny = p;
       p->zawartosc = prod;
    }

Za pierwszym razem jak wywołujesz metodę dodaj to wskaźnik ostatni ma wartość null więc
p->zawartosc = prod;
się nie wykona i wskaźnik zawartość w węźle będzie miał wartość null i podczas wywołania:
p->zawartosc->pokaz();
program się wysypie bo będziesz się próbował odwołać to wskaźnika która pokazuje na nic.
Rozwiązanie:
linijkę: p->zawartosc = prod;
umieścić od razu po tej linijce: wezel *p = new wezel;


Nie odpowiadam na PW z prośbą o pomoc programistyczną.

Pozostało 580 znaków

2013-04-20 20:52
0

Działa idealnie! Dziękuję.

Teraz napotkałem problem z usuwaniem rekordu. (Ciągle naruszam pamięć, topornie mi to wchodzi do głowy), chcę usunąć rekord podając numer "lp".

dodałem coś takiego:

void baza::usun(int idx) {
    wezel *tmp = new wezel;

    tmp = pierwszy;

    if(tmp->zawartosc->pole_lp() == idx) delete ostatni;
    else
    {
        while(tmp->zawartosc->pole_lp() != idx)
        {
            tmp=tmp->nastepny;
        }
    }
        delete tmp;
        licznik--;
};

a w main:

int x;
cout << "Numer elementu: ";
cin >> x;
db1.usun(x);

Pozostało 580 znaków

2013-04-20 23:12
0
kaczkazdw napisał(a):

void baza::usun(int idx) {
wezel *tmp = new wezel;
tmp = pierwszy;

if(tmp->zawartosc->pole_lp() == idx) delete ostatni;
else
{
    while(tmp->zawartosc->pole_lp() != idx)
    {
        tmp=tmp->nastepny;
    }
}
    delete tmp;
    licznik--;

};



ja bym zrobił to tak:

void baza::usun(int idx) {
    wezel *tmp = pierwszy;

     while(tmp->zawartosc->pole_lp() != idx && tmp != NULL)
        {
            tmp=tmp->nastepny;
        }

       if(tmp != NULL)
       {
            if(tmp == pierwszy) 
            {
                     pierwszy = pierwszy->nastepny;
                     delete tmp;
                       licznik--;
            }
            else
            {
                       wezel *tmp2 = pierwszy;
                       while(tmp2->nastepny != tmp)
                                          tmp2 = tmp->nastepny;
                       tmp2->nastepny = tmp->nastepny;
                       if(tmp == ostatni) ostatni = tmp2;
                       delete tmp;
                       licznik--;
             }

};

mogą być błędy ale myślę, że koncepcja dobra
edytowany 2x, ostatnio: tamarind17, 2013-04-20 23:14

Pozostało 580 znaków

2013-04-20 23:32
1
tamarind17 napisał(a):

mogą być błędy ale myślę, że koncepcja dobra
To co podałeś nie może być dobre, patrz niżej:

bool baza::usun(int idx)
{
for(wezel *i=pierwszy,*p=0;i;p=i,i=p->nastepny)
{
if(i->zawartosc->pole_lp()==idx)
{
(p?p->nastepny:pierwszy)=i->nastepny;
if(!pierwszy) ostatni=0;
else if(!i->nastepny) ostatni=p;
delete i->zawartosc;
delete i;
return true;
}
}
return false;
}

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon, 2013-04-21 21:15

Pozostało 580 znaków

2013-04-21 17:36
0

tamarind17: brakło tylko jednej klamry na końcu ale w ogólnym przypadku działało.
_13th_Dragon: był nieznaczny problem przy kompilacji na początku (brakowało zdefiniowanego "p" i kompilator się sapał o wezel *i=pierwszy) ale to już poprawiłem. Wyskakuje tylko Warning przy kompilacji, że brak jest virtualnego destruktora w klasie produktu. Ale działa jak należy

Głowię się nad kwestią zapisywania obiektów klasy do pliku i późniejsze odczytywanie ich.

Mam na razie coś takiego:

case 4:
                {
    ofstream ofs("baza.bin");
    const pamiec p(1, "Kingston", 2, "sztuk", 5, 0.07, 1024, "Intel");
    {
        boost::archive::text_oarchive oa(ofs);
        oa << p;
    }
                break;
                }
            case 5:
                {
        pamiec newp;
            {
        ifstream ifs("baza.bin");
        boost::archive::text_iarchive ia(ifs);
        ia >> newp;
        newp.pokaz();
            }
                break;
                }

to jest w switch'u w funkcji main. Jest to serializacja i deserializacja boostem i działa dla pojedynczych obiektów bazowych i obiektow pochodnych klasy bazowej.
Jak umieścić serializacje i deserializacje w metodach zapisz() wczytaj() by po wypełnieniu bazy danych zapisala wszystkie obiekty do pliku, a przy otworzeniu i wczytaniu odtworzyla stan bazy ze wszystkimi obiektami?

Brakowało jedynie znaku '' przed zamiast ,p=0 ma być `,p=0` - _13th_Dragon 2013-04-21 21:16
to może źle poprawiłem ;) - kaczkazdw 2013-04-21 21:49

Pozostało 580 znaków

2013-05-19 09:25
0

Podołałem w końcu z zapisem i odczytem. Ale do ukończenia całego projektu dzieli mnie tylko jeden problem. Mianowicie, zawsze po wczytaniu bazy danych, bo probie zakończenia Bazy Danych, cały program się wiesza na napisie "Zamykanie Programu" i nic nie rusza dalej. Nie mogę znaleźć problemu...

Oto kod:

Podaje w linkach, bo jest długawy.

Main.cpp

http://pastebin.com/n9M3CSej

functions.h

http://pastebin.com/q3ZYvzK

edytowany 3x, ostatnio: kaczkazdw, 2013-06-06 04:55

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0