Baza danych pracowników - pomoc z zadaniem

0

Witam,
Dostałem kolejne zadanie do zrobienia. Jest to moje pierwsze spotkanie z template więc nie bijcie! :D
Mamy podane main() i do niego mamy dorobić potrzebne klasy tak żeby wszystko działało. Część zadania już działa.
Komentarze dodałem po polsku ale kod będę pisał po angielsku. Po prostu do tłumaczenia profesorowi tak będzie lepiej.
Potrzebuję jeszcze dopisać kod do rzeczy, które zakomentowałem:

*cout - operator << do ostream

*DataBase = NewDatabase - tu jak rozumiem operator= ?

Kod maptemplate.cpp:

#include "maptemplate.h"

int main(void)
{
    typedef unsigned int ID;                            //Identification number of Employee
    map_template<ID,Employee> Database;                 //Database of employees

    Database.Add(761028073,Employee("Jan Kowalski","salesman",28));     //Add first employee: name: Jan Kowalski, position: salseman, age: 28,
    Database.Add(510212881,Employee("Adam Nowak","storekeeper",54));    //Add second employee: name: Adam Nowak, position: storekeeper, age: 54
    Database.Add(730505129,Employee("Anna Zaradna","secretary",32));    //Add third employee: name: Anna Zaradna, position: secretary, age: 32

    //cout << Database << endl;                         //Print databese

    //map_template<ID,Employee> NewDatabase = Database; //Make a copy of database

    Employee* pE;
    pE = Database.Find(510212881);       //Find employee using its ID
    pE->Position = "salesman";          //Modify the position of employee
    pE = Database.Find(761028073);     //Find employee using its ID
    pE->Age = 29;             //Modify the age of employee

    //Database = NewDatabase;    //Update original database
 
    ///cout << Database << endl;  //Print original database
cout<<"Wszystko dziala"<<endl;
}

kod maptemplate.h:

#include <iostream>
#include <vector>

using namespace std;

//Początek klasy Employee bez template
class Employee
{
private:

public:
    Employee(string Name, string Position, int Age);
    string Name;
    int Age;
    string Position;

};//koniec klasy employee

//Dodanie pól Name, Age, Position
Employee::Employee(string Name, string Position, int Age)
{
    this->Name = Name;
    this->Age = Age;
    this->Position = Position;

}

template <class Key, class T> //template <klucze, dane pracownikow>
class map_template{ 
private:
    vector<Key> keys;   //vector do przechowywania unikalnych kluczy pracowników
    vector<T> content;  //vector do przechowywania danych pracowników
public:
    map_template(){}
    void Add(Key key, T t);
    T* Find(Key key);
}; //koniec klasy map_template

//Dodanie do bazy (Add)
template<class Key, class T>
void map_template <Key, T>::Add(Key key, T t)
{
    keys.push_back(key);
    content.push_back(t);
}
//Szukanie w bazie (Find)
template<class Key, class T>
T* map_template<Key, T>::Find(Key key)
{
    for(unsigned int i = 0; i < keys.size(); i++)
        if (keys[i] == key)
        {
            return &content.at(i);
        }
return nullptr;
}


A zatem pytania :D

  1. Jaki nagłówek powinien być do operatora <<. Z tego co widziałem w google to w niektórych przypkach nagłówek był dosyć długi albo nie widziałem zależności więc potrzebuję wytłumaczenia..
    Co w tym powinienem dopisać / zmienić?
 friend ostream & operator<< (ostream & s, tutaj coś na wejscie);

// będzie trzeba odczytać map_template<ID,Employee> Database

Czy nad tą metodą powinno być też template<class Key, class T> ?

Jak zrobię cout, to zajmę się robieniem NewDatabase tak żeby już widzieć jak DataBase wygląda.
Jak ktoś ma jakieś porady, albo pomysły to proszę o aktywność! :D Będę nagradzał lajkami :) Konstruktywny hejt też zlajkuję :D

1

Do Peruna, pora zacząć używać nowocześniejszych składników C++, a w pierwszej kolejności nowego słowa kluczowego auto jak będziesz definiował operator <<.
Nie zapomnij włączyć w kompilatorze flagę obsługi minimum C++11, inaczej auto nie zadziała

0

samo to, że mam użyć "auto" mi nic nie mówi niestety, bo w operator<< nigdy tego nie używałem. Ucząc się z Tobą używałem go tylko z dwa razy :/

Nagłówek operator << może wyglądać tak?

//operator <<
template <class Key, class T>
ostream& operator << (ostream& out, const map_template<Key, T>& map) 
{
    out << map.Name << map.Position << map.Age;  
    return out;
}

