Problem z plikiem binarnym i alokacja pamieci tablic w C

Witam

Pisze programik bazodanowy i mam dosc duzy problem.Nie wiem jak usuwac wybrane wpisy z pliku i jak wyszukiwac np po miejscowosci

Mam zainicjowana strukture

Aby zapisywac do pliku po wczytaniu danych uzywam funkcji

I teraz wczytuje plik kiedy utworzone sa juz wpisy

Moj probem polega na tym ze nie wiem jak usunac wpis np 5 (lub podany przez uzytkownika) i nie wiem jak szukac np po imieniu nazwisku czy miejscowosci bo kiedy probuje uzyc funkcji stricmp aby porownac tablice z podana przez uzytkownika miejscowoscia dostaje bledy o konwersji typu char :frowning:

Gdyby ktos mialby jakis pomysl jak to rozwiazac bede wdzieczny! !!

Kilka uwag.

char *imie[10];

To jest błędne (tego samego typu błąd popełniłeś kilka razy). Nie tworzysz tablicy 10-elementowej tylko wskaźnik do tablicy 10-elementowej.

calloc

Dlaczego calloc a nie malloc? I tak po chwili nadpisujesz zawartość, więc inicjalizowanie zerami nie ma sensu.

fread(A,sizeof(*A),n,baza);

Spacje nie bolą. Przy okazji - używaj prosze tagu CODE a nie QUOTE. Błędy konwersji wynikają z uwagi #1 - pokaszaniłeś typ zmiennej. Z tego typu plików przeważnie danych się… nie usuwa. Najpopularniejsza metodą obcługi własnego formatu z danymi o stałej wielkości jest dodanie do każdej struktury pola określającego, czy wpis jest aktywny. Usunięcie elementu to zmiana wartości tego pola. Przy czytaniu danych pomijasz nieaktywne struktury. Takie podejście wymaga też zaimplementowania defragmentacji pliku - przykładowo przy zakończeniu pracy z plikiem powinieneś wczytać jego zawartość (tylko aktywne bloki) i zapisać ponownie (nadpisać stary plik z blokami aktywnymi i nieaktywnymi). //edit Jeszcze to:

};Osoba ktos;

Możesz użyć konstrukcji:

struct Klasa {

...

} Zmienna;

Dzieki zaraz bede dokonywal poprawek.

Mam jeszcze jedno pytanko.Jak dobrze zapisac wczytana tablice z powrotem do pliku binarnego ?

Osoba *A;

fwrite(A,sizeof(*A),n,baza);

Czy ten zapisa jest wogole dobry ?? Czy powininenem go zmienic ?

Zależy od tego jakie pola ma Osoba. Przykładowy kod:

#include 

#include 


struct Person1 {

	int iHeight;

	char *wszName;

} _Person1;


struct Person2 {

	int iHeight;

	char wszName[20];

} _Person2;


void main(void)

{

	printf("sizeof(Person1) = %d\n", sizeof(Person1));

	printf("sizeof(_Person1) = %d\n", sizeof(_Person1));

	printf("sizeof(_Person1.wszName) = %d\n", sizeof(_Person1.wszName));

	printf("sizeof(*(_Person1.wszName)) = %d\n", sizeof(*(_Person1.wszName)));


	printf("sizeof(Person2) = %d\n", sizeof(Person2));

	printf("sizeof(_Person2) = %d\n", sizeof(_Person2));

	printf("sizeof(_Person2.wszName) = %d\n", sizeof(_Person2.wszName));

	printf("sizeof(*(_Person2.wszName)) = %d\n", sizeof(*(_Person2.wszName)));



	Person1 *p1_1 = new Person1;

	Person1 *p1_2 = (Person1 *)malloc(sizeof(Person1));


	Person2 *p2_1 = new Person2;

	Person2 *p2_2 = (Person2 *)malloc(sizeof(Person2));



	free(p2_2);

	delete p2_1;


	free(p1_2);

	delete p1_1;

}

Wynik działania:

sizeof(Person1) = 8

sizeof(_Person1) = 8

sizeof(_Person1.wszName) = 4

sizeof(*(_Person1.wszName)) = 1

sizeof(Person2) = 24

sizeof(_Person2) = 24

sizeof(_Person2.wszName) = 20

sizeof(*(_Person2.wszName)) = 1

Jak widzisz istnieje zasadnicza różnica między wskaźnikiem a tablicą. Wskaźnik wymaga od Ciebie zaalokowania pamięci a pamięć zaalokowana zostanie na stercie. Struktura Person1 wygląda zatem w pamięci tak:

...........IIIIPPPP........

Gdzie:

..... jakaś pamięć

IIII pamięć przechowująca wzrost (int)

PPPP wskaźnik do adresu pod którym przechowany będzie ciąg znaków (char*)

Wskaźnik na maszynie 32bitowej ma 4 bajty, podobnie jak zmienna typu int. Przykładowo Person1 może wyglądać w pamięci tak:

Adres wartość

00 ?

01 ?

02 ?

03 ?

04 00 --

05 00 // integer o

06 00 // wartości 180

07 B4 --

08 00 --

0a 00 // wskaźnik kierujący

0b 00 // pod adres 00000010h

0c 10 --

0d ?

0e ?

0f ?

10 4a // 'J'

11 61 // 'a'

12 6e // 'n'

13 00 // '\0'

14 ?

15 ?

Jeśli zaalokowałeś 4 bajty na tekst (3 znaki + znak końca ciągu) to właśnie tak może Twoja pamięć wyglądać. Zwróć uwagę, że rozmiar struktury to 8 bajtów i jeśli zapiszesz strukturę na dysk to znajdzie się w niej nie imię, a wskaźnik. Po odczytaniu będziesz miał wskaźnik kierujący Bóg wie gdzie. Mówiąc prościej - aplikacja z pewnością nie będzie działała poprawnie. Przykładowo Person2 może wyglądać w pamięci tak:

Adres wartość

00 ?

01 ?

02 ?

03 ?

04 00 --

05 00 // integer o

06 00 // wartości 180

07 B4 --

08 4a // 'J'

09 61 // 'a'

0a 6e // 'n'

0b 00 // '\0'

0c 00

0d 00

0e 00

0f 00

10 00

...

19 00

1a 00

1b 00

1c ?

1d ?

W tym wypadku zapisując strukturę do pliku zapiszesz 24 bajty.

Więc czy fwrite, który pokazałeś jest dobry? Zależy. :wink:

Jeszcze raz dzieki za wskazowki.Bo jestem samoukiem wiec nie bylem po zadnym kursie i tak dalej.Wiec Twoje wskazowki beda bardzo cenne. A raczej sa :smiley:

Pozdr :mrgreen: