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

Odczyt obiektów z pliku

Object Storage Arubacloud
0 głosów
359 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 (194,920 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 521 wizyt
pytanie zadane 13 stycznia 2022 w C i C++ przez Nikso Nowicjusz (230 p.)
0 głosów
2 odpowiedzi 280 wizyt
pytanie zadane 25 sierpnia 2020 w C# przez Comparion Obywatel (1,810 p.)
0 głosów
0 odpowiedzi 120 wizyt

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 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!

...