map.Name ani inne rzeczy nie zadziałały, a ślepych prób robiłem wiele. Niestety nie ogarniam jak mam się dostać do danych...

Name, Position i Age są zadeklarowane w klasie Employee. A jeśli dobrze rozumiem, to potem dane tych obiektów są przechowywane w vector<T> content.

czyli najpierw bym chciał wejść do content, a potem do danych pól Name itd.

Mógłby ktoś na szybko wytłumaczyć jak to zrobić?

1

Pogóglaj sobie za frazą "specjalizowanie szablonu klas", możliwe, że operator<< będzie wymagał konkretyzacji map_template'a. Ale generalnie dobrze kombinujesz, ino te znaczki referencji stawiaj jak Swaróg przykazał przy zmiennej.
Co do dobierania się do zmiennych name, age itd to zapomniałeś Bracie, że tam po drodze są wektory content i keys, jako prywatne składniki map_template'a. Wygląda znajomo? Powinno :]

0

Nie bardzo rozumiem co będzie do zrobienia. To co wyczytałem to, że specjalizowanie szablonu polega na robieniu szablonów dla danego typu - string itd. i że wygląda to wtedy tak:

template <>

i że to jest to specjalizowanie szablonu klasy.
Znaczki referencji poprawiłem :)
Co do operator << to jeśli są prywatne to muszę dać friend przed całą metodą operator << czy w jakiś inny sposób to zrobić?
Próbowałem dodawać friend to wyrzucało błąd:

maptemplate.h:60:1   'friend' used outside of class

no to oczywiście chciałem dodać deklarację całego operatora << do klasy. Ale tutaj miałem kolejne problemy:
deklaracja tego powinna wyglądać jakoś tak:

//Nagłówek:
friend ostream& operator << (ostream& out, const map_template<Key, T>& map){}
//Deklaracja 
ostream& operator << (ostream& , tutaj nie wiem co)

No i generalnie to nie ogarniam już coraz bardziej tego wszystkiego. Niby prosty operator << do napisania, a siedzę już ponad godzinę nad tym xd

0

Ktokolwiek może ogarnia ten temat?
Obecny kod:

#include <iostream>
#include <vector>

using namespace std;


template <class Key, class T> //template <klucze, dane pracownikow>
class map_template{ 
private:
    vector<Key> keys;   //vector do przechowywania unikalnych kluczy pracowników
    vector<T> content;  //vector do przechowywania danych pracowników
public:

    map_template(){}
    void Add(Key key, T t);
    T* Find(Key key);
}; //koniec klasy map_template

//Dodanie do bazy (Add)
template<class Key, class T>
void map_template <Key, T>::Add(Key key, T t)
{
    keys.push_back(key);
    content.push_back(t);
}
//Szukanie w bazie (Find)
template<class Key, class T>
T* map_template<Key, T>::Find(Key key)
{
    for(unsigned int i = 0; i < keys.size(); i++)
        if (keys[i] == key)
        {
            return &content.at(i);
        }
return nullptr;
}

//Początek klasy Employee bez template
class Employee
{
private:

public:
    Employee(string Name, string Position, int Age);
    string Name;
    int Age;
    string Position;

};//koniec klasy employee

//Dodanie pól Name, Age, Position
Employee::Employee(string Name, string Position, int Age)
{
    this->Name = Name;
    this->Age = Age;
    this->Position = Position;

}
//operator <<
template<class Key, class T>
ostream &operator << (ostream &out, const map_template<Key, T> &map) {
 out << map.Name << map.Position << map.Age;
    return out;
}

Na samym dole jest kod do operator <<. Musi tutaj zadziałać wypisanie w mainie:

map_template<ID,Employee> Database;                 //Database of employees
\...\
cout << Database << endl;

Obecne errory:

maptemplate.h: In instantiation of ‘std::ostream& operator<<(std::ostream&, const map_template<Key, T>&) [with Key = unsigned int; T = Employee; std::ostream = std::basic_ostream<char>]’:
maptemplate.cpp:12:13:   required from here
maptemplate.h:62:13: error: ‘const class map_template<unsigned int, Employee>’ has no member named ‘Name’
  out << map.Name << map.Position << map.Age;
         ~~~~^~~~
maptemplate.h:62:25: error: ‘const class map_template<unsigned int, Employee>’ has no member named ‘Position’
  out << map.Name << map.Position << map.Age;
                     ~~~~^~~~~~~~
maptemplate.h:62:41: error: ‘const class map_template<unsigned int, Employee>’ has no member named ‘Age’
  out << map.Name << map.Position << map.Age;

Może ktoś ma pomysł jak to wypisać poprawnie?

2

