• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Struktura w klasie (zadanie C++)

0 głosów
196 wizyt
pytanie zadane 18 czerwca 2018 w C i C++ przez Sic Mądrala (7,330 p.)

Z góry proszę tylko o podpowiedź!.

Napisz program, który będzie dodawał struktury customer (klient) na stos i usuwał je z tego stosu; stos ma być reprezentowany klasą "Stack". Za każdym razem, kiedy struktura jest usuwana ze stosu należy dodać wartość 'payment' do ogólnej sumy należności i wyświetlic tę sumę.

plik nagłówkowy:

#ifndef P_H_
#define P_H_

struct customer {
        char fullname[35];
        double payment;
};

class Stack
{
        private:
                customer person;
                int top;
        public:
                Stack();
                bool isempty() const;
                bool isfull() const;
                bool push(const double & item);
                bool pop(double & element);
};

#endif

deklaracja klasy:

#include "p.h"

Stack::Stack()
{ top = 0; }

bool Stack::isempty() const { return top == 0; }
bool Stack::isfull() const { return top == 35; }

bool Stack::push(const double & element)
{
        if (top < 35) //trzeba wprowadzic całą strukturę na stos!
        {       person.fullname[top++] = element;
                return true;
        }
        else
                return false;
}

bool Stack::pop(double & element)
{
        if (top > 0)
        {       element = person.fullname[--top];
                return true;
        }
        else
                return false;
}

Tutaj pojawia się błąd, ponieważ nie wiem w jaki sposób wrzucić na stos całą strukturę (?).

 

plik główny:

#include "p.h"
#include <iostream>
#include <cctype>

int main()
{
        Stack mystack;
        customer myperson;
        char letter;

        std::cout << "Nacisnij D, aby wprowadzic deklaracje,\nP, aby przetworzyć deklaracje lub K, aby zakończyć.\n";
        while(std::cin >> letter && toupper(letter) != 'K')
        {
                while(std::cin.get() != '\n')
                        continue;
                if(!isalpha(letter))
                { std::cout << '\a'; continue; }

                switch(toupper(letter))
                {
                        case 'D':
                                std::cout << "Podaj nr deklaracji: ";
                                std::cin >> myperson.payment;
                                if(mystack.isfull())
                                        std::cout << "Stos pełen!\n";
                                else
                                        mystack.push(myperson.payment);
                        break;
                        case 'P': 
                                if(mystack.isempty())
                                        std::cout << "Stos pusty\n";
                                else {
                                        mystack.pop(myperson.payment);
                                        std::cout << "Deklaracja nr " << myperson.payment << " zdjeta\n";
                                        }
                        break;
                }//switch
                std::cout << "Nacisnij D, aby wprowadzic deklaracje,\nP, aby przetworzyć deklaracje lub K, aby zakończyć.\n";
        }//while
        std::cout << "Zakończenie programu!\n";
        return 0;
}//main

Proszę tylko o podpowiedź.

komentarz 18 czerwca 2018 przez RafalS VIP (112,950 p.)
A w jaki spospb chcesz ten stos zaimplementować? Na jakiej strukturze danych? Liscie, tablicy? Na razie Twoj stos przechowuje jeden element.
komentarz 19 czerwca 2018 przez Sic Mądrala (7,330 p.)
edycja 19 czerwca 2018 przez Sic

@ RafalS,

Tablicy, po twoim komentarzu zmieniłem fragment kodu z pliku nagłówkowego i deklaracji klasy (chociaż ta druga ma wadę w argumentach metod)

#ifndef P_H_
#define P_H_

#include <cctype>
struct customer {
        char fullname[35];
        double payment;
};

class Stack
{
        private:
                std::size_t quantity = 10;
                customer person[quantity];
                int top;
        public:
                Stack();
                bool isempty() const;
                bool isfull() const;
                bool push(const double & item);
                bool pop(double & element);
};

#endif
#include "p.h"

Stack::Stack()
{ top = 0; }

bool Stack::isempty() const { return top == 0; }
bool Stack::isfull() const { return top == quantity; }

bool Stack::push(const double & element[])
{
        if (top < quantity)
        {
                for(int i=0; i<quantity; i++)
                { person[i].fullname[i] = element[i];
                  person[i].payment = element[i];
                  top++;
                }
                return true;
        }
        else
                return false;
}

