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

Odczyt obiektów z pliku

0 głosów
397 wizyt
pytanie zadane 27 września 2017 w C i C++ przez B0nkers Początkujący (310 p.)

Witam,

Zadanie polega na tym aby napisać program, w którym standardowe i plikowe operacje wejścia-wyjścia języka C++ używane są w połączeniu z typami employee, manager, fink oraz highfink. Klasy dziedziczą po wirtualnej klasie bazowej abstr_emp. O tyle z wczytaniem danych do pliku nie ma problemu, to z odczytaniem jest gorzej. Do klas dodałem kilka metod wirtualnych: writeall() oraz getall(), które mają na celu umożliwić komunikacje z plikiem. Utworzyłem też tablice wskaźników na typ abstr_emp, do którego mają być wczytywane dane. (w zadaniu jest napisane, że to ma być tablica wskaźników na typ employee, ale bardziej mi to pasuje na wirtualną klasę bazową). W zadaniu jest też napisane jak odczytywać dane z pliku, określając na początku danych wartość całkowitą określającą typ występującego po niej obiektu. Później podczas wprowadzania danych program odczyta taką wartość, a następnie korzystając z konstrukcji switch utworzy odpowiedni obiekt, który te dane otrzyma: 

enum classkind {Employee, Manager, Fink, Highfink}; //w pliku nagłówkowym
...
int classtype;
while((fin >> classtype).get(ch)) { //znak nowego wiersza odziela wartość całkowitą od danych
       switch(classtype) {
               case Employee : pc[i] = new employee;
                                          break;

 

Poniżej kod źródłowy, plik nagłówkowy i implementacja. Aha i program nie może używać operacji binarnych I/O.

#include "stdafx.h"
#include "emp02.h"
#include <iostream>
#include <fstream>
#include <iomanip>


int main()
{
	using namespace std;
	const char * filename = "employers.txt";

	const int MAX = 10;
	abstr_emp * pc[MAX];
	
	ifstream fin;
	fin.open(filename, ios_base::cur);
	int i = 0;

	if (fin.is_open())
	{
		//wskaźnik na początek
		fin.seekg(0);
		//aktulna zawartosc pliku
		cout << "Oto aktualna zawartosc pliku \"" << filename << "\":\n";
		int classtype;
		char ch;
	
		while ((fin >> classtype).get(ch) && i < MAX)
		{
			switch (classtype)
			{
			case Employee : pc[i] = new employee;
				break;
			case Manager: pc[i] = new manager;
				break;
			case Fink: pc[i] = new fink;
				break;
			case Highfink: pc[i] = new highfink;
				break;
			}
			pc[i++]->getall(fin);
		}
		if (fin.eof())
			fin.clear();
		else 
		{
			cerr << "Blad przy probie odczytu pliku \"" << filename << "\".\n";
			exit(EXIT_FAILURE);
		}
	}
	fin.close();
	int all = i;		//ilość wczytanych plików

	int index;
	cout << "Podaj ile nowych pracownikow chcesz wprowadzic: ";
	cin >> index;
	while((index + all) > MAX)
	{
		cin.clear();
		cout << "Podaj mniejsza liczbe: ";
		cin >> index;
	}

	cout << "Podaj jakich pracownikow chcesz wprowadzic:\n";
	cout << setw(19) << "1. pracownik" << setw(20) << "2. manager" << endl;
	cout << setw(20) << "3. donosiciel" << setw(27) << "4. glo. donosiciel" << endl;
	
	char choice;
	for (i = all; i < index + all; i++)
	{
		cout << "\nOsoba nr " << (i + 1) << ": ";
		(cin >> choice).get();
		switch (choice)
		{
		case '1':
			pc[i] = new employee;
			pc[i]->SetAll();
			break;

		case '2':
			pc[i] = new manager;
			pc[i]->SetAll();
			break;
		case '3':
			pc[i] = new fink;
			pc[i]->SetAll();
			break;

		case '4':
			pc[i] = new highfink;
			pc[i]->SetAll();
			break;
		}
	}

	ofstream fout;
	fout.open(filename, ios_base::app);

	cout << "Koniec wprowadzania. Nastapi teraz skopiowanie do pliku.\n\n";
	for (int i = all; i < index + all; i++)
		pc[i]->writeall(fout);

	for (int i = 0; i < index + all; i++)
	{
		pc[i]->ShowAll();
		cout << endl;
	}

	for (int i = 0; i < index + all; i++)
	{
		delete pc[i];
	}

	
	system("PAUSE");
	return 0;
}


#ifndef EMP_H_
#define EMP_H_
#include <iostream>
#include <string>
#include <fstream>

enum classkind { Employee, Manager, Fink, Highfink };

class abstr_emp
{
private:
	std::string fname;	//imię obiektu abstr_emp
	std::string lname;	//nazwisko obiektu abstr_emp
	std::string job;	//zawód obiektu abstr_emp
	
public:
	
	abstr_emp()
		: fname("noname"), lname("nolastname"), job("brak") {}
	abstr_emp(const std::string & fn, const std::string & ln, const std::string & j)
		: fname(fn), lname(ln), job(j) {}
	virtual void ShowAll() const;	//opisuje i wyświetla wszystkie dane
	virtual void SetAll();			//prosi użytkownika o podanie wartości
	//r17
	virtual void writeall(std::ofstream & file);
	virtual void getall(std::ifstream & file);
	//////
	friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e);
	//tylko wyświetla imię i nazwisko
	virtual ~abstr_emp() = 0;	//wirtualna klasa bazowa, wirtualny destruktor
};

class employee : public abstr_emp
{
public:
	employee()
		: abstr_emp() {}
	employee(const std::string & fn, const std::string & ln, const std::string & j)
		: abstr_emp(fn, ln, j) {}
	virtual void ShowAll() const;
	virtual void SetAll();
	//r17
	virtual void writeall(std::ofstream & file);
	virtual void getall(std::ifstream & file);
	~employee() {}
};

class manager : virtual public abstr_emp
{
private:
	int inchargeof;	//liczba obiektów abstr_emps, którymi zarządza
protected:
	int InChargeOf() const { return inchargeof; }	//wyjście
	int & InChargeOf() { return inchargeof; }		//wejście
public:
	manager()
		: abstr_emp(), inchargeof(0) {}
	manager(const std::string & fn, const std::string & ln, const std::string & j, int ico = 0)
		: abstr_emp(fn, ln, j), inchargeof(ico) {}
	manager(const abstr_emp & e, int ico)
		: abstr_emp(e), inchargeof(ico) {}
	manager(const manager & m)
		: abstr_emp(m), inchargeof(m.inchargeof) {} //nie wiem czemu tak trzeba ale teraz chodzi dobrze
	virtual void ShowAll() const;
	virtual void SetAll();
	//r17
	virtual void writeall(std::ofstream & file);
	virtual void getall(std::ifstream & file);
	~manager() {}
};

class fink : virtual public abstr_emp
{
private:
	std::string reportso;	//do kogo fink (donosiciel ) przesyła raport
protected:
	const std::string ReportsTo() const { return reportso; }
	std::string & ReportsTo() { return reportso; }
public:
	fink()
		: abstr_emp(), reportso("brak") {}
	fink(const std::string & fn, const std::string & ln, const std::string & j, const std::string & rpo)
		: abstr_emp(fn, ln, j), reportso(rpo) {}
	fink(const abstr_emp & e, const std::string & rpo)
		: abstr_emp(e), reportso(rpo) {}
	fink(const fink & e)
		: abstr_emp(e), reportso(e.reportso) {}		//nie wiem czemu tak trzeba ale teraz chodzi dobrze
	virtual void ShowAll() const;
	virtual void SetAll();
	//r17
	virtual void writeall(std::ofstream & file);
	virtual void getall(std::ifstream & file);
	~fink() {}
};

class highfink : public manager, public fink	//główny donosiciel
{

public:
	highfink()
		: abstr_emp(), manager(), fink() {}
	highfink(const std::string & fn, const std::string & ln, const std::string & j, const std::string & rpo, int ico)
		: abstr_emp(fn, ln, j), manager(fn, ln, j, ico), fink(fn, ln, j, rpo) {}
	highfink(const abstr_emp & e, const std::string & rpo, int ico)
		: abstr_emp(e), manager(e, ico), fink(e, rpo) {}
	highfink(const fink & f, int ico)
		: abstr_emp(f), manager(f, ico), fink(f) {}
	highfink(const manager & m, const std::string & rpo)
		: abstr_emp(m), fink(m, rpo), manager(m) {}
	highfink(const highfink & h)
		: abstr_emp(h), manager(h), fink(h) {}
	virtual void ShowAll() const;
	virtual void SetAll();
	//r17
	virtual void writeall(std::ofstream & file);
	virtual void getall(std::ifstream & file);
	~highfink() {}
};

#endif
#include "stdafx.h"
#include "emp02.h"

//metody klasy abstr_emp
void abstr_emp::ShowAll() const
{
	using std::cout;

	cout << "Imie: " << fname << "\n";
	cout << "Nazwisko: " << lname << "\n";
	cout << "Praca: " << job << "\n";
}

void abstr_emp::SetAll() 
{
	using std::cout;

	cout << "Podaj imie: ";
	getline(std::cin, fname);
	cout << "Podaj nazwisko: ";
	getline(std::cin, lname);
	cout << "Podaj prace: ";
	getline(std::cin, job);
}

//funkcja zaprzyjazniona
std::ostream & operator<<(std::ostream & os, const abstr_emp & e)
{
	os << e.fname << " " << e.lname;
	return os;
}

abstr_emp::~abstr_emp() {}

//metody klasy employee
void employee::ShowAll() const 
{
	std::cout << "Pracownik\n";
	abstr_emp::ShowAll();
}

void employee::SetAll()
{
	std::cout << "Pracownik\n";
	abstr_emp::SetAll();
}

//metody klasy manager
void manager::ShowAll() const
{
	std::cout << "Manager\n";
	abstr_emp::ShowAll();
	std::cout << "Liczba pracownikow, ktorymi zarzadza: " << InChargeOf() << "\n";
}

void manager::SetAll()
{
	std::cout << "Manager\n";
	abstr_emp::SetAll();
	std::cout << "Podaj ilosc pracownikow, ktorymi zarzadza: ";
	(std::cin >> InChargeOf()).get();
}

//metody klasy fink
void fink::ShowAll() const
{
	std::cout << "Donosiciel\n";
	abstr_emp::ShowAll();
	std::cout << "Przesyla raport do: " << ReportsTo() << "\n";
}

void fink::SetAll()
{
	std::cout << "Donosiciel\n";
	abstr_emp::SetAll();
	std::cout << "Do kogo przesyla raport: ";
	getline(std::cin, ReportsTo());
}

//metody klasy highfink
void highfink::ShowAll() const
{
	std::cout << "Glowny donosiciel\n";
	abstr_emp::ShowAll();
	std::cout << "Liczba pracownikow, ktorymi zarzadza: " << InChargeOf() << "\n";
	std::cout << "Przesyla raport do: " << ReportsTo() << "\n";
}

void highfink::SetAll()
{
	std::cout << "Glowny donosiciel\n";
	abstr_emp::SetAll();
	std::cout << "Podaj ilosc pracownikow, ktorymi zarzadza: ";
	(std::cin >> InChargeOf()).get();
	std::cout << "Do kogo przesyla raport: ";
	getline(std::cin, ReportsTo());
}

//nowe funkcje z rozdz 17
 void abstr_emp::writeall(std::ofstream & file)
{
	 file << fname << std::endl;
	 file << lname << std::endl;
	 file << job << std::endl;
}

 void employee::writeall(std::ofstream & file)
 {
	 file << Employee << std::endl;
	 abstr_emp::writeall(file);
 }

 void manager::writeall(std::ofstream & file)
 {
	 file << Manager << std::endl;
	 abstr_emp::writeall(file);
	 file << InChargeOf() << std::endl;
 }

 void fink::writeall(std::ofstream & file)
 {
	 file << Fink << std::endl;
	 abstr_emp::writeall(file);
	 file << ReportsTo() << std::endl;
 }

 void highfink::writeall(std::ofstream & file)
 {
	 file << Highfink << std::endl;
	 abstr_emp::writeall(file);
	 file << ReportsTo() << std::endl;
	 file << InChargeOf() << std::endl;
 }
 //inne funkcje
 void abstr_emp::getall(std::ifstream & file)
 {
	 file >> fname;
	 file >> lname;
	 std::getline(file, job);
 }

 void employee::getall(std::ifstream & file)
 {
	 abstr_emp::getall(file);
 }

 void manager::getall(std::ifstream & file)
 {
	
	 abstr_emp::getall(file);
	 file >> inchargeof;
 }

 void fink::getall(std::ifstream & file)
 {
	 abstr_emp::getall(file);
	 getline(file, ReportsTo());
 }

 void highfink::getall(std::ifstream & file)
 {
	 abstr_emp::getall(file);
	 file >> InChargeOf();
	 getline(file, ReportsTo());
 }

 

1 odpowiedź

+1 głos
odpowiedź 27 września 2017 przez j23 Mędrzec (195,240 p.)
wybrane 27 września 2017 przez B0nkers
 
Najlepsza
while ((fin >> classtype).get(ch) && i < MAX) 
while ((fin >> classtype).ignore(numeric_limits<streamsize>::max(), '\n') && i < MAX) { ... } 

Tak będzie lepiej.

 

Operator >> dla stringa nie ściąga delimitera ze strumienia, zapewne to powoduje błąd. Użyj ignore po każdym >>, który jest przed wywołaniem np. getline.

komentarz 27 września 2017 przez B0nkers Początkujący (310 p.)
Dzięki pomogło. Jeszcze zapomniałem w kodzie dopisać żeby wyświetlało aktualne dane. No ale teraz jest już w porządku :)

Podobne pytania

0 głosów
0 odpowiedzi 910 wizyt
pytanie zadane 13 stycznia 2022 w C i C++ przez Nikso Nowicjusz (230 p.)
0 głosów
2 odpowiedzi 385 wizyt
pytanie zadane 25 sierpnia 2020 w C# przez Comparion Obywatel (1,810 p.)
0 głosów
0 odpowiedzi 188 wizyt

93,426 zapytań

142,421 odpowiedzi

322,647 komentarzy

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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...