Klasa do operacji na plikach binarnych języka C.

0

Witam,
stawiam pierwsze kroki w programowaniu, na ogół radziłem sobie sam, jednak w tym przypadku mam problem na tyle dla mnie upierdliwy, że postanowiłem się zwrócić o pomoc. Otóż mam za zadanie stworzyć klasę do zarządzania plikami binarnymi w języku C, używając do tego funkcji fopen, fclose, fwrite, fread etc. Klasa ma posiadać podstawowe konstruktory do otwierania pliku o podanej nazwie (tryb "a+b"), destruktor, który zamyka plik, konstruktor i operator do kopiowania. Do tego metody do zapisu i odczytu danych oraz licznik otwartych plików zwracany w metodzie.

To co mam do tej pory ( bardziej zlepek tego, co udało mi się znaleźć w internecie, niż to co napisałem sam) :

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

class plik
{
private:
	FILE *file;
	char *name;
protected:
	static int counter;
public:
	plik()
	{
		name = "dane.txt";
		file = fopen(name, "a+b");
		if (file == NULL)
		{
			printf("Blad");
		}
		else
		{
			printf("Ok");
			counter++;
		}
	}
	plik(const char *nazwa)
	{
		file = fopen(nazwa, "a+b");
		if (file == NULL)
			if (file == NULL)
			{
			printf("Blad");
			}
			else
			{
				printf("Ok");
				counter++;
			}
	}
	plik(const char &nazwa);
        void operator=(const plik &nazwa);

	~plik()
	{
		fclose(file);
		counter--;
	}
	void Zapisz(const char *teksDoZapisu)
	{
		size_t zapisanychElementow = fwrite(teksDoZapisu, sizeof(char), strlen(teksDoZapisu), file);
		printf("Dlugosc tekstu = %d\n", strlen(teksDoZapisu));
		printf("Zapisanych elementow = %d\n", zapisanychElementow);
	}
	void Odczytaj()
	{
		const int ROZMIAR_BUFORA = 1024;
		char bufor[ROZMIAR_BUFORA];
		size_t odczytanychElementow = fread(bufor, sizeof(char), ROZMIAR_BUFORA, file);
		printf("Odczytanych elementow = %d\n", odczytanychElementow);
	}
	static int LiczbaOtwartych()
	{
		return counter;
	}
};

int plik::counter = 0;

int main()
{
	plik plik("aaa.txt");
	plik.Zapisz("asasaas");
	plik.Odczytaj();
	printf("%d\n", plik.LiczbaOtwartych());
} 

Konstruktor domniemany nie działa tak jak powinien ( albo nie działa wcale :( ), to samo licznik, nie mam też za bardzo pomysłu na konstruktor i operator do kopiowania. Póki co, dla przyjemniejszego testowania, badałem działanie programu na plikach tekstowych. Prosiłbym o jakieś porady.

Pozdrawiam.

1

Nie rozumiem: Po co probujesz zaimplementowac istniejaca klase fstream?

Najpierw zastanow sie co w ogole probujesz zrobic i napisz, patrzac na kod nie jest to oczywiste.

Jakby ne bylo to tak:

  • napisz program ktory robi to co chcesz bez uzycia klas
  • zapisz sobie na kartce co chcesz zeby Twoja klasa robila i jaka funkcjonalnosc powinna byc zamknieta w oddzielna czesc z logika.

Poki co patrzac na Twoj design klasy nie mam pojecia jak jej uzywac. Co niby mialby robic operator=? Albo co robi funkcja Zapisz, ktora bierze stringa na pliku ktory jest juz otwarty. Zupelnie bez sensu. Tak samo wypisywanie czegokolwiek na ekran w klasie obslugujacej plik jest bez sensu.

2

Pierwszy raz widzę kod "C z klasami" który zasługuje w 100% na tę nazwę.

  1. co oznacza "Konstruktor domniemany nie działa tak jak powinien". Takie opisy dają użytkownicy, nie programiści.

  2. "nie mam też za bardzo pomysłu na konstruktor". Szukasz pomysłów? Ale jakie są wymagania?

  3. wywal "void operator=(const plik &nazwa);"

  4. zmień interfejs "Odczytaj". Aktualnie na zewnątrz nic nie robi (nic nie zwraca).

  5. licznik raczej działa, tylko nie wiesz jak. W ostatniej linii kodu powinien być = 1.

1

zapisujesz cstring bez kończonego zera, potem to wczytujesz (zera nie ma) i drukujesz zawartość (brak zera końcowego powoduje, że drukują ci się śmieci).
Na dodatek próbujesz czytać z końca pliku! Najpierw powinieneś przewinąć plik na początek.

0
krwq napisał(a):

Nie rozumiem: Po co probujesz zaimplementowac istniejaca klase fstream?

Najpierw zastanow sie co w ogole probujesz zrobic i napisz, patrzac na kod nie jest to oczywiste.

Jakby ne bylo to tak:

  • napisz program ktory robi to co chcesz bez uzycia klas
  • zapisz sobie na kartce co chcesz zeby Twoja klasa robila i jaka funkcjonalnosc powinna byc zamknieta w oddzielna czesc z logika.

Poki co patrzac na Twoj design klasy nie mam pojecia jak jej uzywac. Co niby mialby robic operator=? Albo co robi funkcja Zapisz, ktora bierze stringa na pliku ktory jest juz otwarty. Zupelnie bez sensu. Tak samo wypisywanie czegokolwiek na ekran w klasie obslugujacej plik jest bez sensu.

Ogólnie, tak jak już wcześniej wspomniałem, docelowo klasa ma obsługiwać pliki binarne. Myślałem, że nie robi to większej różnicy i póki co
operowałem na plikach tekstowych, żeby łatwiej było sprawdzić czy kod działa tak jak chce. Z tego samego powodu klasa wypisuje cokolwiek na ekran - w celach testowych.

plik(const char &nazwa);
void operator=(const plik &nazwa);

To deklaracje konstruktora kopiującego i operatora do kopiowania, nie wiem jak je zdefiniować. Ich zadaniem jest po prostu kopiowanie pliku.

Zarys klasy jest taki:

  • konstruktory mają otwierać plik binarny o podanej nazwie
  • destruktor ma zamykać plik binarny
  • konstruktor kopiujący i operator do kopiowania mają kopiować plik binarny
  • metoda Czytaj ma odczytywać zawartość pliku binarnego
  • metoda Zapisz ma zapisywać dane do bliku binarnego
  • metoda LiczbaOtwartych ma zwracać ilość otwartych plików binarnych
vpiotr napisał(a):

Pierwszy raz widzę kod "C z klasami" który zasługuje w 100% na tę nazwę.

  1. co oznacza "Konstruktor domniemany nie działa tak jak powinien". Takie opisy dają użytkownicy, nie programiści.

  2. "nie mam też za bardzo pomysłu na konstruktor". Szukasz pomysłów? Ale jakie są wymagania?

  3. wywal "void operator=(const plik &nazwa);"

  4. zmień interfejs "Odczytaj". Aktualnie na zewnątrz nic nie robi (nic nie zwraca).

  5. licznik raczej działa, tylko nie wiesz jak. W ostatniej linii kodu powinien być = 1.

  1. wydaje mi się, że to co napisałem powinno w momencie utworzenia obiektu (
plik plik();

) przez konstruktor domyślny utworzyć i otworzyć plik tekstowy o nazwie "dane.txt" do odczytu i zapisu, a póki co jest tak, że nie dzieje się nic i nie wiem dlaczego
2),3) jak już pisałem nie wiem jak zaimplementować konstruktor kopiujący i operator do kopiowania, wymagania są takie, że mają one po prostu kopiować plik
4) chodzi o to, że nie wiem jak mam go zmienić
5) nie rozumiem, docelowo licznik ma zwracać liczbę otwartych plików, przez metodą LiczbaOtwartych, nie jestem też pewien czy metoda ta ma być w klasie, bo z tego co rozumiem, to żeby ją wywołać to muszę się posłużyć konkretnym obiektem, a taki obiekt w momencie tworzenia otwiera plik, ale jak zrobię ich kilka, to wywołując metodą na którymś z nich zwróci mi wartość wszystkich otwartych plików?
Czyli np. w przypadku:

 plik plik(); 
	plik plik2("aaa.txt");
	printf("%d", plik.LiczbaOtwartych());