bool Stack::pop(double & element[])
{
        if (top > 0)
        {
                for(int i=0; i<quantity; i++)
                { element[i] = person[i].fullname[i];
                  person[i].[payment] = element[i];
                  --top; 
                }
                return true;
        }
        else
                return false;
}

 

komentarz 19 czerwca 2018 przez RafalS VIP (112,950 p.)
No to śmiało dodajesz tablicę struktur customer jako pole składowe klasy Stack i push dodaje na koniec tej tablicy. Trzeba jeszcze pamiętać w którym miejscu tablicy obecnie jest top, wiec musisz pamiętać indeks ostatniego pushniętego elementu. Ten indeks cofasz w metodzie pop, to tyle :D.
komentarz 19 czerwca 2018 przez RafalS VIP (112,950 p.)
bool Stack::push(const double & element[])

Co Ty chcesz dodawać do tego stosu? Hurtowo całe tablice czy pojedyńczych customerów? Klasyczne podejście to push pojedynczego elementu. Przekaż strukture a nie tablicę.

Po drugie:

person[i].fullname[i] = element[i];

do tablicy charów przypisujesz double :D? Myślę, że to nigdy nie może mieć sensu.

Po trzecie:

                bool push(const double & item);
                bool pop(double & element);

trzymaj się konwencji, raz nazywasz go item raz element, a chodzi o to samo. Generalnie taki problem nawet nie powinien wystapić, bo pop nie powienien przyjmować argumentów :D. pop sciąga element z góry stosu, nic mu nie jest do tego potrzebne. Jeśli chcesz przekazywać jakiś argument to nie nazywaj tego stosem :P.

komentarz 19 czerwca 2018 przez Sic Mądrala (7,330 p.)

Poprawiłem, jednak nie wiem jak się uporać z tą konwersją w obu metodach oraz z tym w jaki sposób na raz wrzucić elementy na stos i je ściągnąć ?

#include "p.h"

Stack::Stack()
{ top = 0; }

bool Stack::isempty() const { return top == 0; }
bool Stack::isfull() const { return top == 35; }

bool Stack::push(customer & element)
{
        if (top < 35)
        {
                person.fullname[top++] = element;
                person.payment = element;
                top++;
                return true;
        }
        else
                return false;
}

bool Stack::pop(customer & element)
{
        if (top > 0)
        {
                element = person.fullname[--top];
                person.payment = element;
                --top;
                return true;
        }
        else
                return false;
}

dokładnie chodzi mi o te linie:

person.fullname[top++] = element;
                person.payment = element;
                top++;
element = person.fullname[--top];
                person.payment = element;
                --top;
                return true

 

2 odpowiedzi

+2 głosów
odpowiedź 19 czerwca 2018 przez Szfierzak Gaduła (3,240 p.)
wybrane 19 czerwca 2018 przez Sic
 
Najlepsza

Zwróć uwagę, że...

class Stack
{
        private:
                customer person; // Twoja zawartość stosu!!!
                int top;
        public:
                Stack();
                bool isempty() const;
                bool isfull() const;
                bool push(const double & item);
                bool pop(double & element);
};

...tak zbudowany stos będzie przechowywał tylko jeden element. 

Napisałeś, że chcesz przechowywać elementy na stosie z wykorzystaniem tablicy, zakładasz również maksymalny rozmiar stosu na 35 elementów, stąd spróbuj może w ten sposób:

private:
customer people[35]; // Twoja struktura imitująca stos

Masz teraz stos o rozmiarze 35. Jeżeli chodzi o "wrzucenie" na stos całej struktury to w tym przypadku stos jest już pełen takich struktur, tylko nie zainicjalizowanych, czyli bez wartości. Żeby nadać wartości "całej strukturze" czyli fullname i payment, musisz przy pomocy funkcji push nadawać wartości obu tym polom struktury. Tymczasem...

bool Stack::push(const double & element)
{
        if (top < 35) //trzeba wprowadzic całą strukturę na stos!
        {       person.fullname[top++] = element;
                return true;
        }
        else
                return false;
}

... w pole typu char* wpisujesz double, czy takie było zamierzenie, czy raczej przekazywany argument tyczył się pola payment??

