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

Sortowanie kontenera (std::vector) złożonego z klas za pomocą funkcji sort() z biblioteki <algorithm>

Object Storage Arubacloud
+3 głosów
986 wizyt
pytanie zadane 23 sierpnia 2016 w C i C++ przez plkpiotr Stary wyjadacz (12,420 p.)

Mój program dotyczący pracowników i zarobków, który wcześniej konsultowałem na forum jest na ukończeniu, jednak mam problem z posortowaniem kontenera wg "wynagrodzenia". Rozumiem zamysł użytkownika ison z tego forum, jednak u mnie sprawa się komplikuje, gdyż działam na klasie abstrakcyjnej Pracownik, z której dziedziczą trzy pozostałe klasy, zaś sam dostęp do składowych tych klas jest prywatny, a pole "wynagrodzenie" znajduje się dopiero w trzech klasach potomnych.

Czy mógłbym prosić o wytłumaczenie w jaki sposób ugryźć rozwiązanie tego problemu w moim przypadku? Byłbym również wdzięczny za inne uwagi dotyczące mojego kodu, bo może wyrobiłem sobie jakieś niepotrzebne nawyki lub podchodzę do czegoś niepoprawnie...

Kod zamieszczam poniżej oraz podświetlam istotne linijki:

//===============================================
// Nazwa          : pracownik.h
//===============================================

#ifndef PRACOWNIK_H
#define PRACOWNIK_H
#include <iostream>
#include <cstdio>
#include <string>
#define PROCENT 0.35
#define PREMIA 1.5
#define STRUMIEN 128

using namespace std;

class Pracownik
{
private:
    bool zatrudnienie;
    string imie;
    string nazwisko;
    string nip;
    string pesel;
public:
    Pracownik();
    Pracownik(string im, string nzwsk, string psl, string np);
    bool sprawdzDane(string im, string nzwsk);
    bool porownajZarobki(Pracownik& p1,Pracownik& p2);
    virtual void wyswietlDane() = 0;
    virtual void obliczZarobki() = 0;
    virtual ~Pracownik() {};
};

class Staly: public Pracownik
{
private:
    double wynagrodzenie;
public:
    Staly();
    Staly(string im, string nzwsk, string psl, string np, double wngrdzn);
    void obliczZarobki() {} // istotne
    void wyswietlDane();
    ~Staly() {};
};

class Zleceniobiorca: public Pracownik
{
private:
    double stawka;
    int godziny;
    double wynagrodzenie;
public:
    Zleceniobiorca();
    Zleceniobiorca(string im, string nzwsk, string psl, string np, double stwk, int gdzn);
    void wyswietlDane();
    void obliczZarobki();
    ~Zleceniobiorca() {}
};

class Handlujacy: public Pracownik
{
private:
    double wartosc;
    int transakcje;
    double wynagrodzenie;
public:
    Handlujacy();
    Handlujacy(string im, string nzwsk, string psl, string np, double wrtsc, int trnskcj);
    void wyswietlDane();
    void obliczZarobki();
    ~Handlujacy() {}
};

void enter();
void naglowek();
void czyszczenie();

#endif
//===============================================
// Nazwa          : pracownik.cpp
//===============================================

#include "pracownik.h"

Pracownik::Pracownik()
{
    zatrudnienie = true;
    cout << "Wprowadzanie danych nowego pracownika..." << endl;
    cout << "Imie: ";
    cin >> imie;
    cout << "Nazwisko: ";
    cin >> nazwisko;
    cout << "PESEL: ";
    cin >> pesel;
    cout << "NIP: ";
    cin >> nip;
}

Pracownik::Pracownik(string im, string nzwsk, string psl, string np)
{
    zatrudnienie = true;
    imie = im;
    nazwisko = nzwsk;
    pesel = psl;
    nip = np;
}

Staly::Staly(): Pracownik()
{
    cout << "Miesieczne wynagrodzenie: ";
    cin >> wynagrodzenie;
}

Staly::Staly(string im, string nzwsk, string psl, string np, double wngrdzn): Pracownik(im, nzwsk, psl, np)
{
    wynagrodzenie = wngrdzn;
}

Zleceniobiorca::Zleceniobiorca(): Pracownik()
{
    cout << "Godzinna stawka: ";
    cin >> stawka;
    cout << "Przepracowane godziny: ";
    cin >> godziny;
    obliczZarobki();
}

Zleceniobiorca::Zleceniobiorca(string im, string nzwsk, string psl, string np, double stwk, int gdzn): Pracownik(im, nzwsk, psl, np)
{
    stawka = stwk;
    godziny = gdzn;
    obliczZarobki();
}

