Hmm no dobrze, dość już tego gadania... napiszmy troszkę kodu, oto przykładowa funkcja:
double PoleKola(double dPromien)
{
double dWynik;
dWynik = 3.14 * dPromien * dPromien;
return(dWynik);
}
Nie, nie ma tutaj nic, kompletnie nic podchwytliwego. Powyższa funkcja działa poprawnie. Możemy więc użyć ją w programie:
int main()
{
double dPole;
double dPromien;
scnaf("%lf",&dPromien);
dPole = PoleKola(dPromien);
printf("Pole kola o promieniu %f wynosi %f.\n", dPromien, dPole);
}
Funkcja PoleKola zwraca wartość typu double. Aby przypisać tę wartość jakiejś zmiennej musimy użyć konstrukcji zmienna = PoleKola(...). Co jednak zrobić, gdyby okazało się, ze funkcja musi zwracać więcej niż jedną wartość? Załużmy, że chcemy za pomocą jednej funkcji policzyć pole oraz obwód koła. W zaprezentowany powyżej sposób jest to oczywiście niewykonalne. I tutaj przychodzą z pomocą wskaźniki. Zobaczmy więc jak można to zrealizować:
bool PoleKola(double dPromien, double* dPole, double* dObwod)
{
if( dPromien <= 0.0 )
{
return( false );
}
*dPole = 3.14 * dPromien * dPromien;
*dObwod = 6.28 * dPromien;
return( true );
}
Hmm no tak, teraz wygląda to... troszke inaczej. Zanijmy od wyjaśnienia czym są owe gwiazdki występujące po typie zmiennej. Gwiazdka mówi nam o tym (a raczej za jej pomocą my mówimy to kompilatorowi), że dPole i dObwod nie sa bynajmniej zwyczajnymi zmiennymi. Poprzedzając nazwę zmiennej gwiazdką czynimy z niej zmienna wskaźnikową. Nasza funkcja przyjmuje więc jedną zmienną jako wartość, jest nią dPromien oraz dwa wskaźniki do zmiennych typu double.
Fakt iż są to wskaźniki ma tutaj kluczowe znaczenie dla działania funkcji. Zauważmy, że nasza funkcja w żaden sposób nie wypisuje wyniku swojego działania na ekranie. Oczywiście jest to działanie zamierzone. Zadaniem tej funkcji jest modyfikacja zmiennych, które deklarujemy wcześniej w programie. W tym momencie można zadać sobie pytanie... skoro zmienne są deklarowane wcześniej to czemu po prostu zwyczajnie nie przekazać ich do funkcji? Rezultat takiego rozwiązania, dla osoby początkującej może być dość zaskakujący, zresztą aby sie o tym przekonać polecam samodzielnie przetestować taki przypadek. Wróćmy jednak do tematu. W tym wypadku kluczowe znaczenie ma fakt, iż zmienne w C i C++ są przekazywane do funkcji przez wartość. Oznacza to tyle, że w momencie wywołania funkcji tworzone są lokalne kopie zmiennych, które w "normalny" sposób do niej przekazujemy. Co za tym idzie, wszelkie operacje modyfikacji ich wartości odbywają się na tych kopiach a nie na oryginałach zadeklarowanych w programie. W naszym przypadku, nie jest to efekt pożądany. Aby osiągnąć to, czego oczekujemy jestśmy więc zmuszeni użyć wskaźników.
Wskaźnik jest tak naprawdę liczbą, konkretnie numerem (adresem) komórki w pamięci, pod którym znajduje się zmienna. Oczywiście wskaźnik sam nie wie na jaką zmienna ma pokazywać, zadanie "powiedzenia" mu o tym spoczywa na nas. Robimy to za pomocą tzw. operatora wyłuskania: &. A konkretnie tak:
double dZmienna; double* pWskaznik; pWskaznik = &dZmienna;Za pomocą operatora wyłuskania uzyskujemy adres zmiennej, na której go użyjemy. W naszym konkretnie przypadku nie musimy jednak tworzyć w programie głównym specjalnych zmiennych wskaźnikowych. Wystarczy, że operator wyłuskania użyjemy w wywołaniu funkcji, przed nazwa zmiennej. Zakładając, że gdzieś w programie mamy zadeklarowane zmienne dPromien, dPole, dObwod, poprawne wywołanie funkcji powinno wygladać tak:
PoleKola(dPromien, &dPole, &dObowd);Aby w czasie wykonywania funkcji zmodyfikować zmienna dPole a nie wskazanie do niej znowu musimy użyć gwiazdki:
*dObwod = 6.28 * dPromien; // poprawnie dObwod = 6.28 * dPromien; // blad: zostanie zmodyfikowana wartość wskazania a nie wartość zmiennej!!!Wartość logiczna zwracaną przez funkcje można użyć, np. tak jak w powyższym przykładzie, do wychwycenia niepożądanego działania użytkownika (podanie zerowego bądź też ujemnego promienia). Na koniec przykładowy program, który czytelnik powinien być w stanie napisać samodzielnie po przeczytaniu tej notki i zrozumiemniu, czym są i do czego, już w początkowej fazie nauki, mogą przydać się wskaźniki.
#include#include bool PoleKola(double dPromien, double* dPole, double* dObwod); int main() { double dPromien; double dPole; double dObwod; bool bOK; scanf("%lf",&dPromien); bOK = PoleKola(dPromien, &dPole, &dObwod); if(bOK) { printf("Promien: %.2f\nPole: %.2f\nObwod: %.2f\n", dPromien, dPole, dObwod); } else { printf("Podano nieprawidlowy promien!!!\n"); } system("pause"); return(0); } bool PoleKola(double dPromien, double* dPole, double* dObwod) { if(dPromien <= 0.0) { return(false); } *dPole = 3.14 * dPromien * dPromien; *dObwod = 6.28 * dPromien; return(true); }
0 komentarze:
Prześlij komentarz