dekompozycja - rozbijanie problemu na mniejsze częsci
kompilator musi mieć następujące informacje o funkcji:
nazwę
ile parametrów i jakiego typu
jaki zwraca typ
kompilator może to odkryć przy pierwszym uruchomieniu funkcji (implicit declaration)
albo wcześniej z prototypu, prototyp niezbędny gdy definicja pod main.
deklaracja funkcji (prototyp)zakończona ; nie zawiera ciała
definicja funkcji ciało w {}
wywołanie funkcji nazwa();
jeśli funkcja nic nie zwraca void, nie można wywołać tak:
int i=hello();
jeśli funkcja zwraca konkretny typ to return expression
bloki funkcji { } określają zakres działania zmiennych w nich zainicjowanych
zmienna zadeklarowana poza blokami (main czy funkcji) będzie zmienna globalną
dostępną dla każdej funkcji
parametry funkcji - specjalny rodzaj zmiennej zadeklarowanej w nawiasach, dostępnej wewnątrz F.
parametry funkcji moga zawierać działanie
np:
hello (2*x); //jeśli tylko wynik zgadza się z typem określonym w deklaracji/prototypie
parametry funkcji przez wartość tworzą kopię więc zmiany wew. funkcji nie wpływają na wartość
przekazywanie przez wskaźnik wpłynie na wynik:
void functionx(int *ptr) {
*ptr = *ptr + 100;
}
albo:
void incr(int *value) {
(*value)++; //w nawiasach musi byc !!!
}
PARAMETRY FUNKCJI i STRUKTURY
struktury przekazywane są jako wartość
ale możemy zastosować wskaźnik do struktury (wtedy wywołujemy struturę przez adres &)
struct STR {
int Int;
char Char;
};
void funx(struct STR *p) {
p -> Int = 2; //uwaga, konieczne odwolanie przez ->
p -> Char = 'B';
}
int main(void) {
struct STR str = { 1, 'A' };
funx(&str); //uwaga przekazanie przez & zeby powstał wskaznik
PARAMETRY FUNKCJI I TABLICE
tablice zawsze są przekazywane jako wskaźnik do pierwszego elementu
#include <stdio.h> void mul2(int *arrptr) { int i; for(i = 0; i < 5; i++) arrptr[i] *= 2; } int main(void) { int arr[5] = { 1, 2, 3, 4, 5 }; int i; for(i = 0; i < 5; i++) printf("%d ", arr[i]); printf("\n"); mul2(arr); for(i = 0; i < 5; i++) printf("%d ", arr[i]); printf("\n"); return 0; }
i pomimo tego, ze są przekazane jako wskaznik, to mozna nimi operować jak tablicą (ideksując [])
nawet jak przekazujemy przez void funkcja (int a[]); to przekazuje przez wkaśnik i nie ma informacji o wielkości tablicy, sizeof pokaze wewnatrz funkcji tylko wielkosc wskaxnika, zeby wiedziec o wielkosci tablicy przekazanej do funkcji stosuje się kilka metod, jedna z nich to przekazanie dodatkowej wartosci o długości tablicy.
String jest specjalnym rodzajem tablicy (typu char) bo kończy się \0
dzięki czemu możemu szukać \0 i policzyć dlugosc ciagu (wielkosc tablicy)
int mystrlen(char *str) { int counter = 0; while(*str != '\0') { //mozemy zamienic na while(*str) counter++; str++; //a zeby pozbyc się te lini na while(*str++) } return counter; }
powiększamy str++ bo ma zmieniać się sam wskaźnik i przeskakiwać na następne pola(a nie wartosc)
a tutaj wersja zoptymalizowana do pętli for:
int mystrlen(char *str) { int counter; for(counter =0; *str++; counter++) ; return counter; }
i jeszcze jedna wersja bez zmiennej counter (wspolna zmienna str) ale za to z dodanym wskaznikiem
{ char *begin; for(begin=str;*str;str++) ; return str-begin; }
poniżej własna wersja strcpy:
char *mystrcpy(char *destination, char *source) { char *res = destination; for( ; ; ) { /* a finite infinite loop */ *destination = *source; if(*source == '\0') break; destination++; source++; } return res; }
znak = ma pewną właściwość, nie tylko przypisuje wartość, ale ja zwraca !
dlatego możemy uprościc i zapisać tak, czyli jak w source bedzie 0 zwroci poza () tez 0
for( ; ; ) { /* a finite infinite loop */ if(!(*destination = *source)) break;
generalnie :
i = j = k = 0;
i = (j = (k = 0));
czyli:
k = 0;
j = 0;
i = 0;
forma najkrótsza:
char *mystrcpy(char *destination, char *source) { char *res; for(res = destination; (*destination = *source);) { destination++; source++; } return res; }
mega skrócone:
for(res = destination; (*destination++ = *source++); ) ;
TABLICE WIELOWYMIAROWE jako PARAMETR FUNKCJI
potrzebujemy informacji o ilosci kolumn, zeby wiedziec co ile skakać
void printarr(int t[3][3]);
w praktyce wystarczy taka informacja
void printarr(int t[][3]);
TABLICA WSKAŹNIKÓW
inne rozwiązanie to tablica wskaźników
int *arrptr[3]; //tak zwany fake array
w takiej sytuacji musimy alokować pamięć i ją potem zwolnić
for(i = 0; i < 3; i++) { arrptr[i] = (int *) malloc(3 * sizeof(int)); for(j = 0; j < 3; j++) arrptr[i][j] = (3 * i) + j + 1; }
zwolnienie:
for(i = 0; i < 3; i++)
free(arrptr[i]);
całość:
#include <stdio.h> #include <stdlib.h> void printarrptr(int **t) { int i,j; for(i = 0; i<3; i++) { for(j = 0; j<3; j++) printf("%d\t",t[i][j]); printf("\n"); } } int main(void) { int *arrptr[3]; int i,j; for(i = 0; i < 3; i++) { arrptr[i] = (int *) malloc(3 * sizeof(int)); for(j = 0; j < 3; j++) arrptr[i][j] = (3 * i) + j + 1; } printarrptr(arrptr); for(i = 0; i < 3; i++) free(arrptr[i]); return 0; }
PARAMETRY FUNKCJI MAIN
int main(int argc,char *argv[])
argc- counter, licznik argumentów, kiedy 1 to bez parametrów
argv - tablica wskaźników do stringów zawierających argumenty
argv[0] contains the name of the running program
argv[1] contains the string passed to the program as the first argument
argv[n] contains the string passed to the program as the n-th argument
wydruk argumentów w kolumnie:
#include <stdio.h> int main(int argc, char *argv[]) { int i; for(i = 0; i < argc; i++) printf("%s\n", argv[i]); return 0; }
REKURENCJA
funkcja rekurencyjna n!
int factorial(int n) {
if(n == 1)
return 1;
else
return n * factorial(n – 1);
}
OPERATOR EX1 ? EX2 : EX3
jeśli EX1 prawda to EX2 jesli nie to EX3
EXTERN
extern int factorial(int n);
the purpose of a header file can be twofold:
firstly, the compiler finds out how to compile the external function invocation;
secondly, the programmer can learn how to use the functions in the program.
przykładowy:
/***********************************************************
factorial version 1.0, 24 July 2012
author: sauron@mordor.com
the function computes the factorial of its argument
acceptable range of the parameter is [1..20]
the correctness of the parameter isn't checked – be careful!
************************************************************/
teraz funkcja factorial w osobnym pliku (dlatego extern) nazwanym factorial.h
w głównym programie go dołączamy przez include ale piszemy w " " (bo plik w tym samym katalogu)
przykład całości:
#include <stdio.h> #include "factorial.h" int main(int argc, char *argv[]) { int n, result; printf("Enter n value:"); scanf("%d", &n); if(n <= 0 || n > 20) { printf("Bad news: you've entered an invalid value.\n"); return 1; } result = factorial(n); printf("Factorial of %d is %d\n", n, result); return 0; }
gdzie zawartość factorial.h to:
int factorial(int n) {
return n == 1 ? 1 : factorial (n - 1) - n;
}
ZADANIA
Zad1:
#include <stdio.h>
int i = 0;
void f(void) {
int i = 1;
}
int main(void) {
f();
printf("%d",i);
return 0;
}
wynik 0, zamiana w funkcji z int i=1 na i=1 sprawi ze nie stworzy nowej ale zmieni globalna
Zad2
#include <stdio.h>
int i = 1;
int *f(void) {
return &i;
}
int main(void) {
int i = 0;
i = *f();
printf("%d",i);
return 0;
}
Wynik 1, mamy stworzenie kolejnej zmiennej i w zakresie maina {}, ale funkcja odwola sie do globalnej
Zad3
#include <stdio.h>
int i = 0;
int *f(int *i) {
(*i)++;
return i;
}
int main(void) {
int i = 1;
i = *f(&i);
printf("%d",i);
return 0;
}
Wynik 2, bo w tym przypadku wpisujemy parametr funkcji w obszarze main {} a tam mamy inna zmienna i o wartosci 1 a nie 0 jak w globalnym
Zad 4
#include <stdio.h>
int f(int t[][]) {
return t[0][0] + t[1][0];
}
int main(void) {
int i,a[2][2] = { {-2,-1},{1,2} };
i = f(a + 2);
printf("%d",i);
return 0;
}
Wynik: błąd kompilacji, bo jeśli [][] jako parametr funkcji to musi mieć ilość kolumn
Zad5
#include <stdio.h>
int f(char t[]) {
return t[1] - t[0];
}
int main(void) {
int i = 2;
i -= f("ABDGK" + 1);
printf("%d",i);
return 0;
}
Wynik 0, bo D-B =2
Zad 6
#include <stdio.h>
#include <string.h>
void f(char *s,int i) {
*(s + i) = '\0';
}
int main(void) {
char a[] = { 'a','b','c','d' };
f(*a[1],1);
printf("%d",strlen(a));
return 0;
}
Wynik błąd kompilacji, nie może być *a[1]
Zad7
to samo zadanie co 6 ale poprawne
#include <stdio.h>
#include <string.h>
void f(char *s,int i) {
*(s + i) = '\0';
}
int main(void) {
char a[] = { 'a','b','c','d' };
f(a+1,1);
printf("%d",strlen(a));
return 0;
}
Wynik 2