• 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
1,036 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ź 532 wizyt
pytanie zadane 10 grudnia 2016 w C i C++ przez Kasztan Dyskutant (8,080 p.)
+1 głos
3 odpowiedzi 889 wizyt
0 głosów
1 odpowiedź 1,244 wizyt
pytanie zadane 16 czerwca 2017 w C i C++ przez excavelty Bywalec (2,480 p.)

92,695 zapytań

141,606 odpowiedzi

320,106 komentarzy

62,052 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

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!

...