Przekazanie enum do funkcji

0

Witam. Mam problem z enum. W mojej klasie wszystkie składni(name, surname) przechodzą z funkcji enter_data() do show(). Jednak problem jest z enumem, który nie chce przejść i nie mam pojęcia czemu.


#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>
#include <sstream>

using namespace std;
enum POSSITION {
	Goalkeeper=1,
	Defender=2,
	Helper=3,
	Attacker=4
};

class Player {
	string name;
	string surname;
	POSSITION posOnThePitch;



public:

	void enter_data() {

		cout << "\nName: "; 
		cin >> name;
		cout << "Surname: "; 
		cin >> surname;
		cout << "\n\n\nSelect Possition:\n"; 
		cout << "1.Goalkeeper" << endl;
		cout << "2.Defender" << endl;
		cout << "3.Helper" << endl;
		cout << "4.Attacker\n\n\n" << endl;


		int temp_possition;
		cin >> temp_possition;
		POSSITION posOnThePitch = static_cast<POSSITION>(temp_possition);

		
	}

	string show()
	{
		string temp;
		cout << "xd" << endl;

		temp = name + " " + surname + " " + posOnThePitch;
		cout << temp << endl;
		return temp;
	}

};

int main()
{
	Player p1;
	p1.enter_data();
	p1.show();

	system("pause");

}// main
 

Problem pojawia się dokładnie w tej linijce:

temp = name + " " + surname + " " + posOnThePitch; 

Name oraz surname ładnie się wyświetlają, ale gdy dodam posOnThePitch to nie kompiluje. Na pewno dałoby się to jakoś rozwiązać poprzez przeciążenie operatora, ale ja chcę normalnie.

4

string + enum nie ma sensu (o ile go temu wyrażeniu nie nadasz).

użyj std::to_string aby zamienić enum na string (jako liczbę).

3

Właśnie, co istotne - std::to_string(jakis_enum) zwróci Ci liczbę odpowiadającą jakis_enum w stringu. Jeśli chciałbyś mieć słowną interpretację tego enuma, to problem jest bo w runtime takich informacji już nie ma. Musiałbyś zrobić mapę enum -> string.

0

pingwindykator: otóż mylisz się. Można to zrobić za pomocą "stringification" - https://gcc.gnu.org/onlinedocs/cpp/Stringification.html

#include <iostream>

enum class Test
{
	EPierwszy,
	EDrugi
};

#define Enum2String(x) #x

int main()
{
	std::cout << Enum2String(Test::EDrugi);

	return 0;
}
3

@intruz to teraz napisz takie stringification, które wyciągnie ci nazwę wartości enuma ze zmiennej i zadziała niezależnie od tego czy wartości enuma są ciągiem monotonicznym, czy nie.
Można to zrobić tak jak zasugerował @pingwindyktator albo użyć gotowego rozwiązania (np. https://github.com/aantron/better-enums), albo poczekać aż w c++1z wejdzie jakiś proposal ze statyczną refleksją.

0

Daj człowiekowi palec to weźmie rękę.. Satirev, czy ja gdziekolwiek napisałem że takie coś zadziała do wyciągania wartości ze zmiennej? stringification z C tak nie działa więc nie wiem o co się burzysz ?

Klasa z linka całkiem fajna.

0

Na razie dałem sobie spokój z enumem i robię dalej. Teraz problem jest z zapisem do pliku. Kiedys używałem przeciążenia operatora do tego i fajnie się zapisywało, ale teraz chcę to zrobić na inny sposób bo na pewno taki też istnieje. Ktoś pomoże ? Kod do zapisu wygląda tak:

#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>
#include <sstream>

using namespace std;


class Player {
	string name;
	string surname;
	string posOnThePitch;



public:

	void enter_data() {

		cout << "\nName: "; 
		cin >> name;
		cout << "Surname: "; 
		cin >> surname;
		cout << "Possition: ";
		cin >> posOnThePitch;
		
	}

	string getFulName()
	{
		string temp;
		temp = name + " " + surname + ", " + posOnThePitch;
			return temp;
	}
	

};

class Team {
	list<Player>team;
public:
	void add_player()
	{
		Player player;
		player.enter_data();
		team.push_back(player);
		cout << "\n\n\n";
	}
	void display_list()
	{
		if (team.empty())
		{
			cout << "\n\nThe list is empty. Add player or open list from file.\n\n";
		}
		cout << "\n\n\n";
		list<Player>::iterator it = team.begin();
		int number=1;
		while (it != team.end())
		{
			cout << number++ << ": " << it->getFulName()<<endl;
			it++;
		}
		cout << "\n\n\n";
	}
};

int main()
{
	Team team;

	char switchOption;
	do {
		cout << "1. Add player" << '\n';
		cout << "2. Display list" << '\n';
		cout << "3. Save to file" << '\n';
		cout << "4. Read from file" << '\n';
		cout << "5. Remove player from list" << '\n';
		cout << "6. Exit" << '\n';
		cin >> switchOption;
		switch (switchOption) {
		case '1'://1. Add player
		{
			team.add_player();
			break;
		}
		case '2'://2. Display list
		{
			team.display_list();
			break;
		}
		case '3'://3. Save to file
		{///////////////////////////////////////////////////////////
			ofstream file;
			file.open("list.txt");
		
			
			list<Team>team;
			list<Team>::iterator it = team.begin();
			int number = 1;
			while (it != team.end())
			{
				file << it->display_list();
				it++;
			}
			file.close();
			break;
		}///////////////////////////////////////////////

		case '4'://Open from file
		{
			//jjjj
		}

		break;
		case '5':// 5. Remove player from list
		{
			cout << "working..\n";
			break;
		}
		case '6':// 6.exit
		{
			cout << "Goodbye !\n";
			break;
		}
		default:
		{
			cerr << "Jakis nieokreslony przypadek.\n";
		}
		}
	} while (switchOption != '6');






	system("pause");

}// main
 

kompilator krzyczy tutaj

 file << it->display_list();
1
file << it->display_list(); 

Czumu miałby nie krzyczeć. Próbujesz zapisać do pliku efekt wywołania funkcji, która nic nie zwraca.

Taki zapis do pliku (całego obiektu) można dokonać jeśli jest on PODem.
Poczytaj o serializacji.

edit:
Możesz dodać taki kod do klasy team

void save_list_to_file() {
        ofstream file("list.txt");
        if (file.is_open()) {
            file << team.size() << '\n';
            for (auto const& el : team) {
                file << el.getFulName().c_str() << '\n';
            }
        }
    } 

i w switchu tylko wywołać:

team.save_list_to_file(); 

Btw: w twoim switchu masz zadeklarowaną nową listę (pustą) i ją wypisujesz (niewypisujesz).

0

Ta linijka nie przechodzi przez kompilator :(

  file << el.getFulName().c_str() << '\n';
2
string getFulName()

Zamień na:

string getFulName() const
0

Dzięki. "Prawie działa". Zapisuje wszystko ładnie do pliku, ale zapisuje również opcję jaką wybiorę z menu. Przykład:
wybieram opcję nr 1 (add player), czyli wciskam na klawiaturze klawisz "1". Potem zapisuje do pliku i wraz z danymi zapisuje mi się "1". Z tym jakoś pokombinuję.
Teraz chciałem pójść w drugą stronę, czyli wczytać dane z pliku. Zamieszczam poniżej kod. W deklaracji klasy Player dodałem przyjaźń z klasą Team w której jest funkcja do wczytywania z pliku, jednak coś popsułem z argumentami jakie trzeba przekazać. Może ktoś poprawić ?

 

#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>
#include <sstream>

using namespace std;


class Player {
	string name;
	string surname;
	string posOnThePitch;
	friend class Team;
	friend void Team::open_list_from_file(Player&);



public:

	void enter_data() {

		cout << "\nName: "; 
		cin >> name;
		cout << "Surname: "; 
		cin >> surname;
		cout << "Possition: ";
		cin >> posOnThePitch;
		
	}

	string getFulName() const
	{
		string temp;
		temp = name + " " + surname + "," + posOnThePitch;
			return temp;
	}
	

};

class Team {
	list<Player>team;
public:
	void add_player()
	{
		Player player;
		player.enter_data();
		team.push_back(player);
		cout << "\n\n\n";
	}
	void display_list()
	{
		if (team.empty())
		{
			cout << "\n\nThe list is empty. Add player or open list from file.\n\n";
		}
		cout << "\n\n\n";
		list<Player>::iterator it = team.begin();
		int number=1;
		while (it != team.end())
		{
			cout << number++ << ": " << it->getFulName()<<endl;
			it++;
		}
		cout << "\n\n\n";
	}
	
	void save_list_to_file() {
		ofstream file("list.txt");
		if (file.is_open()) {
			file << team.size() <<endl;
			for (auto const& el : team) {
				file << el.getFulName().c_str() << endl;
			}
		}
		file.close();
	}
	void open_list_from_file(Player& p1){
		ifstream file("list.txt");
		if (!file.good()) 
		{ 
			cout << "\n Error. I can't open file. \n\n" << endl; 
		}
		else if(file.peek()==EOF)
		{
			cout << "\n Opened file is empty ! \n" << endl; 
		}
		else
		{
			Player p1;
			getline(file, p1.name, ' ');
			getline(file, p1.surname, ',');
			getline(file, p1.posOnThePitch, ' ');
			team.push_back(p1);
		}
	}
};

int main()
{
	Team team;

	char switchOption;
	do {
		cout << "1. Add player" << '\n';
		cout << "2. Display list" << '\n';
		cout << "3. Save to file" << '\n';
		cout << "4. Read from file" << '\n';
		cout << "5. Remove player from list" << '\n';
		cout << "6. Exit" << '\n';
		cin >> switchOption;
		switch (switchOption) {
		case '1'://1. Add player
		{
			team.add_player();
			break;
		}
		case '2'://2. Display list
		{
			team.display_list();
			break;
		}
		case '3'://3. Save to file
		{///////////////////////////////////////////////////////////

			team.save_list_to_file();

			break;
		}///////////////////////////////////////////////

		case '4'://Open from file
		{
			team.open_list_from_file();
		}

		break;
		case '5':// 5. Remove player from list
		{
			cout << "working..\n";
			break;
		}
		case '6':// 6.exit
		{
			cout << "Goodbye !\n";
			break;
		}
		default:
		{
			cerr << "Jakis nieokreslony przypadek.\n";
		}
		}
	} while (switchOption != '6');






	system("pause");

}// main
1

Z kodu wynika, że zapisywana jest wielkość teamu.

0

No tak :) Masz rację. Wystarczyło usunąć jedną linijkę:

   file << team.size() <<endl; 

Zapis już działa tak jak chcę. Moje niedopatrzenie.

Tylko teraz co z tym odczytaniem z pliku ?

#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>
#include <sstream>

using namespace std;

class Team;
class Player {
	string name;
	string surname;
	string posOnThePitch;
	



public:
	friend class Team;
	friend void Team::open_list_from_file(Player&);
	void enter_data() {

		cout << "\nName: "; 
		cin >> name;
		cout << "Surname: "; 
		cin >> surname;
		cout << "Possition: ";
		cin >> posOnThePitch;
		
	}

	string getFulName() const
	{
		string temp;
		temp = name + " " + surname + "," + posOnThePitch;
			return temp;
	}
	

};

class Team {
	list<Player>team;
public:
	void add_player()
	{
		Player player;
		player.enter_data();
		team.push_back(player);
		cout << "\n\n\n";
	}
	void display_list()
	{
		if (team.empty())
		{
			cout << "\n\nThe list is empty. Add player or open list from file.\n\n";
		}
		cout << "\n\n\n";
		list<Player>::iterator it = team.begin();
		int number=1;
		while (it != team.end())
		{
			cout << number++ << ": " << it->getFulName()<<endl;
			it++;
		}
		cout << "\n\n\n";
	}
	
	void save_list_to_file() {
		ofstream file("list.txt");
		if (file.is_open()) {
			for (auto const& el : team) {
				file << el.getFulName().c_str() << endl;
			}
		}
		file.close();
	}
	void open_list_from_file(Player& p1){
		ifstream file("list.txt");
		if (!file.good()) 
		{ 
			cout << "\n Error. I can't open file. \n\n" << endl; 
		}
		else if(file.peek()==EOF)
		{
			cout << "\n Opened file is empty ! \n" << endl; 
		}
		else
		{
			getline(file, p1.name, ' ');
			getline(file, p1.surname, ',');
			getline(file, p1.posOnThePitch, ' ');
			team.push_back(p1);
		}
	}
};

int main()
{
	Team team;

	char switchOption;
	do {
		cout << "1. Add player" << '\n';
		cout << "2. Display list" << '\n';
		cout << "3. Save to file" << '\n';
		cout << "4. Read from file" << '\n';
		cout << "5. Remove player from list" << '\n';
		cout << "6. Exit" << '\n';
		cin >> switchOption;
		switch (switchOption) {
		case '1'://1. Add player
		{
			team.add_player();
			break;
		}
		case '2'://2. Display list
		{
			team.display_list();
			break;
		}
		case '3'://3. Save to file
		{///////////////////////////////////////////////////////////

			team.save_list_to_file();

			break;
		}///////////////////////////////////////////////

		case '4'://Open from file
		{
			Player p1;
			team.open_list_from_file(p1);
		}

		break;
		case '5':// 5. Remove player from list
		{
			cout << "working..\n";
			break;
		}
		case '6':// 6.exit
		{
			cout << "Goodbye !\n";
			break;
		}
		default:
		{
			cerr << "Jakis nieokreslony przypadek.\n";
		}
		}
	} while (switchOption != '6');






	system("pause");

}// main
 

Kompilator krzyczy tutaj:

	friend void Team::open_list_from_file(Player&); 

Przekazałem złe argumenty czy źle zadeklarowałem przyjaźń ? Nie mam już pojęcia jak to napisać.

1
friend void Team::open_list_from_file(Player&); 

Funkcja zaprzyjaźniona z klasą Team nie może być zadeklarowana w klasie Player.

Odczytywanie z pliku robisz dokładnie tak samo jak przy zapisie. Nie potrzebujesz jakiś dodatkowych funkcji zaprzyjaźnionych.

edit:

getline(file, p1.posOnThePitch, ' '); 

W pliku za zapisaną pozycją nie ma już spacji.

0

Poradziłem sobie już z odczytem i zapisem. Przy odczycie jednak w ramach nauki wykorzystałem funkcje zaprzyjaźnione i działa.
Zamieszczam kod, gdyby ktoś początkujący tak jak nadal ja, potrzebował tego.

#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>
#include <sstream>

using namespace std;

class Team;
class Player {
	string name;
	string surname;
	string posOnThePitch;




public:
	friend class Team;

	void enter_data() {

		cout << "\nName: ";
		cin >> name;
		cout << "Surname: ";
		cin >> surname;
		cout << "Possition: ";
		cin >> posOnThePitch;

	}

	string getFulName() const
	{
		string temp;
		temp = name + " " + surname + "," + posOnThePitch;
		return temp;
	}


};

class Team {
	list<Player>team;
public:
	friend void Team::open_list_from_file(Player&);
	void add_player()
	{
		Player player;
		player.enter_data();
		team.push_back(player);
		cout << "\n\n\n";
	}
	void display_list()
	{
		if (team.empty())
		{
			cout << "\n\nThe list is empty. Add player or open list from file.\n\n";
		}
		cout << "\n\n\n";
		list<Player>::iterator it = team.begin();
		int number = 1;
		while (it != team.end())
		{
			cout << number++ << ": " << it->getFulName() << endl;
			it++;
		}
		cout << "\n\n\n";
	}

	void save_list_to_file() {
		if (team.empty())
		{
			cout << "\n\n Your player's list ist empty ! No data to save. \n\n" << endl;
			exit;
		}
		else
		{
			ofstream file("list.txt");
			if (file.is_open()) {
				for (auto const& el : team) {
					file << el.getFulName().c_str() << endl;
				}
			}
			file.close();
		}

		
	}
	void open_list_from_file(Player& p1) {
		ifstream file("list.txt");
		if (!file.good())
		{
			cout << "\n Error. I can't open file. \n\n" << endl;
			exit;

		}
		else if (file.peek() == EOF)
		{
			cout << "\n Opened file is empty ! \n" << endl;
			exit;
		}
		else
		{

			while (!file.eof())
			{


				getline(file, p1.name, ' ');
				if (p1.name == "")
				{
				
					break;
				}
				getline(file, p1.surname, ',');
				getline(file, p1.posOnThePitch);
				team.push_back(p1);
			}
			cout << "\n\n Your data has beem loaded.\n\n";
		}
		file.close();

	}
};

int main()
{
	Team team;

	char switchOption;
	do {
		cout << "1. Add player" << '\n';
		cout << "2. Display list" << '\n';
		cout << "3. Save to file" << '\n';
		cout << "4. Read from file" << '\n';
		cout << "5. Remove player from list" << '\n';
		cout << "6. Exit" << '\n';
		cin >> switchOption;
		switch (switchOption) {
		case '1'://1. Add player
		{
			team.add_player();
			break;
		}
		case '2'://2. Display list
		{
			team.display_list();
			break;
		}
		case '3'://3. Save to file
		{///////////////////////////////////////////////////////////

			team.save_list_to_file();

			break;
		}///////////////////////////////////////////////

		case '4'://Open from file
		{
			Player p1;
			team.open_list_from_file(p1);
			break;
		}


		case '5':// 5. Remove player from list
		{
			cout << "working..\n";
			break;
		}
		case '6':// 6.exit
		{
			cout << "Goodbye !\n";
			break;
		}
		default:
		{
			cerr << "Jakis nieokreslony przypadek.\n";
		}
		}
	} while (switchOption != '6');






	system("pause");

}// main
 
0
while (!file.eof())
            {


                getline(file, p1.name, ' ');
                if (p1.name == "")
                {

                    break;
                }
                getline(file, p1.surname, ',');
                getline(file, p1.posOnThePitch);
                team.push_back(p1);
            } 

Brzydkie rozwiązanie. Nadal nie rozumiesz relacji między tymi klasami (struct byłby wygodniejszy lub pola publiczne w klasie Player).
Player wykorzystuj jak każdy inny typ wbudowany.

Z

while(!file.eof()) 

też wiąże się ryzyko wczytywania głupot po ostatnim prawidłowym wczytaniu obiektu.
eof() zwraca false dopiero przy próbie odczytania z końca pliku, a nie gdy pętla doczyta do końca pliku.
Powstaje dodatkowy obrót pętli.

0

Na razie cieszy mnie, że działa. Jednak faktycznie możesz mieć rację. Co byś proponował aby to zoptymalizować bo na razie pojęcia nie mam.

0

Zrezygnowałem z tego:

lub pola publiczne w klasie Player

aby być w zgodzie z enkapsulacją klas.

#include<iostream>
#include <string>
#include <list>
#include <fstream>

using namespace std; // staraj się jak najmniej używać przestrzeni std

class Player {
    string name;
    string surname;
    string posOnThePitch;
public:
    friend istream& operator >> (istream& is, Player& player) {
        cout << "\nName: ";
        is >> player.name;
        cout << "Surname: ";
        is >> player.surname;
        cout << "Possition: ";
        is >> player.posOnThePitch;
        return is;
    }

    friend ostream& operator<<(ostream& os, const Player& player) {
        return os << player.name + " " + player.surname + "," + player.posOnThePitch;;
    }

    friend ifstream& operator >> (ifstream& in, Player& player) {
        getline(in, player.name, ' ');
        getline(in, player.surname, ',');
        getline(in, player.posOnThePitch);
        return in;
    }

    friend ofstream& operator<<(ofstream& out, const Player& player) {
        constexpr char space[] = " ";
        constexpr char comma[] = ", ";
        out << player.name.c_str() << space << player.surname.c_str() << comma << player.posOnThePitch.c_str();
        return out;
    }
};

class Team {
    list<Player> team;
public:
    void add_player()
    {
        Player player;
        cin >> player;
        team.push_back(player);
        cout << "\n\n\n";
    }

    void display_list()
    {
        if (team.empty())
        {
            cout << "\n\nThe list is empty. Add player or open list from file.\n\n";
            return;
        }
        int nr{ 1 };
        for (auto const& elem : team) {
            cout << nr++ << ": " << elem << '\n';
        }
        cout << "\n\n\n";
    }

    void save_list_to_file() {
        if (team.empty())
        {
            cout << "\n\n Your player's list ist empty ! No data to save. \n\n" << endl;
            exit;
        }
        else
        {
            ofstream file("list.txt");
            if (file.is_open()) {
                for (auto const& el : team) {
                    file << el << '\n';
                }
            }
            file.close();
        }


    }

    void open_list_from_file() {
        ifstream file("list.txt");
        if (!file.good())
        {
            cout << "\n Error. I can't open file. \n\n" << endl;
            exit;

        }
        else if (file.peek() == EOF)
        {
            cout << "\n Opened file is empty ! \n" << endl;
            exit;
        }
        else
        {
            Player tmpPlayer;
            while (file >> tmpPlayer) {
                team.push_back(tmpPlayer);
            }
            cout << "\n\n Your data has beem loaded.\n\n";
        }
        file.close();

    }
};

int main()
{
    Team team;

    char switchOption;
    do {
        cout << "1. Add player" << '\n';
        cout << "2. Display list" << '\n';
        cout << "3. Save to file" << '\n';
        cout << "4. Read from file" << '\n';
        cout << "5. Remove player from list" << '\n';
        cout << "6. Exit" << '\n';
        cin >> switchOption;
        switch (switchOption) {
        case '1'://1. Add player
        {
            team.add_player();
            break;
        }
        case '2'://2. Display list
        {
            team.display_list();
            break;
        }
        case '3'://3. Save to file
        {///////////////////////////////////////////////////////////

            team.save_list_to_file();

            break;
        }///////////////////////////////////////////////
        case '4'://Open from file
        {            
            team.open_list_from_file();
            break;
        }
        case '5':// 5. Remove player from list
        {
            cout << "working..\n";
            break;
        }
        case '6':// 6.exit
        {
            cout << "Goodbye !\n";
            break;
        }
        default:
        {
            cerr << "Jakis nieokreslony przypadek.\n";
        }
        }
    } while (switchOption != '6');
} 

Teraz jest kilka wywołań i instrukcji, a całe gro to część opisowa.
Jeśli tylko można, należy ukrywać co się tylko da i maksymalnie upodobnić używanie klasy do typów wbudowanych.
Wczytywanie z pliku dałbym w ctorze klasy Team, aby odczyt z pliku był przy tworzeniu obiektu,
natomiast zapis do pliku albo przy dodawaniu graczy lub przed wyjściem z programu. Wtedy metody od pliku mogłyby być
prywatne. Zostawiam to do rozważenie. (Zabieg zmiany to tylko kilka przeklej z miejsca na miejsce).

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