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

Struktura w klasie (zadanie C++)

VPS Starter Arubacloud
0 głosów
1,019 wizyt
pytanie zadane 18 czerwca 2018 w C i C++ przez Sic Dyskutant (8,510 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 (122,820 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 Dyskutant (8,510 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 (122,820 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 (122,820 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 Dyskutant (8,510 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,750 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 Dyskutant (8,510 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,750 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 Dyskutant (8,510 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,750 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 Dyskutant (8,510 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,750 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 Dyskutant (8,510 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
0 odpowiedzi 301 wizyt
pytanie zadane 12 listopada 2023 w C i C++ przez whiteman808 Obywatel (1,780 p.)
0 głosów
1 odpowiedź 128 wizyt

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...