Akurat deklaracja przyjaźni to część, która się udaje:

//deklaracje zapowiadające okazują się być potrzebne, inaczej się rzuca o nieznajomość typów
template <class Key, class T> class map_template; 
template <class Key, class T> ostream& operator<<(ostream &o, const map_template<Key, T> &map);

template <class Key, class T> //template <klucze, dane pracownikow>
class map_template{ 
private:
    vector<Key> keys;   //vector do przechowywania unikalnych kluczy pracowników
    vector<T> content;  //vector do przechowywania danych pracowników

public: 
    map_template(){}

    void Add(Key key, T t);
    T* Find(Key key);

friend ostream& operator<< <> (ostream &out, const map_template<Key, T> &map);
};

tylko z użyciem tego były problemy, cały czas mi wyrzucał błąd że nie ma definicji szablonu dla podanych typów Key i T.

EDIT:
Coś Bracie @wiezaawieza ruszyło w temacie.

EDIT2:
Sukces!
DlaWieży.PNG
Dobra Bracie @wiezaawieza, to najcięższą część, czyli deklarację i definicję wspólnymi siłami z Bratem @kq rozkminiłem. Dalej radź sobie sam, bacz na moje wcześniejsze uwagi.

EDIT3:
W sumie, to nie daliśmy definicji dla operatora<<

template<class Key, class T>
ostream& operator<<(ostream &out, const map_template<Key, T> &map)
{
    out << "dupa";   
    return out;
}
1

Mała podpowiedź @wiezaawieza - jak się wyjmuje jakąś daną z std::vector?

0

Odpowiedź na twoją wskazówkę:
Jeśli chodzi o odczytanie wartości to c++ reference podaje, że robi się to podając indeks danej w nawiasach [].
Czyli u nas by to było content[0] na przykład.
http://www.cplusplus.com/reference/vector/vector/operator[]/

Próbowałem kilka funkcji z c++ reference i większość mi nie zadziałała co prawda ale np. map.content.size() wykazało, że size = 3.
Czyli zapewne Name, Age, Position :D
Do tego próbowałem używać funkcji at() ale niestety nic to nie dało.
Jedynie jeszcze funkcja .data() mi wypisała ładnie adres czy coś ;d

No ale chyba chodzi o [ ]. Próbowałem coś w stylu: map.content[0] żeby sprawdzić co jest w pierwszym elemencie ale no też błędy więc nie wiem :/

Jeszcze jakaś mini podpowiedź chyba potrzebna :D

0

Bardzo dobrze, naprawdę ciepło!
A weź Ty mi powiedz Bracie @wiezaawieza, co dokładnie siedzi w tym konkretnym, stworzonym u Ciebie w main() obiekcie map_template, w wektorze content? :]

0

No jest ID i Employee
W tym:
Employee rozdziela się na 3 pola:
Age, Name i Position

Ale samo ID jest z tego drugiego wektora keys, bo to te unikalne wartości pracowników, jakkolwiek to rozumieć ;d

Ale zapis map.content.Employee i coś tam dalej raczej nie zadziała nie?

1

Cieplutko, baaaardzo cieplutko :D
Może tak - piszesz, że próbowałeś map.content[0] ale nie działało. A weź Ty mi Bracie powiedz, co się dzieje jak na std::vector robisz wektor[indeks]? :]

0

No generalnie powinno zwrócić wartość elementu z danego indeksu w tym wektorze.

Chyba, że jednak zwraca referencję do danego elementu:
https://en.cppreference.com/w/cpp/container/vector/operator_at
Nie wiem czy ten operator[] to zupełnie co innego niż się zajmujemy czy nie ale no to tutaj wyczytałem, że zwraca referencję.
zapis
&map.content[0] sobie sprawdziłem i wypisuje znowu jakiś adres elementu 0, a nie wartość. A bez & nie działa więc nwm :/

EDIT! SUKCES!

map.content[0].Name itd!
Bo content[0] to dla nas
Jezu jak ty mnie dobrze naprowadzasz xD Lecę zrobić tego couta ładnie. Do poprawy pewnie będzie for ale ogólnie to jestem zadowolony już xD Nawet nie wiesz jak :D

1

Bardzo dobrze! Jeszcze tylko jedno napięcie mózgownicy i odnajdziesz Światłość Swaroga^^
Zwraca referencję do elementu. A cóż to u nas w programie jest tym elementem? Żebyś się w dywagacje nie zapuszczał - przyjmijmy, że mówimy o wektorze map.content.

1

MISSION COMPLETED
title
Kolejna zbłąkana po bezdrożach klas szablonowych dusza doznała oświecenia. Choć sroodze się przez zrozumieniem broniła :]

