Funkcje w C
Ogólna składnia funkcji
typ identyfikator ( typ1 argument1, typ2 argument2)
{
/* instrukcje */
}
procedura - podprogram nie zwracający wyniku, realizujący pewną funkcjonalność
void identyfikator ( typ1 argument1, typ2 argument2)
{
/* instrukcje */
}
Instrukcja return powoduje zakończenie wykonywania funkcji i zwrócenie wartości. Może być ona użyta dowolną ilość razy w kodzie funkcji.
Funkcja - podprogram zwracający wynik na podstawie przekazanych argumentów
typ identyfikator ( typ1 argument1, typ2 argument2)
{
/* instrukcje */
return ...;
}
Funkcja czysta - funkcja, która nie ma żadnych skutków ubocznych, tzn. nie modyfikuje ani przekazanych argumentów, ani globalnego stanu programu.
Przykłady:
Funkcja bez argumentu zwracająca int
:
int foo1()
{
return 62 ;
}
Funkcja z jednym argumentem zwracająca int
int foo2( int a)
{
return a+ 4 ;
}
Funkcja z dwoma argumentami zwracająca float
float foo3( int a, int b)
{
return ( b+ a)/ 3.0 ;
}
Procedura bez argumentu:
void foo4()
{
printf( "abc" );
}
---
Procedura z jednym argumentem
```c
void foo5( int a)
{
printf( " %d " , a* 8 );
}
Wszystkie wcześniejsze funkcje były “czyste”.
Czy ta funkcja jest czysta?
#include <stdio.h>
#include <stdlib.h>
void foo10( int a)
{
a+= 5 ;
printf( "a %d\n " , a);
}
int main()
{
int a = 7 ;
printf( "b %d\n " , a);
foo10( a);
printf( "c %d\n " , a);
return 0 ;
}
Rekurencja
Rekurencja, zwana także rekursją (ang. recursion, z łac. recurrere, przybiec z powrotem) – odwoływanie się np. funkcji lub definicji do samej siebie.
Przykłady:
\[0!=1, \quad n!=(n-1)! \cdot n\]
\[F_n := \begin{cases}
0 & \text{dla } n = 0, \\
1 & \text{dla } n = 1, \\
F_{n-1}+F_{n-2} & \text{dla } n > 1.
\end{cases}\]
#include <stdio.h>
#include <stdlib.h>
int silnia( int n)
{
if ( n == 0 )
{
return 1 ;
}
return n* silnia( n- 1 );
}
int main()
{
int a = 5 ;
printf( " %d\n " , silnia( a));
return 0 ;
}
#include <stdio.h>
#include <stdlib.h>
int fib( int n)
{
if ( n == 0 )
return 0 ;
if ( n == 1 )
return 1 ;
return fib( n- 1 )+ fib( n- 2 );
}
int main()
{
int a = 6 ;
printf( " %d\n " , fib( a));
return 0 ;
}
Zadanie na rekurencję
Napisz funkcję rekurencyjną, która dla otrzymanej w argumencie nieujemnej liczby całkowitej \(n\) zwraca wartość elementu o indeksie \(n\) ciągu zdefiniowanego w następujący sposób
\[a_0=a_1=1\] \[a_{3n}=a_n, n>0\] \[a_{3n+1}=a_{3n}-1,n>0\] \[a_{3n+2}=a_{3n+1}+1, n\geqslant 0\] Stwórz dwa przypadki testowe dla funkcji.
Zasady dobrego programowania
Keep it Simple Stupid (KISS) - BUZI (Bez Udziwnień Zapisu, Idioto)
Don’t Repeat Yourself (DRY)
Tell Don’t Ask
You Aren’t Gonna Need It (YAGNI)
Separation of Concerns
KISS
kod ma być prosty i zrozumiały
unikanie skomplikowanych zapisów
nie oznacza upraszczania za wszelką cenę
Don’t Repeat Yourself (DRY)
unikanie powtórzeń w kodzie – u nas to np. polimorficzność, stałe
oddzielenie powtarzającej się części od metody
zalety: unikanie błędów, poprawki możemy dodać w jednym miejscu
Tell Don’t Ask
związane z hermetyzacją i podziałem obowiązków
należy mówić obiektom jakie akcje mają wykonywać
nie należy uzależnia wykonania akcji od stanu w jakim znajdują się obiekty
You Aren’t Gonna Need It (YAGNI)
tworzenie tego co jest potrzebne i niezbędne
usuwanie dodatków, które mogą się przydać
np. usunięcie zbędnych usingów, zwolnienie zasobów, usuwanie nie używanych zmiennych, metod
Cytat: Antoine de Saint-Exupéry
Perfekcję osiąga się wtedy, gdy nie można już nic odjąć, a nie dodać.
Separation of Concerns
elementy składowe (np. klasy i metody) powinny być rozłączne i mieć oddzielne zastosowanie
te elementy nie powinny współdzielić odpowiedzialności
Cytat: Albert Einstein
Wszystko trzeba robić tak prosto, jak to tylko jest możliwe, ale nie prościej.