Przekazywanie argumentów przez referencję

W języku C++ funkcje domyślnie kopiują pojedyncze zmienne na czas wywołania funkcji. W momencie zakończenia funkcji, kopie te są usuwane z pamięci. Aby móc operować na oryginalnych zmiennych, np. wczytywać do nich dane, musimy zawrzeć znak & (czyt. „ampersand”) przed nazwą zmiennej, w nagłówku funkcji np. 
void WczytajDane(int& a, char& b)

Nie jest to konieczne przy operowaniu na tablicachmacierztablicach. Ponieważ gdy przekazujemy tablicę do funkcji, jednocześnie przekazujemy adres pierwszego elementu w tej tablicy. Tablice nie są kopiowane na potrzeby funkcji, ponieważ byłoby to zbyt czasochłonne, a sam proces zajmowałby dużo pamięci.

W naszym przypadku, aby wczytane wartości były zapisane do oryginalnych zmiennych przy wywołaniu funkcji, musimy zapisać znak & przed każdą nazwą zmiennej. Nagłówek funkcji powinien być zapisany w następujący sposób:
void WczytajDane(int& a, int& b, int& c, int& d, int& e, int& f)

Różne funkcje o tych samych nazwach

Warto wspomnieć, że w języku C++ kilka funkcji może mieć te same nazwy. Jednak wywoływana będzie ta funkcja, która ma odpowiednie typy argumentów.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. void WczytajDane otwórz nawias okrągły int ampersant a zamknij nawias okrągły. Linia 6. otwórz nawias klamrowy. Linia 7. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj liczbe dwukropek cudzysłów średnik. Linia 8. cin zamknij nawias ostrokątny zamknij nawias ostrokątny a średnik. Linia 9. zamknij nawias klamrowy. Linia 11. void WczytajDane otwórz nawias okrągły char ampersant a zamknij nawias okrągły. Linia 12. otwórz nawias klamrowy. Linia 13. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj znak dwukropek cudzysłów średnik. Linia 14. cin zamknij nawias ostrokątny zamknij nawias ostrokątny a średnik. Linia 15. zamknij nawias klamrowy. Linia 17. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 18. otwórz nawias klamrowy. Linia 19. int a średnik. Linia 20. char b średnik. Linia 22. WczytajDane otwórz nawias okrągły a zamknij nawias okrągły średnik. Linia 23. WczytajDane otwórz nawias okrągły b zamknij nawias okrągły średnik. Linia 25. return 0 średnik. Linia 26. zamknij nawias klamrowy.

W przedstawionym programie mamy zapisane dwie funkcje WczytajDane(). Jedna z nich jako parametr ma podaną referencję do zmiennej typu int, natomiast druga jako parametr ma podaną referencję do zmiennej typu char. W momencie wywołania funkcji WczytajDane() w naszej funkcji main kompilator wie, której funkcji musi użyć na podstawie podanych jej argumentów. W przypadku wywołania funkcji WczytajDane() dla zmiennej a zostanie wywołana ta funkcja, która jako parametr ma podaną referencję do zmiennej typu int. Natomiast w momencie wywołania funkcji WczytajDane() dla zmiennej b zostanie wywołana ta funkcja, której parametr jest typu char.

Występowanie co najmniej dwóch funkcji o takiej samej nazwie nazywamy przeciążaniem funkcji. W przypadku wywołania takich funkcji mogą pojawić się sytuacje niejednoznaczne lub błędy, ponieważ nie zawsze kompilator jest w stanie odpowiednio odróżnić funkcje o tej samej nazwie. W celu uniknięcia tych problemów warto rozróżniać funkcje, nadając im niejednakowe nazwy.

Przykład 1

Program obliczający, ile jest liczb pierwszych w przedziale < 2 ; x >

Nasz program będzie pobierał od użytkownika liczbę, a następnie sprawdzał czy kolejne liczby (począwszy od dwójki, a kończąc na liczbie x) są pierwsze. Wynikiem programu będzie informacja, ile z napotkanych liczb było pierwszymi. Zaproponowane rozwiązanie wyznaczania liczb pierwszych z zadanego zakresu jest rozwiązaniem alternatywnym do tego, które przedstawiliśmy w innym materiale dotyczącym algorytmu - Sito Eratostenesa. Nie wymaga użycia dodatkowych struktur danych – tablic, dzięki czemu zyskujemy więcej pamięci, kosztem wydajności. Po przeanalizowaniu implementacji, spróbuj samodzielnie zaimplementować algorytm Sito Eratostenesa w języku C++, z zastosowaniem funkcji.

Specyfikacja problemu:

Dane:

  • x – koniec przedziału, w którym będą poszukiwane liczby pierwsze; liczba naturalna > 2

Wynik:

Program na standardowym wyjściu drukuje liczbę liczb pierwszych w przedziale < 2 ; x >

Krok 1.
Zapisz szkielet naszego programu.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 6. otwórz nawias klamrowy. Linia 8. return 0 średnik. Linia 9. zamknij nawias klamrowy.