Czy nie było Twoją intencją coś w stylu:

bool Stack::push( customer person)
{
        if (top < 35) //trzeba wprowadzic całą strukturę na stos!
        {       
              strcpy(people[top].fullname, person.fullname); //dlaczego tak??:)
              people[top].payment = person.payment;
              top++;
              return true;
        }
        else
              return false;
}

Oczywiście trzeba zmienić też metodę pop.

Zwróć uwagę również na sposób wprowadzanie i przekazywania zmiennej do funkcji.

std::cout << "Podaj nr deklaracji: ";
std::cin >> myperson.payment;
if(mystack.isfull())
     std::cout << "Stos pełen!\n";
else
     mystack.push(myperson.payment);

Przekazując zmienną przez referencje powodujesz, że zmiana tej zmiennej na zewnątrz funkcji spowoduje zmianę na Twoim stosie - prawdopodobnie niepożądaną.

Proponuję również spróbować dynamicznej alokacji pamięci i stos zorganizować np w postaci tablicy wskaźników na struktury typu customer.

 

komentarz 19 czerwca 2018 przez Sic Mądrala (7,330 p.)
edycja 19 czerwca 2018 przez Sic

Zrobiłem twoim sposobem przyznaję, że chodziło właśnie o tą tablicę, jednak w moim programie występuje jeden błąd, gdy ściągam ze stosu pokazuje się tylko ostatni dodany element (nie zależnie ile ich bym dodał).

W jaki sposób mógłbym dodać ją tutaj?

case 'P':
                                if(mystack.isempty())
                                        std::cout << "Stos pusty\n";
                                else {
                                        mystack.pop(myperson);
                                std::cout << "Nazwa deklaracji: " << myperson.fullname << ", nr deklaracji: " << myperson.payment << " zdjeta\n";
                                }
                        break;

 

komentarz 19 czerwca 2018 przez Szfierzak Gaduła (3,240 p.)

Zwróć uwagę na to czy po dodaniu do stosu zwiększasz wartość zmiennej top(top++), a po zdjęciu ze stosu zmniejszasz jej wartość(top--). Następna pułapka to sposób przekazywania zmiennej do funkcji pop(i push). Czy myperson to wskaźnik czy referencja?

bool Stack::pop(customer & myperson)
{
        if (top > 0)
        {       
                strcpy(myperson.fullname,people[top].fullname);
                myperson.payment = people[top].payment;
                top--;
                return true;
        }
        else
                return false;
}

lub

bool Stack::pop(customer *myperson)
{
        if (top > 0)
        {       
               strcpy(myperson->fullname,people[top].fullname);
               myperson->payment = people[top].payment;
               top--;
               return true;
        }
        else
                return false;
}

 

Być może przekazujesz argument przez wartość do funkcji pop

bool Stack::pop(customer myperson){...}

W tym wypadku struktura kopiowana jest i w funkcji pop działania wykonywane są na kopii, i jeżeli używasz zmiennej strukturalnej myperson do dodawania elementów na stos w funkcji push, to kod podany przez Ciebie będzie rzeczywiście wyświetlał ostatnio dodany element.

Spróbuj zdebudować swój program właśnie pod względem zwiększania/zmniejszania zmiennej top i sposobu przekazywania argumentów do funkcji push i pop.

Może kontrolnie wyświetlaj zawartość całego stosu(funkcją void Stack::print() ) po każdym wykonaniu pętli głównej lub jako dodatkowa opcja.

komentarz 19 czerwca 2018 przez Sic Mądrala (7,330 p.)
#include "p.h"
#include <string.h>
#include <iostream>
Stack::Stack()
{ top = 0; }

bool Stack::isempty() const { return top == 0; }
bool Stack::isfull() const { return top == 35; }

bool Stack::push(customer & element)
{
        if (top < 35)
        {
                strcpy(person[top].fullname, element.fullname);
                person[top].payment = element.payment;
                top++;
                return true;
        }
        else
                return false;
        std::cout << "Wartość stosu: " << top << std::endl;
}

bool Stack::pop(customer & element)
{
        if (top > 0)
        {
                strcpy(person[top].fullname, element.fullname);
                person[top].payment = element.payment;
                --top;
                return true;
        }
        else
                return false;
        std::cout << "Wartość stosu: " << top << std::endl;
}

