Przekazywanie wskaźników do struktur
Część sekcji Logika i sterowanie przepływem ścieżki C w Coddy. Lekcja 47 z 63.
Przekazywanie struktur przez wartość sprawdza się przy odczytywaniu danych, ale w przypadku dużych struktur staje się nieefektywne, ponieważ kopiowana jest cała struktura. Co ważniejsze, nie możesz modyfikować oryginalnej struktury z poziomu funkcji. Właśnie dlatego niezbędne staje się przekazywanie .
Gdy przekazujesz wskaźnik do struktury zamiast samej struktury, funkcja otrzymuje adres pamięci oryginalnej struktury. To podejście ma dwie kluczowe zalety: jest wydajniejsze (nie wymaga kopiowania) i pozwala funkcji modyfikować oryginalne dane.
Składnia funkcji, która przyjmuje wskaźnik do struktury, wygląda następująco:
void functionName(struct StructureName *ptr) {
// Treść funkcji korzystająca z ptr->member
}Wewnątrz funkcji używasz operatora strzałki, aby uzyskać dostęp do składowych struktury i je modyfikować. Wszelkie zmiany wprowadzone za pośrednictwem wskaźnika bezpośrednio wpłyną na oryginalną strukturę w funkcji wywołującej, co sprawia, że to podejście idealnie nadaje się do funkcji, które muszą aktualizować lub przekształcać dane struktury.
Ta technika ma fundamentalne znaczenie przy tworzeniu wydajnych programów w C, które pracują ze złożonymi strukturami danych, ponieważ łączy możliwości wskaźników z uporządkowaniem struktur.
Wyzwanie
ŁatwyUtwórz program w C, który demonstruje przekazywanie wskaźników do struktur do funkcji w celu efektywnej modyfikacji danych. Twój program powinien:
- Zdefiniować strukturę
structo nazwieBankAccountz następującymi składowymi:- Liczbę całkowitą
accountNumberdo przechowywania numeru konta - Tablicę znaków
ownerNameo rozmiarze 30 do przechowywania imienia i nazwiska właściciela konta - Liczbę zmiennoprzecinkową
balancedo przechowywania salda konta - Liczbę całkowitą
transactionCountdo przechowywania liczby transakcji
- Liczbę całkowitą
- Napisać funkcję o nazwie
depositMoney, która:- Przyjmuje jako parametry wskaźnik do struktury
BankAccountoraz kwotę typu float - Dodaje kwotę do salda konta, używając operatora strzałki
- Zwiększa liczbę transakcji o 1
- Wyświetla
Deposit successful. New balance: [balance]
- Przyjmuje jako parametry wskaźnik do struktury
- Napisać funkcję o nazwie
withdrawMoney, która:- Przyjmuje jako parametry wskaźnik do struktury
BankAccountoraz kwotę typu float - Sprawdza, czy kwota wypłaty jest większa od bieżącego salda
- Jeśli brakuje środków, wyświetla
Insufficient funds. Current balance: [balance] - Jeśli środków wystarcza, odejmuje kwotę od salda, zwiększa liczbę transakcji i wyświetla
Withdrawal successful. New balance: [balance]
- Przyjmuje jako parametry wskaźnik do struktury
- Napisać funkcję o nazwie
displayAccount, która:- Przyjmuje jako parametr wskaźnik do struktury
BankAccount - Wyświetla informacje o koncie w dokładnie takim formacie:
Account Information:Account Number: [accountNumber]Owner: [ownerName]Balance: [balance]Transactions: [transactionCount]
- Przyjmuje jako parametr wskaźnik do struktury
- W funkcji main:
- Utworzyć zmienną
BankAccounto nazwieaccount - Odczytać z wejścia numer konta, imię i nazwisko właściciela oraz początkowe saldo
- Ustawić liczbę transakcji na 0
- Wywołać
displayAccount, aby wyświetlić początkowy stan konta - Odczytać kwotę wpłaty i wywołać
depositMoney - Odczytać kwotę wypłaty i wywołać
withdrawMoney - Wywołać
displayAccount, aby wyświetlić końcowy stan konta
- Utworzyć zmienną
To wyzwanie pokazuje zalety przekazywania wskaźników do struktur do funkcji. W przeciwieństwie do przekazywania przez wartość, funkcje otrzymują adres pamięci oryginalnej struktury, dzięki czemu mogą bezpośrednio modyfikować oryginalne dane. To podejście jest wydajniejsze (nie wymaga kopiowania) i umożliwia funkcjom trwałą zmianę wartości struktury w funkcji wywołującej.
Spróbuj swoich sił
#include <stdio.h>
#include <string.h>
// TODO: Zdefiniuj tutaj strukturę BankAccount
// TODO: Napisz tutaj funkcję depositMoney
// TODO: Napisz tutaj funkcję withdrawMoney
// TODO: Napisz tutaj funkcję displayAccount
int main() {
// Wczytaj dane wejściowe
int accountNum;
char ownerName[30];
float initialBalance;
float depositAmount;
float withdrawAmount;
scanf("%d", &accountNum);
scanf("%s", ownerName);
scanf("%f", &initialBalance);
scanf("%f", &depositAmount);
scanf("%f", &withdrawAmount);
// TODO: Utwórz zmienną typu BankAccount i ją zainicjalizuj
// TODO: Wywołaj displayAccount, aby pokazać stan początkowy
// TODO: Wywołaj depositMoney z kwotą wpłaty
// TODO: Wywołaj withdrawMoney z kwotą wypłaty
// TODO: Wywołaj displayAccount, aby pokazać stan końcowy
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