Handlujacy::Handlujacy(): Pracownik()
{
    cout << "Wartosc pojedynczej transakcji: ";
    cin >> wartosc;
    cout << "Ilosc transakcji: ";
    cin >> transakcje;
    obliczZarobki();
}

Handlujacy::Handlujacy(string im, string nzwsk, string psl, string np, double wrtsc, int trnskcj): Pracownik(im, nzwsk, psl, np)
{
    wartosc = wrtsc;
    transakcje = trnskcj;
    obliczZarobki();
}

void Zleceniobiorca::obliczZarobki()
{
    if(godziny>40)
        wynagrodzenie = stawka * PREMIA;
    else
        wynagrodzenie = stawka;
}

void Handlujacy::obliczZarobki()
{
    wynagrodzenie = wartosc * transakcje * PROCENT;
}

void Pracownik::wyswietlDane()
{
    cout.width(15);
    cout << left << imie;
    cout.width(15);
    cout << left << nazwisko;
    cout.width(15);
    cout << left << pesel;
    cout.width(15);
    cout << left << nip;
}

void Staly::wyswietlDane()
{
    Pracownik::wyswietlDane();
    cout.width(15);
    cout.setf( ios::showpoint );
    cout << left << wynagrodzenie << endl;
}

void Zleceniobiorca::wyswietlDane()
{
    Pracownik::wyswietlDane();
    cout.width(15);
    cout.setf( ios::showpoint );
    cout << left << wynagrodzenie << endl;
}

void Handlujacy::wyswietlDane()
{
    Pracownik::wyswietlDane();
    cout.width(15);
    cout.setf( ios::showpoint );
    cout << left << wynagrodzenie << endl;
}

bool Pracownik::sprawdzDane(string im, string nzwsk)
{
    if(imie == im && nazwisko == nzwsk)
        return true;
    return false;
}

bool Pracownik::porownajZarobki(Pracownik& p1, Pracownik& p2)
{
    return p1.wynagrodzenie > p2.wynagrodzenie;
}

void enter()
{
    getchar();
    getchar();
}
void naglowek()
{
    cout.width(5);
    cout << left << "Lp:";
    cout.width(15);
    cout << left << "Imie:";
    cout.width(15);
    cout << left << "Nazwisko:";
    cout.width(15);
    cout << left << "PESEL:";
    cout.width(15);
    cout << left << "NIP:";
    cout.width(15);
    cout << left << "Wynagrodzenie:" << endl;
}

void czyszczenie()
{
    printf("\033[2J"); // Czysci ekran
    printf("\033[0;0f"); // Ustawia kursor w lewym, gornym rogu
}
//==================================================
// Nazwa          : main.cpp
//==================================================

#include <vector>
#include <windows.h>
#include <algorithm>
#include "pracownik.h"

int main()
{
    vector <Pracownik*> kadra;
    kadra.push_back(new Staly("Piotr","Wierchowienski","63032300373","4457301037",3300));
    kadra.push_back(new Staly("Mikolaj","Stawrogin","89102905493","7260631988",4100));
    kadra.push_back(new Zleceniobiorca("Iwan","Szatow","77082213114","6825506522",2300,50));
    kadra.push_back(new Zleceniobiorca("Aleksy","Kirillow","85052403018","5913117469",2700,35));
    kadra.push_back(new Handlujacy("Sergiusz","Liputin","67052801713","4621950579",800,14));
    kadra.push_back(new Handlujacy("Ignacy","Lebiadkin","79091902931","8442924521",850,10));
    unsigned short wybor;
    do
    {
        cout << "Zarzadzanie kadra pracownicza:" << endl;
        cout << "[1] --> Zatrudnij stalego pracownika" << endl;
        cout << "[2] --> Zatrudnij zleceniobiorce" << endl;
        cout << "[3] --> Zatrudnij handlujacego" << endl;
        cout << "[4] --> Wyswietl dane pracownika" << endl;
        cout << "[5] --> Wyswietl dane calej kadry" << endl;
        cout << "[6] --> Wyswietl liczbe pracownikow" << endl;
        cout << "[7] --> Zwolnij pracownika" << endl;
        cout << "[8] --> Zwolnij cala kadre" << endl;
        cout << "[0] --> Wyjscie" << endl;
        cout << "Twoj wybor: " << endl;
        do
        {
            cin.clear();
            cin.sync();
            cin >> wybor;
        }
        while(!cin.good());
        cout << endl;
        switch(wybor)
        {
        case 1 :
            kadra.push_back(new Staly());
            break;
        case 2 :
            kadra.push_back(new Zleceniobiorca());
            break;
        case 3 :
            kadra.push_back(new Handlujacy());
            break;
        case 4 :
        {
            if(kadra.empty())
            {
                cout << "Brak zatrudnionych pracownikow. [ENTER]" << endl;
                enter();
                break;
            }
            cout << "Wyszukiwanie pracownika na podstawie imienia i nazwiska..." << endl;
            string szukaneImie,szukaneNazwisko;
            cout << "Imie: ";
            cin >> szukaneImie;
            cout << "Nazwisko: ";
            cin >> szukaneNazwisko;
            unsigned int i;
            for(i=0; i<kadra.size(); i++)
            {
                if(kadra[i]->sprawdzDane(szukaneImie,szukaneNazwisko))
                {
                    kadra[i]->wyswietlDane();
                    cout << "Aby powrocic do menu nacisnij [ENTER]." << endl;
                    enter();
                    break;
                }
            }
            if(i==kadra.size())
            {
                cout << "Brak pracownika o takim imieniu u nazwisku. [ENTER]";
                enter();
                break;
            }
        }
        break;
        case 5 :
        {
            if(kadra.empty())
            {
                cout << "Brak zatrudnionych pracownikow. [ENTER]" << endl;
                enter();
                break;
            }
            unsigned int i;
            sort(kadra.begin(),kadra.end(),porownanie);
            naglowek();
            for(i=0; i<kadra.size(); i++)
            {
                cout.width(5);
                cout << left << i;
                kadra[i]->wyswietlDane();
            }
            cout << "Aby powrocic do menu nacisnij [ENTER]." << endl;
            enter();
        }
        break;
        case 6 :
            cout << "Liczba pracownikow: " << kadra.size() <<  ". [ENTER]" << endl;
            enter();
            break;
        case 7 :
        {
            if(kadra.empty())
            {
                cout << "Brak zatrudnionych pracownikow. [ENTER]" << endl;
                enter();
                break;
            }
            cout << "Usuwanie pracownika o podanym indeksie" << endl;
            unsigned int szukanyIndeks;
            do
            {
                cout << "Indeks:";
                cin.clear();
                cin.sync();
                cin >> szukanyIndeks;
            }
            while(szukanyIndeks>kadra.size() || !cin.good());
            kadra.erase(kadra.begin()+szukanyIndeks);
            cout << "Usunieto pracownika. Aby powrocic do menu nacisnij [ENTER]." << endl;
            enter();
        }
        break;
        case 8 :
            kadra.clear();
            cout << "Cala kadra zostala zwolniona. [ENTER]" << endl;
            enter();
            break;
        }
        system("cls");
    }
    while(wybor!=0);
    return 0;
}

 

4
komentarz 23 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)

Twoje pytanie to wzór dla innych - opisałeś rzetelnie każdy aspekt swojego problemu, ładnie wszystko udokumentowałeś, no i nawet podkreśliłeś nurtujące cię fragmenty kodu...

Wielki plus dla ciebie yes

3
komentarz 23 sierpnia 2016 przez criss Mędrzec (172,590 p.)
Nawet nie wiedziałem, że jest opcja podświetlenia linii :D Ale bardzo ułatwia i fakt - pytanie zadane wzorowo. Niby to powinno być normalne... ale na tym forum jesteś bohaterem XD
3
komentarz 23 sierpnia 2016 przez plkpiotr Stary wyjadacz (12,420 p.)
Dziękuję za miłe słowa ;)
Jestem bardzo wdzięczny za pomoc okazywaną przez Was - Drodzy użytkownicy tego forum tym bardziej, że nie bardzo mam od kogo uczyć się programowania, ani kogo zapytać o jakąś często prostą rzecz. Oczekując właśnie waszej pomocy chciałbym, żeby i Wam łatwo się pomagało, żeby było wszystko jak na dłoni bo wtedy i wam łatwiej zrozumieć "co poeta miał na myśli" i mi łatwiej się skupić na jednym, wybranym problemie :)
2
komentarz 23 sierpnia 2016 przez Patrycjerz Mędrzec (192,320 p.)

Człowieku, z nieba nam spadłeś!

Oczekując właśnie waszej pomocy chciałbym, żeby i Wam łatwo się pomagało, żeby było wszystko jak na dłoni bo wtedy i wam łatwiej zrozumieć "co poeta miał na myśli" i mi łatwiej się skupić na jednym, wybranym problemie :)