Nie wiem dlaczego ale nie wyświetla w ogóle wartości top (wrzuciłem wyjście w 'if', również nic).

komentarz 19 czerwca 2018 przez Szfierzak Gaduła (3,240 p.)

Rzeczywiście, powyższy kod nie wyświetli wartości top. Instrukcja return kończy wywołanie funkcji zwracając true lub false. Spróbuj umieścić podgląd tej zmiennej przed tą instrukcją.

Jeżeli nie kodujesz w notatniku, tylko używając jakiegoś IDE, np Code::Block, Devc++, C++ Builder lub inne podobne, to zapewne masz do dyspozycji debugger. Używając go mógłbyś podglądać wartości zmiennych bez konieczności drukowania ich na ekranie. Jeżeli myślisz o dłuższej przygodzie z programowaniem, spróbuj może zaprzyjaźnić się z tego typu narzędziem, bo ułatwi Ci ono pracę z kodem i szukanie ewentualnych błędów.

komentarz 20 czerwca 2018 przez Sic Mądrala (7,330 p.)
edycja 20 czerwca 2018 przez Sic
Dziękuję za tą informację, nie wziąłem tego pod uwagę.

Zadziałało ! Ilość 'top' zwiększa się i zmniejsza zależnie od wyboru, jednak w dalszym  ciągu pokazuję ostatnie wpisane dane, przy wszystkich zdjeciach ze stosu.
komentarz 20 czerwca 2018 przez Szfierzak Gaduła (3,240 p.)

Ok, już widzę błąd. W funkcji push wrzucasz elementy na stos. Działa ona i ma się dobrze. Jednak źle zmieniłeś funkcję pop. Zwróć uwagę, że robi ona dokładnie to samo, co funkcja push, czyli przypisuje elementowi tablicy wartości podane jako argument, a powinno być na odwrót. 

bool Stack::pop(customer & element)
{
        if (top > 0)
        {
                strcpy(element.fullname, people[top-1].fullname); //top-1 !!!!
                element.payment = people[top-1].payment;//top-1 !!!!
                top--;
                cout << "Wartość stosu: " << top << endl;
                return true;
        }
        else
        {
            cout << endl << "Wartość stosu: " << top << endl;
            return false;
        }
}

widzisz różnicę? teraz skoro zdejmujemy element ze stosu, to przypisujemy mu wartości przechowywane na stosie. Zwróć uwagę na zmianę kolejności również w funkcji strcpy, oraz na to, że dostajemy się do elementów stosu za pomocą top-1 - ponieważ tablicę numerujemy od 0 a nie od 1.

PS. żeby zaoszczędzić trochę czasu podczas pisania, możesz używać

using namespace std;

na początku swoich plików - po zadeklarowaniu bibliotek, a później  nie musisz już pisać std:: przed każdym cin-em i cout-em itp.

komentarz 20 czerwca 2018 przez Sic Mądrala (7,330 p.)
edycja 20 czerwca 2018 przez Sic

Dziękuję znam tą metodę.

Oto błąd, który nie ustępuje:

Nacisnij D, aby wprowadzic deklaracje,
P, aby przetworzyć deklaracje lub K, aby zakończyć.
d
Podaj nazwę deklaracji: tak
Podaj nr deklaracji: 11
Wartość stosu: 1
Nacisnij D, aby wprowadzic deklaracje,
P, aby przetworzyć deklaracje lub K, aby zakończyć.
d
Podaj nazwę deklaracji: yyy
Podaj nr deklaracji: 3333
Wartość stosu: 2
Nacisnij D, aby wprowadzic deklaracje,
P, aby przetworzyć deklaracje lub K, aby zakończyć.
p
Wartość stosu: 1
Nazwa deklaracji: yyy, nr deklaracji: 3333 zdjeta
Nacisnij D, aby wprowadzic deklaracje,
P, aby przetworzyć deklaracje lub K, aby zakończyć.
p
Wartość stosu: 0
Nazwa deklaracji: yyy, nr deklaracji: 3333 zdjeta
Nacisnij D, aby wprowadzic deklaracje,
P, aby przetworzyć deklaracje lub K, aby zakończyć.
k
Zakończenie programu!

 

