Dynamiczna alokacja struktur
Część sekcji Logika i sterowanie przepływem ścieżki C w Coddy. Lekcja 48 z 63.
Do tej pory nauczyłeś się tworzyć struktury na stosie — istnieją one w zakresie, w którym zostały zadeklarowane, i są automatycznie usuwane, gdy ten zakres się kończy. Ale co, jeśli potrzebujesz, aby struktura istniała także po zakończeniu pierwotnego zakresu albo nie wiesz w czasie kompilacji, ile struktur będzie potrzebnych?
Właśnie tutaj przydaje się alokacja dynamiczna. Możesz użyć malloc(), aby tworzyć struktury na stercie, tak jak w przypadku każdego innego typu danych. Kluczowa różnica polega na tym, że struktury zaalokowane dynamicznie pozostają w pamięci, dopóki jawnie ich nie zwolnisz za pomocą free().
Oto składnia dynamicznego przydzielania pamięci dla struktury:
struct Point *ptr = malloc(sizeof(struct Point));Przydziela to wystarczająco dużo pamięci na stercie, aby pomieścić jedną strukturę Point, i zwraca wskaźnik do tej pamięci. Następnie możesz użyć operatora strzałki, aby uzyskać dostęp do składowych struktury i je modyfikować:
ptr->x = 10;
ptr->y = 20;Pamiętaj, aby zawsze sprawdzać, czy malloc() zakończyło się powodzeniem (zwróciło wartość inną niż NULL), i wywołać free(ptr), gdy skończysz korzystać ze struktury, aby zapobiec wyciekom pamięci. Ta technika jest niezbędna do tworzenia elastycznych programów, które mogą tworzyć struktury danych i zarządzać nimi w czasie wykonywania.
Wyzwanie
ŁatwyUtwórz program w C, który demonstruje dynamiczną alokację struktur za pomocą malloc(). Twój program powinien:
- Zdefiniować
structo nazwieCarz następującymi składowymi:- Liczbę całkowitą
yeardo przechowywania roku produkcji - Tablicę znaków
brando rozmiarze 20 do przechowywania marki samochodu - Tablicę znaków
modelo rozmiarze 25 do przechowywania modelu samochodu - Liczbę zmiennoprzecinkową
pricedo przechowywania ceny samochodu - Liczbę całkowitą
mileagedo przechowywania przebiegu samochodu
- Liczbę całkowitą
- W funkcji main zadeklarować wskaźnik do struktury
Caro nazwiecarPtr - Użyć
malloc(), aby dynamicznie zaalokować pamięć dla jednej strukturyCari przypisać zwrócony adres docarPtr - Sprawdzić, czy alokacja pamięci się powiodła:
- Jeśli
carPtrma wartośćNULL, wypisaćMemory allocation failedi zakończyć program - Jeśli alokacja się powiodła, wypisać
Memory allocation successful
- Jeśli
- Odczytać następujące wartości wejściowe i przypisać je do składowych struktury za pomocą operatora strzałkowego:
- Odczytać liczbę całkowitą oznaczającą rok i przypisać ją za pomocą
carPtr->year - Odczytać ciąg znaków oznaczający markę i przypisać go za pomocą
carPtr->brand - Odczytać ciąg znaków oznaczający model i przypisać go za pomocą
carPtr->model - Odczytać liczbę zmiennoprzecinkową oznaczającą cenę i przypisać ją za pomocą
carPtr->price - Odczytać liczbę całkowitą oznaczającą przebieg i przypisać ją za pomocą
carPtr->mileage
- Odczytać liczbę całkowitą oznaczającą rok i przypisać ją za pomocą
- Po odczytaniu wszystkich wartości wykonać następujące obliczenia za pomocą operatora strzałkowego:
- Obliczyć wiek samochodu, odejmując rok od 2024:
int age = 2024 - carPtr->year; - Obliczyć stopę amortyzacji na podstawie wieku: jeśli wiek jest większy niż 10, ustawić depreciation na 0.6, w przeciwnym razie ustawić ją na 0.8
- Obliczyć bieżącą wartość:
carPtr->price * depreciation
- Obliczyć wiek samochodu, odejmując rok od 2024:
- Wypisać informacje o samochodzie za pomocą operatora strzałkowego, dokładnie w tym formacie:
Car Information:Year: [year]Brand: [brand]Model: [model]Original Price: [price]Mileage: [mileage]Age: [age] yearsCurrent Value: [current_value]
- Zwolnić dynamicznie zaalokowaną pamięć za pomocą
free(carPtr) - Wypisać
Memory freed successfully
To wyzwanie sprawdza Twoje rozumienie dynamicznej alokacji struktur za pomocą malloc(), sprawdzania, czy alokacja się nie powiodła, dostępu do składowych struktury przez wskaźniki za pomocą operatora strzałkowego oraz prawidłowego zwalniania zaalokowanej pamięci za pomocą free(). Przećwiczysz pełny cykl zarządzania pamięcią dynamiczną w przypadku struktur.
Spróbuj swoich sił
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TODO: Zdefiniuj tutaj strukturę Car
int main() {
// TODO: Zadeklaruj wskaźnik do struktury Car o nazwie carPtr
// TODO: Użyj malloc(), aby przydzielić pamięć dla jednej struktury Car
// TODO: Sprawdź, czy przydzielenie pamięci się powiodło
// Odczytaj wartości wejściowe
int year, mileage;
char brand[20], model[25];
float price;
scanf("%d", &year);
scanf("%s", brand);
scanf("%s", model);
scanf("%f", &price);
scanf("%d", &mileage);
// TODO: Przypisz wartości wejściowe do pól struktury za pomocą operatora strzałki
// TODO: Oblicz wiek, amortyzację i bieżącą wartość
// TODO: Wypisz informacje o samochodzie w wymaganym formacie
// TODO: Zwolnij przydzieloną pamięć i wypisz komunikat o powodzeniu
return 0;
}Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Logika i sterowanie przepływem
1Podstawy wskaźników
Czym jest wskaźnik?Deklarowanie wskaźnikówOperator pobrania adresu (&)Operator dereferencji (*)Wskaźniki NULLPodsumowanie: podstawy wskaźników4Projekt: Proste narzędzie tekstowe
Przegląd projektuLiczenie znaków2Wskaźniki i tablice
Nazwy tablic jako wskaźnikiElementy tablic — wskaźnikiArytmetyka wskaźnikówPorównywanie wskaźnikówPodsumowanie: przechodzenie po tablicy za pomocą wskaźników5Wskaźniki i funkcje
Przekazywanie przez wartośćPrzekazywanie wskaźników do funkcjiModyfikowanie zmiennych za pomocą wskaźnikówKlasyczny przykład: zamianaPrzekazywanie tablic do funkcjiPowtórka: argumenty wskaźnikowe funkcji8Struktury i wskaźniki
Wskaźniki do strukturOperator strzałki (->)Przekazywanie struktur przez wartośćPrzekazywanie wskaźników do strukturDynamiczna alokacja strukturPodsumowanie: modyfikowanie struktury — wskaźnik11Końcowe zadania powtórkowe
Powtórka: dynamiczne łączenie ciągów znakówPowtórka: tablica strukturPowtórka: licznik częstotliwości słów3Tablice znaków i ciągi znaków
Ciągi znaków jako tablice charZnak końca ciąguWczytywanie ciągu za pomocą scanfUżywanie strlen()Używanie strcpy()Używanie strcat()Używanie strcmp()Podsumowanie: podstawowe funkcje do obsługi ciągów znakówPoćwicz samodzielnie: Kompilator C online