Krok 2.
Zapisz nagłówek funkcji wczytującej dane wraz z klamrami obejmującymi ciało funkcji.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. void WczytajDane otwórz nawias okrągły int ampersant x zamknij nawias okrągły. Linia 6. otwórz nawias klamrowy. Linia 8. zamknij nawias klamrowy. Linia 10. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 11. otwórz nawias klamrowy. Linia 13. return 0 średnik. Linia 14. zamknij nawias klamrowy.

W nagłówku funkcji zapisujemy znak & przy każdej zmiennej. Ponieważ wczytujemy dane do tej zmiennej, potrzebujemy dostępu do oryginału. Funkcja WczytajDane() jest funkcją typu void, ponieważ pozwala wczytać dane, a nie zwraca żadnych wartości.

Krok 3. Wypełnij ciało funkcji WczytajDane().

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. void WczytajDane otwórz nawias okrągły int ampersant x zamknij nawias okrągły. Linia 6. otwórz nawias klamrowy. Linia 7. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj x dwukropek cudzysłów średnik. Linia 8. cin zamknij nawias ostrokątny zamknij nawias ostrokątny x średnik. Linia 9. zamknij nawias klamrowy. Linia 11. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 12. otwórz nawias klamrowy. Linia 14. return 0 średnik. Linia 15. zamknij nawias klamrowy.

Krok 4. W funkcji main() zadeklaruj odpowiednią zmienną, a następnie wczytaj do niej dane za pomocą wcześniej utworzonej funkcji.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. void WczytajDane otwórz nawias okrągły int ampersant x zamknij nawias okrągły. Linia 6. otwórz nawias klamrowy. Linia 7. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj x dwukropek cudzysłów średnik. Linia 8. cin zamknij nawias ostrokątny zamknij nawias ostrokątny x średnik. Linia 9. zamknij nawias klamrowy. Linia 11. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 12. otwórz nawias klamrowy. Linia 13. int x średnik. Linia 14. WczytajDane otwórz nawias okrągły x zamknij nawias okrągły średnik. Linia 16. return 0 średnik. Linia 17. zamknij nawias klamrowy.

Krok 5. Zapisz funkcję sprawdzającą, czy dana liczba jest liczbą pierwszą.

Linia 1. bool czyPierwsza otwórz nawias okrągły int a zamknij nawias okrągły. Linia 2. otwórz nawias klamrowy. Linia 3. for otwórz nawias okrągły int i znak równości 2 średnik i otwórz nawias ostrokątny znak równości sqrt otwórz nawias okrągły a zamknij nawias okrągły średnik i plus plus zamknij nawias okrągły. Linia 4. otwórz nawias klamrowy. Linia 5. if otwórz nawias okrągły a procent i znak równości znak równości 0 zamknij nawias okrągły. Linia 6. return false średnik. Linia 7. zamknij nawias klamrowy. Linia 8. return true średnik. Linia 9. zamknij nawias klamrowy.

Nasza funkcja jest typu bool, ponieważ zwraca true, jeśli liczba jest liczbą pierwszą oraz false, jeśli liczba nie jest liczbą pierwszą. Funkcja ma jeden parametr typu int, następnie w pętli, dla  sprawdzane jest, czy nasza liczba dzieli się bez reszty przez i. Jeśli tak – liczba nie jest pierwsza. Zatem zwracamy wartość false. Jeśli w trakcie działania pętli nie znajdziemy dzielnika a – oznacza to, że jest to liczba pierwsza. Możemy więc zwrócić true.

Ważne!

Funkcja sqrt() dostępna jest w bibliotece cmath – pamiętaj, by ją dołączyć w programie. 

Krok 6. Zadeklarujmy zmienną, która będzie przechowywać liczbę wszystkich liczb pierwszych. Od razu wyzerujmy jej wartość.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. bool czyPierwsza otwórz nawias okrągły int a zamknij nawias okrągły. Linia 6. otwórz nawias klamrowy. Linia 7. for otwórz nawias okrągły int i znak równości 2 średnik i otwórz nawias ostrokątny znak równości sqrt otwórz nawias okrągły a zamknij nawias okrągły średnik i plus plus zamknij nawias okrągły. Linia 8. otwórz nawias klamrowy. Linia 9. if otwórz nawias okrągły a procent i znak równości znak równości 0 zamknij nawias okrągły. Linia 10. return false średnik. Linia 11. zamknij nawias klamrowy. Linia 12. return true średnik. Linia 13. zamknij nawias klamrowy. Linia 15. void WczytajDane otwórz nawias okrągły int ampersant x zamknij nawias okrągły. Linia 16. otwórz nawias klamrowy. Linia 17. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj x dwukropek cudzysłów średnik. Linia 18. cin zamknij nawias ostrokątny zamknij nawias ostrokątny x średnik. Linia 19. zamknij nawias klamrowy. Linia 21. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 22. otwórz nawias klamrowy. Linia 23. int x przecinek pierwszych znak równości 0 średnik. Linia 24. WczytajDane otwórz nawias okrągły x zamknij nawias okrągły średnik. Linia 26. return 0 średnik. Linia 27. zamknij nawias klamrowy.

