@sidofler
Dobra, krótkie kompedium. Wiem, że to jest długie, ale proszę przebrnij przez to, ta wiedza będzie Ci niezbędna w szkole.
Weźmy pod uwagę taki niedowartościowany programik:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int fajnosc = 0;
cout << "Jestem bardzo fajny!\n";
cout << "Potrafie dodac dwa do dwoch - prosze bardzo:\n";
cout << "2 + 2 = " << 2+2 << "\n\n";
cout << "Czy uwazasz, ze jestem fajny? Wpisz, na ile tak sadzisz (0-10):\n";
cin >> fajnosc;
if(fajnosc < 0 || fajnosc > 10)
cout << "Mialo byc od 0 do 10, jestes glupi!\n\n";
else if(fajnosc <= 5)
cout << "Jestes niemily!\n\n";
else
cout << "Tak... Masz racje!\n\n";
cout << "Dobra, teraz musimy sie pozegnac, papa!\n";
return 0;
}
Wszystko, a jest tego trochę, napisane jednym ciągiem. Nieczytelne.
Można pogrupować kawałki kodu dla czytelności, definiując funkcje:
#include <iostream>
using namespace std;
void pochwalSie()
{
cout << "Jestem bardzo fajny!\n";
cout << "Potrafie dodac dwa do dwoch - prosze bardzo:\n";
cout << "2 + 2 = " << 2+2 << "\n\n";
return;
}
void coOMnieSadzisz()
{
int fajnosc = 0;
cout << "Czy uwazasz, ze jestem fajny? Wpisz, na ile tak sadzisz (0-10):\n";
cin >> fajnosc;
if(fajnosc < 0 || fajnosc > 10)
cout << "Mialo byc od 0 do 10, jestes glupi!\n\n";
else if(fajnosc <= 5)
cout << "Jestes niemily!\n\n";
else
cout << "Tak... Masz racje!\n\n";
return;
}
void pozegnajSie()
{
cout << "Dobra, teraz musimy sie pozegnac, papa!\n";
return;
}
int main(int argc, char** argv)
{
pochwalSie();
coOMnieSadzisz();
pozegnajSie();
return 0;
}
Zdefiniowaliśmy tutaj 3 funkcje: pochwalSie()
, coOMnieSadzisz()
, pozegnajSie()
. Funkcje (w zapisie) tym różnią się od zmiennych, że posiadają nawiasy na końcu.
Możesz wywołać swoją funkcję (wykonać kawałek kodu, który został w niej zdefiniowany), wpisując jej nazwę (tylko pamiętaj o nawiasach, tak jak w tym przykładzie).
Zauważ jednak, że w tym momencie deklarację zmienniej int fajnosc
musieliśmy przenieść do funkcji coOMnieSadzisz()
- dzieje się tak dlatego, że funkcja widzi wyłącznie własne zmienne, zmiennej zadeklarowanej w innej funkcji (np. main()
, to też jest funkcja!) już nie. Dlatego takie: http://ideone.com/jktNGc rozwiązanie nie przejdzie.
Druga rzecz jest taka, że funkcja musi być zdefiniowana zanim zostaje wywołana (czyli wykonana). Dlatego też takie: http://ideone.com/4LIJuM rozwiązanie nie przejdzie.
Drugie zastosowanie funkcji jest takie, żebyś nie musiał powtarzać własnego kodu.
Weźmy pod uwagę np. taki przykładowy kalkulator:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int czasPracy = 0;
double placaZaDzien = 0;
cout << "Wpisz, w ile dni prace wykona Jan Kowalski:\n";
cin >> czasPracy;
cout << "Wpisz, ile Jan Kowalski wezmie za dziec pracy:\n";
cin >> placaZaDzien;
cout << "Jan Kowalski wezmie " << czasPracy * placaZaDzien;
cout << " za wykonana robote.\n\n";
cout << "Wpisz, w ile dni prace wykona Zbigniew Nowak:\n";
cin >> czasPracy;
cout << "Wpisz, ile Zbigniew Nowak wezmie za dziec pracy:\n";
cin >> placaZaDzien;
cout << "Zbigniew Nowak wezmie " << czasPracy * placaZaDzien;
cout << " za wykonana robote.\n\n";
return 0;
}
Widać, że to rozwiązanie jest baardzo brzydkie, musisz powtarzać 2 razy ten sam kawałek kodu. Beznadzieja.
Z pomocą przychodzą funkcje:
#include <iostream>
#include <string>
using namespace std;
double obliczKoszt(string nazwisko)
{
int czasPracy = 0;
double placaZaDzien = 0;
cout << "Wpisz, w ile dni prace wykona " << nazwisko << "\n";
cin >> czasPracy;
cout << "Wpisz, ile " << nazwisko << " wezmie za dziec pracy:\n";
cin >> placaZaDzien;
return czasPracy * placaZaDzien;
}
int main(int argc, char** argv)
{
double kosztKowalskiego = obliczKoszt("Jan Kowalski");
double kosztNowaka = obliczKoszt("Zbigniew Nowak");
cout << "\nJan Kowalski wezmie " << kosztKowalskiego << " za robote, ";
cout << "natomiast Zbigniew Nowak zazyczy sobie " << kosztNowaka << ".\n";
if(kosztKowalskiego < kosztNowaka)
cout << "Tanszy bedzie p. Kowalski.\n";
else
cout << "Tanszy bedzie p. Nowak.\n";
return 0;
}
Mamy tutaj 2 sprawy.
Po pierwsze: parametry. Funkcje mogą mieć parametry, czyli zmienne zadeklarowane w nawiasach. Tutaj mieliśmy jedną taką zmienną - string nazwisko
. Zmienne te muszą być przekazane funkcji za każdym razem, kiedy się ją wywołuje. (teoretycznie funkcja main()
też ma swoje parametry, int argc, char** argv
- są to dane, jakie można (choć nie trzeba) przekazać programowi, gdy się go uruchamia - żadnych danych jednak nie przekazujemy, więc w programie nigdzie tych zmiennych nie bierzemy pod uwagę).
Po drugie: zwracana wartość. Funkcja może zwracać wartość. Jeśli tak, trzeba zadeklarować typ zwracanej wartości, kiedy definiujemy funkcję - w tym przypadku jest to double
. Wartość, jaką zwraca funkcja, jest określona po słowie kluczowym return
- np. return czasPracy * placaZaDzien
oznacza, że funkcja zwróci iloczyn wartości zmiennych czasPracy
i placaZaDzien
. Jeśli funkcja ma nie zwracać wartości, wtedy musi być zadeklarowana jako void
- tak jak funkcje w przykładzie powyżej; wtedy też po słowie kluczowym return
nic nie następuje. (funkcja main()
powinna być typu int
i zwracać 0
, z przyczyn technicznych.)
Zauważ, że za każdym razem, kiedy wpisujesz nazwę funkcji w swoim programie, wtedy ona się wykona. Np. takie: http://ideone.com/ipehsd rozwiązanie jest niepoprawne, bo wtedy program aż 2 razy zapyta o koszt i czas pracy każdego z Panów, i to w nieodpowiednich momentach - uruchom to sobie w Dev-C++ i zobacz, jak bardzo nie działający jest ten program.
Funkcja może otrzymywać wiele parametrów, musisz je wtedy oddzielić przecinkiem, np. tak:
#include <iostream>
using namespace std;
int pole(int a, int b)
{
return a * b;
}
int main(int argc, char** argv)
{
cout << "Pole kwadratu o bokach 15 na 20 jest rowne " << pole(15, 20);
return 0;
}
Ostatnia sprawa. Przekazywanie tablic. Tablice przekazujesz do funkcji tak:
#include <iostream>
using namespace std;
int sumuj(int tablica[], int rozmiar)
{
int suma = 0;
for(int i=0; i<rozmiar; i++)
suma += tablica[i];
return suma;
}
int main(int argc, char** argv)
{
int tablica[10];
cout << "Wpisz 10 liczb oddzielonych spacja:\n";
for(int i=0; i<10; i++)
cin >> tablica[i];
cout << sumuj(tablica, 10);
return 0;
}
Zwróć uwagę, w których miejscach występują []
, a w których nie. Zauważ też, że funkcja sumuj()
potrzebuje mieć podany rozmiar tablicy.
Istnieją różnice między przekazywaniem funkcji tablic, a zmiennych nietablicowych. Porównaj:
#include <iostream>
using namespace std;
void zwieksz(int a)
{
a++;
cout << "a wewnatrz funkcji zwieksz(), po operacji a++, jest rowne: " << a << "\n";
return;
}
int main(int argc, char** argv)
{
int a = 10;
cout << "a na zewnatrz funkcji zwieksz(), przed jej wywolaniem, jest rowne: " << a << "\n";
zwieksz(a);
cout << "a na zewnatrz funkcji zwieksz(), po jej wywolaniu, jest rowne: " << a << "\n";
return 0;
}
#include <iostream>
using namespace std;
void zwieksz(int a[])
{
a[0]++;
cout << "a[0] wewnatrz funkcji zwieksz(), po operacji a++, jest rowne: " << a[0] << "\n";
return;
}
int main(int argc, char** argv)
{
int a[10];
for(int i=0; i<10; i++)
a[i]=10;
cout << "a[0] na zewnatrz funkcji zwieksz(), przed jej wywolaniem, jest rowne: " << a[0] << "\n";
zwieksz(a);
cout << "a[0] na zewnatrz funkcji zwieksz(), po jej wywolaniu, jest rowne: " << a[0] << "\n";
return 0;
}
Sprawdź sam, na czym polega różnica w obu kodach. Wrzuć to do Dev-C++ i odpal, zobacz, co się stanie.
Okej, to powinno Ci wystarczyć do rozwiązania tego zadania. Jest to w takim stylu, w jakim Cię uczą. Oczywiście kod @twonek 'a jest o niebo bardziej elegancki, być może jutro napiszę kolejny post takiej długości jak ten i wytłumaczę, dlaczego.