Wskaźniki, struktury i funkcje - problem

0

Witam,
mam napisać prostą książkę telefoniczną, opartą o strukturę:

struct wpis {
	char *imie;
	char *nazwisko;
	char *telefon;
};

Na początek robię sobie tablicę 10-cio elementową oraz definiuję zmienną, która będzie mówiła ile elementów jest w książce:

struct wpis rekordy[10];
int ile_elementow = 3;

Dałem 3, bo mam już kilka rekordów w tablicy.

Następnie chce dodać nowy element do tablicy za pomocą funkcji:

void dodajWpis(struct wpis* rekordy, int* ile_elementow){
	char *imie = (char*)malloc(100 * sizeof(char));
	char *nazwisko = (char*)malloc(100 * sizeof(char));
	char *telefon  = (char*)malloc(10 * sizeof(char));
	
	printf("Podaj imie:\n");
	scanf("%s", imie);
	printf("\nNazwisko:\n");
	scanf("%s", nazwisko);
	printf("\nTelefon:\n");
	scanf("%s", telefon);
	
	*ile_elementow += 1;
	
	rekordy[*ile_elementow].imie = imie;
	rekordy[*ile_elementow].nazwisko = nazwisko;
	rekordy[*ile_elementow].telefon = telefon;
	
	free(imie);
	free(nazwisko);
	free(telefon);
	
}

W main'ie wywołuję ją tak:

dodajWpis(&rekordy[0], &ile_elementow);

Po dodaniu nowego wpisu, chcę wyświetlić cały spis i w miejscu, gdzie powinien pojawić się nowy wpis pojawia się:

�@
Naruszenie ochrony pamięci

Jak to naprawić?

1

Problemem jest to, że alokujesz pamięć, wrzucasz tam te napisy, a potem od razu ją zwalniasz - przecież to jest bez sensu.
Dodatkowo najpierw poprzypisuj te wskaźniki, a dopiero potem zwiększ licznik rekordów - elementy w tablicach indeksujemy od 0.
Po co przekazujesz w tak dziwny sposób tą tablicę? Wystarczy dodajWpis(rekordy, &ile_elementów);

0

Wielkie dzięki :)

Niestety znów pojawił się problem. Mam taki kod zczytujący z pliku:

char *zawartosc_pliku = (char*)malloc(100 * sizeof(char));
int wiersz = 1;
int obieg = 0;

*ile_elementow = 0;

while (fscanf(fp, "%s", zawartosc_pliku) != EOF) {
	printf("%s\n", zawartosc_pliku);
	if ((wiersz - obieg*4) == 2) {
		rekordy[*ile_elementow].imie = zawartosc_pliku;
	} else if ((wiersz - obieg*4) == 3) { 
		rekordy[*ile_elementow].nazwisko = zawartosc_pliku;
	} else if ((wiersz - obieg*4) == 4) {
		rekordy[*ile_elementow].telefon = zawartosc_pliku;
		obieg++;
		*ile_elementow += 1;
	}
	wiersz++;
}

Plik wygląda tak:

-Rekord#0
imie
nazwisko
telefon

Funkcja printf() wypisuje mi wszystkie elementy jak należy, ale funkcja wypisująca:

for(int q=0; q<ile_elementow; q++){
	printf("%s\n", rekordy[q].imie);
	printf("%s\n", rekordy[q].nazwisko);
	printf("%s\n\n", rekordy[q].telefon);
}

Wypisuje mi ostatnią wartość jaka została przypisana - "telefon".
Dlaczego?

0

Pola imie, nazwisko, telefon to wskazniki do char i przypisujesz jedynie wskaznik a nie przepisujesz zawartosci pamieci.
Musisz zaalokowac pamiec dla każdego z tych pól z osobna tak jak to robisz w funkcji dodajWpis.

Poza tym jeśli znasz kolejność danych w pliku to nie ma sensu bawić się na ifach.

0

Nie rozumiem... Masz na myśli takie coś?

while (fscanf(fp, "%s", zawartosc_pliku) != EOF) {
	printf("%s\n", zawartosc_pliku);
	if ((wiersz - obieg*4) == 2) {
		rekordy[*ile_elementow].imie = (char*)malloc(100 * sizeof(char));
		rekordy[*ile_elementow].imie = zawartosc_pliku;
	} else if ((wiersz - obieg*4) == 3) { 
		rekordy[*ile_elementow].nazwisko = (char*)malloc(100 * sizeof(char));
		rekordy[*ile_elementow].nazwisko = zawartosc_pliku;
	} else if ((wiersz - obieg*4) == 4) {
		rekordy[*ile_elementow].telefon = (char*)malloc(10 * sizeof(char));
		rekordy[*ile_elementow].telefon = zawartosc_pliku;
		obieg++;
		*ile_elementow += 1;
	}
	wiersz++;
}
0
 
while (fscanf(fp, "%s", zawartosc_pliku) != EOF) {
	printf("%s\n", zawartosc_pliku);
	if ((wiersz - obieg*4) == 2) { 
		rekordy[*ile_elementow].imie = zawartosc_pliku;
	} else if ((wiersz - obieg*4) == 3) { 
			rekordy[*ile_elementow].nazwisko = zawartosc_pliku;
	} else if ((wiersz - obieg*4) == 4) {		
			rekordy[*ile_elementow].telefon = zawartosc_pliku;
			obieg++;
			*ile_elementow += 1;
	}
	zawartosc_pliku = (char*)malloc(100 * sizeof(char));
	wiersz++;
}

// albo w ten sposob JEŚLI masz pewność że zawsze będą podane wszystkie dane
// tj. rekord#numer, imie, nazwisko, telefon
while (fscanf(fp, "%s", zawartosc_pliku) != EOF) {
	// teraz masz wczytany "rekord#numer"
	fscanf(fp, "%s", zawartosc_pliku);			// wczytujesz imie
	rekordy[*ile_elementow].imie = zawartosc_pliku;		// podpinasz wskaznik
	
	zawartosc_pliku = (char*)malloc(100 * sizeof(char));	// alokujesz pamiec dla nazwiska
	fscanf(fp, "%s", zawartosc_pliku);			// wczytujesz nazwisko
	rekordy[*ile_elementow].nazwisko = zawartosc_pliku;	// podpinasz wskaznik
	
	zawartosc_pliku = (char*)malloc(100 * sizeof(char));	// alokujesz pamiec dla telefonu
	fscanf(fp, "%s", zawartosc_pliku);			// wczytujesz telefon
	rekordy[*ile_elementow].telefon = zawartosc_pliku;	// podpinasz wskaznik
	
	zawartosc_pliku = (char*)malloc(100 * sizeof(char));	// alokujesz pamiec dla imienia
	*ile_elementow++;
}
free(zawartosc_pliku); // zwalniasz pamiec z ostatniej alokacji - nie zostala wykorzystana

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