Gdyby każdy myślał i pisał pytania tak samo jak ty, nie byłoby syfu tutaj wink 

3 odpowiedzi

+1 głos
odpowiedź 23 sierpnia 2016 przez ZakosiliMiNeta Nałogowiec (30,870 p.)
wybrane 23 sierpnia 2016 przez plkpiotr
 
Najlepsza

Master na OP w C++ się super nie znam, lecz znam go pod algorytmy/konkursy. Przechodząc do meritum. Daj sobie do klasy bazowej virtual wyswietl_zarobki().

Potem deklarujesz sobie funkcję 

bool porownaj_zarobki( Pracownik a, Pracownik b){
  return a.wyświetl_zarobki() > b.wyświetl_zarobki;
}

Potem przekazujesz to do funkcji sorta czyli sort(pracownicy.begin(), pracownicy.end(), porownaj_zarobki)

komentarz 23 sierpnia 2016 przez plkpiotr Stary wyjadacz (12,420 p.)
edycja 23 sierpnia 2016 przez plkpiotr

Genialne! O to mi właśnie chodziło, działa jak chciałem ;) Dziękuję za pomoc :)

Rozwiązanie:

bool sortowanie(Pracownik* p1, Pracownik* p2)
{
    return p1->zwrocZarobki() > p2->zwrocZarobki();
}

oraz dodeklarowanie getterów:

virtual double zwrocZarobki() = 0;
// lub odpowiednio z returnem
double zwrocZarobki();
+2 głosów
odpowiedź 23 sierpnia 2016 przez MetRiko Nałogowiec (37,110 p.)

Myślę, że wystarczy dodać zmienną wynagrodzenie do klasy Pracownik (oczywiście usunąć ją z klas dziedziczących), następnie zrobić funkcję (nie wirtualną) również klasie bazowej o nazwie GetWynagrodzenie() czy coś w tym stylu.. w każdym razie.. chodzi o prosty Getter.

1
komentarz 23 sierpnia 2016 przez plkpiotr Stary wyjadacz (12,420 p.)
Czyli jednak trzeba będzie zmienić strukturę programu a tego niekoniecznie chciałbym, ale faktycznie to uprościłoby troszkę sprawę ;) Dzięki za odpowiedź :)
+1 głos
odpowiedź 23 sierpnia 2016 przez criss Mędrzec (172,590 p.)
edycja 23 sierpnia 2016 przez criss

Teraz pytanie dlaczego wynagrodzenie deklarujesz w każdej z klas osobno. Jacyś pracownicy (jakieś klasy dziedziczące z Pracownika) nie mają wynagrodzenia? XD Anyway - skoro masz do tego jakiś powód (nie przedstawiłeś go, więc troche głupio to wygląda), to IMO najlepszą opcją jest stworzenie kolejnej klasy bazowej lekko rozszerzającej Pracownika o wynagrodzenie - np. 

class AppreciatedWorker : public Pracownik
{
    //public get i set do wynagrodzenia
    double wynagrodzenie;
};

(swoją drogą przyzwyczajaj się do nazywania klas po ang)

I wtedy trzymaj w vectorze wskaźniki na AppreciatedWorker.

komentarz 23 sierpnia 2016 przez plkpiotr Stary wyjadacz (12,420 p.)

To wielokrotne deklarowanie wynagrodzenia chyba wynika z mojego nie do końca poprawnego zrozumienia polecenia: pozostałe informacje o pracowniku będą wypisywane w funkcjach pochodnych. I nie wiedząc dlaczego pomyślałem sobie, że skoro funkcje wyświetlające będą w klasach dziedziczących to dobrze będzie tam umieścić właśnie zmienne "wynagrodzenie". Wniosek: chyba poszedłem na łatwiznę ;)
Dziękuję za wszystkie uwagi :)

1
komentarz 23 sierpnia 2016 przez criss Mędrzec (172,590 p.)
Więc jeśli to jedyny powód, to po prostu wrzuć wynagrodzenie do klasy bazowej :D

Podobne pytania

0 głosów
1 odpowiedź 512 wizyt
pytanie zadane 10 grudnia 2016 w C i C++ przez Kasztan Dyskutant (8,080 p.)
+1 głos
3 odpowiedzi 849 wizyt
0 głosów
1 odpowiedź 1,205 wizyt
pytanie zadane 16 czerwca 2017 w C i C++ przez excavelty Bywalec (2,480 p.)

92,555 zapytań

141,403 odpowiedzi

319,554 komentarzy

61,939 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...