0

Obecny kod main:

#include "maptemplate.h"

int main(void)
{
    typedef unsigned int ID;                            //Identification number of Employee
    map_template<ID,Employee> Database;                 //Database of employees

    Database.Add(761028073,Employee("Jan Kowalski","salesman",28));     //Add first employee: name: Jan Kowalski, position: salseman, age: 28,
    Database.Add(510212881,Employee("Adam Nowak","storekeeper",54));    //Add second employee: name: Adam Nowak, position: storekeeper, age: 54
    Database.Add(730505129,Employee("Anna Zaradna","secretary",32));    //Add third employee: name: Anna Zaradna, position: secretary, age: 32

    cout << Database << endl;                         //Print databese

    //map_template<ID,Employee> NewDatabase = Database; //Make a copy of database

    Employee* pE;
    pE = Database.Find(510212881);       //Find employee using its ID
    pE->Position = "salesman";          //Modify the position of employee
    pE = Database.Find(761028073);     //Find employee using its ID
    pE->Age = 29;             //Modify the age of employee

    //Database = NewDatabase;    //Update original database
 
    cout << Database << endl;  //Print original database
cout<<"Wszystko dziala"<<endl;
}

Obecny kod .h:

#include <iostream>
#include <vector>

using namespace std;

 template <class Key, class T> class map_template; 
 template <class Key, class T> ostream& operator<< (ostream &o,const map_template<Key, T> &map);
template <class Key, class T> //template <klucze, dane pracownikow>
class map_template{ 
private:
    vector<Key> keys;   //vector do przechowywania unikalnych kluczy pracowników
    vector<T> content;  //vector do przechowywania danych pracowników
public:

    map_template(){}
    void Add(Key key, T t);
    T* Find(Key key);
friend ostream& operator<< <>(ostream &out,const map_template<Key, T> &map);
}; //koniec klasy map_template

//Dodanie do bazy (Add)
template<class Key, class T>
void map_template <Key, T>::Add(Key key, T t)
{
    keys.push_back(key);
    content.push_back(t);
}
//Szukanie w bazie (Find)
template<class Key, class T>
T* map_template<Key, T>::Find(Key key)
{
    for(unsigned int i = 0; i < keys.size(); i++)
        if (keys[i] == key)
        {
            return &content.at(i);
        }
return nullptr;
}

//Początek klasy Employee bez template
class Employee
{
private:

public:
    Employee(string Name, string Position, int Age);
    string Name;
    int Age;
    string Position;

};//koniec klasy employee

//Dodanie pól Name, Age, Position
Employee::Employee(string Name, string Position, int Age)
{
    this->Name = Name;
    this->Age = Age;
    this->Position = Position;

}
//operator <<
template<class Key, class T>
ostream& operator<<(ostream &out,const map_template<Key, T> &map)
{
	for(unsigned int i=0;i<map.content.size();i++)
	{
		out << map.content[i].Name << ", " <<map.content[i].Position << ", " <<map.content[i].Age <<endl;
	}
return out;
}

wykorzystałem to, że map.content.size() mi wcześniej zadziałało ;D Mam nadzieję, że nie będziesz zły, że tak for'a zapisałem, bo nie lubisz tego zapisu ale ważne, że działa :D A działa poprawnie, bo dodałem jeszcze sobie kilka takich pracowników do main'a i wypisuje wszystkich :)

To teraz pytanko co ogólnie powinienem zrobić w programie jeszcze?
Bo w mainie jest kod żeby dodać NewDatabase = Database, a potem żeby zaktualizować bazę danych. A mi się przecież wszystko aktualizuje bez takiego kopiowania xD I jak usunąłem te komentarze to wszystko się kompiluje i działa ładnie

1

A dorób jeszcze żeby na początku tej linii wypisywał ID pracownika :]
I nie, o takiego for-a ani myślę być zły - po prostu zapis for (const Type &t : container) upraszcza zapis. Co więcej, podpowiem, że jeśli masz dodać ID to taki nowoczesny for tylko będzie przeszkadzał^^

O Database = Database na razie się nie martw, przetestuj tylko czy się dobrze na siebie kopiują, a jak nie to załóż nowy wątek.

0

Oki, dorobione i ładnie wypisuje :) (edytuję kod w poprzednim poście)

No to jest następna rzecz do zrobienia w zadaniu i jak pisałem na początku tego tematu - to jest do zrobienia xD
A co do nowego tematu to mogę założyć jak moderacji to nie przeszkadza ;D Ale ptaszek = 3 lajki. Czy warto tylko po to robić ten nowy temat jak i tak tych lajków dostaniesz od groma? xD

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