Lista jednokierunkowa i operacje na plikach

0

Witam. Mam zadanie aby zaimplementować uogólnioną listę jednokierunkową i zaimplementować funkcje: zapisywania listy do pliku binarnego oraz wczytywania listy z pliku binarnego. Zapisywanie do pliku zrobiłem chociaż nie wiem czy 100% dobrze ale nie mogę znaleźć sposobu na wczytywanie z pliku.
Mój kod:
Plik .h

#include "Main.h"

#ifndef Lista
#define Lista

#include<string>
#include<stdio.h>

template<class Type>
struct List{
	List<Type> * next;
	Type data;
};

struct Student{
	string imie;
	string nazwisko;
	int nr_indeksu;

	Student() {};
	Student(string imie, string nazwisko, int nr_indeksu);
};

ostream& operator<< (ostream& stream, Student& other);

template<class Type>
void add_to_list(List<Type> *&first, List<Type> *&last, Type nowy){
	List<Type> * temp = new List<Type>;
	temp->data = nowy;
	temp->next = NULL;

	if(first == NULL){
		first = temp;
		last = first;
	}
	else{
		last->next = temp;
		last = last->next;
	}
}

template<class Type>
void delete_from_list(List<Type> *&first, List<Type> *&last, int szukany_indeks){
	List<Type> * temp = first;
	List<Type> * temp1 = NULL;


	if(temp == NULL)
		cout<< "\nLista jest pusta!";
	else{
		while(temp && temp->data.nr_indeksu != szukany_indeks){
			temp1 = temp;
			temp = temp->next;
		}
		if(temp == NULL){
			return;
		}
		else if(temp == first){
			first = first->next;
			delete temp;
		}
		else{
			temp1->next = temp->next;
			delete temp;
		}
	}
}

template<class Type>
void print_list(List<Type> *temp){
	if(temp == NULL)
		cout<< "\nLista jest pusta!";
	else{
		int i = 0;
		while(temp){
			cout<< endl << endl << ++i << ". Pozycja." << temp->data;
			temp = temp->next;
		}
	}
}

template<class Type>
void search_student(List<Type> *first, int szukany_indeks){
	if(first == NULL)
		cout<< "\nLista jest pusta!";
	else{
		int i = 1;
		while(first && first->data.nr_indeksu != szukany_indeks){
			first = first->next;
			i++;
		}
		cout<< "\nSzukany student znajduje sie na pozycji: " << i;
		cout<< first->data;
	}
}

template<class Type>
void save_to_file(List<Type> *first)
{
	ofstream plik;

	if (first == NULL)
		cout << "Nie ma elementow do zapisania " << endl;
	else
	{
		plik.open("plik.bin");
			List<Type> * temp = first;

			while (temp)
			{
				plik.write((char*)&temp->data.imie, sizeof(string));
				plik.write((char*)&temp->data.nazwisko, sizeof(string));
				plik.write((char*)temp->data.nr_indeksu, sizeof(int));
				temp = temp->next;
			}
			cout << "Lista zostala zapisana" << endl;
		}
		plik.close();
	}

#endif

oraz kod pliku źródłowego:

#include "Main.h"
#include "Lista.h"

Student::Student(string imie, string nazwisko, int nr_indeksu){
	this->imie = imie;
	this->nazwisko = nazwisko;
	this->nr_indeksu = nr_indeksu;
}

ostream& operator<< (ostream& stream, Student& other){
	return stream<< "\nImie: " << other.imie << "\nNazwisko: " << other.nazwisko << "\nNr indeksu: " << other.nr_indeksu;
}

void Zadanie3()
{
	cout<< endl << setw(45) << "Zadanie 3";
	char i;

	List<Student> *first = NULL, *last = NULL;

        ............

Może ktoś coś doradzić? Bo nie mam pomysłu na to.

1

Zaimplementowałeś uogólnioną listę a nie potrafisz odczytać pliku?

0

No właśnie w trybie binarnym coś nie mogę. W tekstowym idzie normalnie ale tutaj jakiś błędy z alokacją pamięci wyskakują ale nie wiem gdzie dokładnie jest błąd.

fstream plik;
plik.open("Lista.bin", ios::binary | ios::in);
if(!plik.good())
	cout<< "\nBLAD OTWARCIA PLIKU";
else{
	string imie, nazwisko;
	int nr_indeksu;

	while(!plik.eof()){
		plik.read((char*)&imie, sizeof(string));
		plik.read((char*)&nazwisko, sizeof(string));
		plik.read((char*)&nr_indeksu, sizeof(int));
		add_to_list(first, last, Student(imie, nazwisko, nr_indeksu));
	}
}
plik.close();
0

A nie trzeba przypadkiem rzutować bufora na typ int ?
Odczyt i zapis plików binarnych w Cpp

0

Nic nie trzeba rzutowac. Swoja droga to plik tekstowy tez jest binarny

0
OverMorda napisał(a):
fstream plik;
plik.open("Lista.bin", ios::binary | ios::in);
if(!plik.good())
	cout<< "\nBLAD OTWARCIA PLIKU";
else{
	string imie, nazwisko;
	int nr_indeksu;

	while(!plik.eof()){
		plik.read((char*)&imie, sizeof(string));
		plik.read((char*)&nazwisko, sizeof(string));
		plik.read((char*)&nr_indeksu, sizeof(int));
		add_to_list(first, last, Student(imie, nazwisko, nr_indeksu));
	}
}
plik.close();

sizeof(std::string) zwróci stałą liczbę, zwróci albo 4 albo 8 - nie pamiętam dokładnie ale raczej to pierwsze. plik.read musisz wywołać wiedząc dokładnie ile bajtów chcesz pobrać. Nie potrafię napisać co zrobi kompilator widząc rzutowanie adresu na wskaźnik. Na początek pobierz sobie cały plik do bufora typu char[] a potem go przeparsuj. Jak to Ci zadziała to wtedy pomyśl jak to zoptymalizować. Rozmiar pliku pobierasz np tak (pisane z palca):

plik.seekg(0, ios::end); //zamiast ios::end moze byc chyba plik.end
int length = plik.tellg();
plik.seekg(0,ios::beg); //zamias ios::beg moze byc chyba plik.beg

i używając zmiennej legth inicjalizujesz bufor.

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