0 głosów
odpowiedź 20 czerwca 2018 przez sp00ky Obywatel (1,760 p.)
edycja 4 lipca 2018 przez sp00ky

Ja zrobiłbym tak, użyłbym typedef aby przechować struktury.

// stack.h

#ifndef STACK_H
#define STACK_H

#include <string>

struct customer {
    std::string fullname;
    double payment;
};

using Item = customer;  // definiuje Item jako synonim typu customer (aby Stack przechowywał egzemplarze struktur)

class Stack {
private:
    enum { MAX = 10 };  // stała zasięgu klasy
    Item items[MAX];    // tablica przechowuje elementy Stack
    int top;            // indeks szczytowego elementu stosu
public:
    Stack();                        // konstruktor domyślny
    ~Stack() = default;             // destruktor domyślny
    bool isempty() const;           // sprawdza czy stos jest pusty
    bool isfull() const;            // sprawdza czy stos jest pełny
    bool push(const Item &item);    // odkłada element na stos, zwraca false jeśli stos jest pełen
    bool pop(Item &item);           // zdejmuje element ze stosu, zwraca false jeśli stos jest pusty
};

#endif // STACK_H
// stack.cpp

#include "stack.h"

// tworzy pusty stos
Stack::Stack() {
    top = 0;
}

// stos jest pusty gdy szczyt jest równy 0
bool Stack::isempty() const {
    return top == 0;
}

// stos jest pełny gdy szczyt jest równy MAX
bool Stack::isfull() const {
    return top == MAX;
}

// dodaje element na stos, zwraca false jeśli stos jest pełen
bool Stack::push(const Item &item) {
    if (top < MAX) {
        items[top++] = item;
        return true;
    }

    return false;
}

// usuwa element ze stosu, zwraca false jeśli stos jest pusty
bool Stack::pop(Item &item) {
    if (top > 0) {
        item = items[--top];
        return true;
    }

    return false;
}
// main.cpp

#include "stack.h"
#include <cctype>
#include <iostream>

int main() {

    using std::cout;
    using std::cin;
    using std::endl;

    Stack st;   // tworzy pusty stos
    char ch;
    customer po;
    double total = 0.0;

    cout << "Nacisnij D, aby dodac klienta \n"
            "Nacisnij U, aby usunac klienta \n"
            "Nacisnij K, aby zakonczyc \n";

    while (cin >> ch && toupper(ch) != 'K') {

        // odrzuca resztę wprowadzonego wiersza
        while (cin.get() != '\n') {
        }

        // gdy znak jest liczbą
        if (isalpha(ch) == 0) {
            cout << '\a';
            continue;
        }
        switch (ch) {
        case 'D':
        case 'd': {
            cout << "Wprowadz nazwe klienta: ";
            getline(cin, po.fullname);
            cout << "Wprawadz nalezna kwote: ";
            cin >> po.payment;
            if (st.isfull()) {
                cout << "Stos pelen!\n";
            } else {
                st.push(po);
            }
            break;
        }
        case 'U':
        case 'u': {
            if (st.isempty()) {
                cout << "Stos pusty!\n";
            } else {
                st.pop(po);
                cout << "Klient " << po.fullname << " usuniety\n";
                total += po.payment;
                cout << "Suma naleznosci: " << total << endl;
            }
            break;
        }
        }
        cout << "Nacisnij D, aby dodac klienta \n"
                "Nacisnij U, aby usunac klienta \n"
                "Nacisnij K, aby zakonczyc \n";
    }
    cout << "Do widzenia!" << endl;

    return 0;
}

 

Podobne pytania

0 głosów
1 odpowiedź 78 wizyt
+2 głosów
4 odpowiedzi 388 wizyt
pytanie zadane 26 czerwca 2015 w C i C++ przez tarnasm Gaduła (3,030 p.)
Porady nie od parady
Pytania na temat serwisu SPOJ należy zadawać z odpowiednią kategorią dotyczącą tej strony.SPOJ

66,384 zapytań

113,137 odpowiedzi

239,497 komentarzy

46,642 pasjonatów

Przeglądających: 292
Pasjonatów: 5 Gości: 287

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...