Krok 7. Zapiszmy pętlę for, która będzie się wykonywała od 2 do x, a w niej sprawdźmy – przy pomocy wcześniej zapisanej funkcji – (pamiętając o dołączeniu biblioteki cmath) czy liczba jest liczbą pierwszą. Jeśli tak jest, zwiększmy wartość zmiennej pierwszych o jeden.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 4. using namespace std średnik. Linia 6. bool czyPierwsza otwórz nawias okrągły int a zamknij nawias okrągły. Linia 7. otwórz nawias klamrowy. Linia 8. for otwórz nawias okrągły int i znak równości 2 średnik i otwórz nawias ostrokątny znak równości sqrt otwórz nawias okrągły a zamknij nawias okrągły średnik i plus plus zamknij nawias okrągły. Linia 9. otwórz nawias klamrowy. Linia 10. if otwórz nawias okrągły a procent i znak równości znak równości 0 zamknij nawias okrągły. Linia 11. return false średnik. Linia 12. zamknij nawias klamrowy. Linia 13. return true średnik. Linia 14. zamknij nawias klamrowy. Linia 16. void WczytajDane otwórz nawias okrągły int ampersant x zamknij nawias okrągły. Linia 17. otwórz nawias klamrowy. Linia 18. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj x dwukropek cudzysłów średnik. Linia 19. cin zamknij nawias ostrokątny zamknij nawias ostrokątny x średnik. Linia 20. zamknij nawias klamrowy. Linia 22. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 23. otwórz nawias klamrowy. Linia 24. int x przecinek pierwszych znak równości 0 średnik. Linia 25. WczytajDane otwórz nawias okrągły x zamknij nawias okrągły średnik. Linia 27. for otwórz nawias okrągły int i znak równości 2 średnik i otwórz nawias ostrokątny znak równości x średnik i plus plus zamknij nawias okrągły. Linia 28. otwórz nawias klamrowy. Linia 29. if otwórz nawias okrągły czyPierwsza otwórz nawias okrągły i zamknij nawias okrągły zamknij nawias okrągły. Linia 30. pierwszych plus plus średnik. Linia 31. zamknij nawias klamrowy. Linia 33. return 0 średnik. Linia 34. zamknij nawias klamrowy.

Krok 8. Wypiszmy wartość zmiennej pierwszych wraz z odpowiednim komunikatem.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 4. using namespace std średnik. Linia 6. bool czyPierwsza otwórz nawias okrągły int a zamknij nawias okrągły. Linia 7. otwórz nawias klamrowy. Linia 8. for otwórz nawias okrągły int i znak równości 2 średnik i otwórz nawias ostrokątny znak równości sqrt otwórz nawias okrągły a zamknij nawias okrągły średnik i plus plus zamknij nawias okrągły. Linia 9. otwórz nawias klamrowy. Linia 10. if otwórz nawias okrągły a procent i znak równości znak równości 0 zamknij nawias okrągły. Linia 11. return false średnik. Linia 12. zamknij nawias klamrowy. Linia 13. return true średnik. Linia 14. zamknij nawias klamrowy. Linia 16. void WczytajDane otwórz nawias okrągły int ampersant x zamknij nawias okrągły. Linia 17. otwórz nawias klamrowy. Linia 18. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj x dwukropek cudzysłów średnik. Linia 19. cin zamknij nawias ostrokątny zamknij nawias ostrokątny x średnik. Linia 20. zamknij nawias klamrowy. Linia 22. int main otwórz nawias okrągły zamknij nawias okrągły. Linia 23. otwórz nawias klamrowy. Linia 24. int x przecinek pierwszych znak równości 0 średnik. Linia 26. WczytajDane otwórz nawias okrągły x zamknij nawias okrągły średnik. Linia 28. for otwórz nawias okrągły int i znak równości 2 średnik i otwórz nawias ostrokątny znak równości x średnik i plus plus zamknij nawias okrągły. Linia 29. otwórz nawias klamrowy. Linia 30. if otwórz nawias okrągły czyPierwsza otwórz nawias okrągły i zamknij nawias okrągły zamknij nawias okrągły. Linia 31. pierwszych plus plus średnik. Linia 32. zamknij nawias klamrowy. Linia 33. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Liczba liczb pierwszych w przedziale otwórz nawias ostrokątny 2 średnik cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny x otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów zamknij nawias ostrokątny dwukropek cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny pierwszych średnik. Linia 34. return 0 średnik. Linia 35. zamknij nawias klamrowy.

Słownik

macierz
macierz

układ liczb, symboli lub wyrażeń zapisanych w postaci tablicy, w rzędach i kolumnach

metoda wyznaczników
metoda wyznaczników

metoda, która polega na rozwiązywaniu układu równań za pomocą wyznaczników; więcej na jej temat znajdziesz w e‑materiale Metoda wyznacznikowa rozwiązywania układu równań liniowych z dwiema niewiadomymiP1GfCfRXFMetoda wyznacznikowa rozwiązywania układu równań liniowych z dwiema niewiadomymi