powinny zostać utworzone dwa pliki, jeden domyślny, drugi o nazwie "aaa" i w momencie użycia metody LiczbaOtwartych powinna zwrócić wartość 2

Btw. na chwilę obecną to bliżej mi do użytkownika, niż do programisty... :/ można powiedzieć, że dopiero zaczynam się uczyć.

1

plik plik(); - zmienna plik bedzie funkcja ktora zwraca plik, a nie typu plik. To co chcesz zrobic to plik plik; albo plik* plik = new plik();

0
krwq napisał(a):

plik plik(); - zmienna plik bedzie funkcja ktora zwraca plik, a nie typu plik. To co chcesz zrobic to plik plik; albo plik* plik = new plik();

:D Dziękuję...

Fajnie panowie, dzięki za wskazówki, mam trochę mało czasu ostatnio, ale coś takiego sklepałem póki co:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

class plik
{
private:
	FILE *file;
	char *name;
protected:
	static int counter;
public:
	plik()
	{
		name = "dane.bin";
		file = fopen(name, "a+b");
		if (file == NULL)
		{
			perror(name);
			exit(EXIT_FAILURE);
		}
		++counter;
	}
	plik(const char *nazwa)
	{
		file = fopen(nazwa, "a+b");
		if (file == NULL)
			if (file == NULL)
			{
			perror(name);
			exit(EXIT_FAILURE);
			}
			++counter;			
	}
	plik(const char &nazwa);
	void operator=(const FILE *kopia);
	~plik()
	{
		fclose(file);
		--counter;
	}
	void Zapisz(const char *teksDoZapisu)
	{
		rewind(file);
		size_t zapisanychElementow = fwrite(teksDoZapisu, sizeof(char), strlen(teksDoZapisu)+2, file);	
		fwrite("\0", sizeof(char), 2, file);
		printf("Dlugosc tekstu = %d\n", strlen(teksDoZapisu));
		printf("Zapisanych elementow = %d\n", zapisanychElementow);
	}
	void Odczytaj()
	{
		rewind(file);
		const int ROZMIAR_BUFORA = 1024;
		char bufor[ROZMIAR_BUFORA];
		size_t odczytanychElementow = fread(bufor, sizeof(char), ROZMIAR_BUFORA, file);
		printf("Odczytanych elementow = %d\n", odczytanychElementow);
		printf("Odczytane dane: %s\n", bufor);
	}
	static void LiczbaOtwartych()
	{
		printf("Liczba otwartych plikow: %d\n", counter);
	}
};
int plik::counter = 0;
int main()
{
	plik plik1("Dane1.bin");
	plik plik2("Dane2.bin");
	plik1.Zapisz("Przykladowy tekst");
	plik1.Odczytaj();
	plik::LiczbaOtwartych();
} 

W miarę działa tak jak wydaje mi się, że powinno działać. Miło by było jakby ktoś jeszcze na to rzucił okiem. No i brakuję mi konstruktora kopiującego i operatora do kopiowania plików, za co kompletnie już nie wiem jak się zabrać. Jakieś rady? :)

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