21.4.2009 Makra
- dělají se také pomocí #define - podobné (použitím) funkcím - předpřipravená jsou např. v ctype.h - jak na vlastní makro: #define je_velke(c)
((c) >= 'A' && (c) <='Z')
- a potom použití v programu: if (je_velke('A' + 'B')) { .. }
- před překladem z toho preprocesor udělá toto: if ((('A' + 'B') >= 'A' && ('A' + 'B') <='Z')) { .. }
- opět je nutno závorkovat jak tělo makra, tak jeho parametr uvnitř těla Makra v ctype.h např.: isalnum(c) – je číslo nebo písmeno ? isalpha(c) – je písmeno ? isascii(c) – je ascii 0-127 ? iscntrl(c) – je ascii 0-26 ? např. test jen na tisknutelné znaky bez háčků a čárek: if (isascii(c) && !iscntrl(c)) { putchar(c); } isdigit(c)
– je číslice ?
– je malé písmeno ? isupper(c) – je velké písmeno ? isprint(c) – je ascii 32-126 (tisknutelné) ? ispunct(c) – je interpunkční znaménko ? (, . / atp.) isspace(c) – je mezera, tab, \n tj. nový řádek ? isxdigit(c) – je hexadec. cislice (0-9, A-F, a-f) ? isgraph(c) – je ascii 33-126 (i pseudografické znaky) ? islower(c)
Konverzní makra tolower(c) - na malá písmena toupper(c) - na velká písmena toascii(c) - ořízne bit s pořadím 7 (tj. osmý, nejvyšší bit), tj. z 8 bitů znaku bere jen dolních 7, tj. 0. až 7.
Pole – stručný úvod do začátku, podrobně později - statická pole (ne dynamicky) - číslují se od 0 int policko[100]; // tj. pole je od 0 do 99 !!! policko[5] = 7; // pozor je to 6. prvek s indexem 5 policko[99] = 2; // poslední prvek. policko[100] = 78; // C nijak neprotestuje příkaz vykoná
- hodnota 78 je zapsána do paměti ZA moje pole, přepisuji paměť, kterou nemám přidělenu => pravděpodobně bude program chybovat. Může tam uložena moje jiná proměnná... - to znamená, že C nekontroluje rozsahy polí a ohlídání je na programátorovi – musím si udržovat např. nějakou proměnnou, kde budu délku pole uloženu.
Dvourozměrné pole: int pol2d[5][10]; pol2d[0][0] = 4;
"Prolezu" dvourozměrné pole: int pole2d[100][100]; for(i = 0; i < 100; i++) { for(j = 0; j < 100; j++) { pol2d[j][i] = 5; // po sloupcích – vždy pro i-tý sloupec projedu všechny řádky (pomocí j) } } - nebo s konstantami
#define RADKU 100 #define SLOUPCU 50 ...tady nějaký začátek programu int pole2d[RADKU][SLOUPCU]; for(i = 0; i < RADKU; i++) { for(j = 0; j < SLOUPCU; j++) { pol2d[i][j] = 5; // po řádcích – vždy pro i-tý řádek projedu všechny sloupce (pomocí j) } }
Funkce – základy (shrnutí ze cvičení) - základní deklarace funkce: návratový_typ název_funkce(typ_parametru název_parametru_funkce) { tělo_funkce; return návratová_hodnota; }
Např: int pocitej_soucin(int a, int b) { int pom; pom = a * b; return(pom); /* lze též return pom; }
*/
Jinak totéž: int pocitej_soucin(int a, int b) { return(a * b); }
Pozn.: funkční prototyp této funkce (např. v hlavičkovém souboru) by vypadal takto: int pocitej_soucin(int a, int b);
nebo také: int pocitej_soucin(int , int);
------------------- 21.4.2009 ------------------Potom volání této funkce: void main(void) { int vysledek; vysledek = pocitej_soucin(10, 20); printf("Vysledek soucinu %d a %d je %d.",5,6,pocitej_soucin(5,6)); }
- jiný postup - kompletnější void main(void) { int vstup1, vstup2, vysledek; vstup1 = 23; vstup2 = 25; vysledek = pocitej_soucin(vstup1, vstup2); printf("Vysledek soucinu %d a %d je %d.",vstup1,vstup2, vysledek); }
- typ proměnné použité jako parametr u return musí být shodný s typem (návratovým typem) dané funkce - lze provést přetypování návratové hodnoty nebo se udělá implicitní typová konverze. Např.: return((int) (a * b));
- pozor – pokud funkci volám, musí už být známa (stačí hlavička funkce, tzv. funkční prototyp) #include <stdio.h> /* funkcni prototyt */ int pocitej_soucin(int a, int b); // tato funkce umi scitat void main(void) { int vstup1, vstup2, vysledek; vstup1 = 23; vstup2 = 25; vysledek = pocitej_soucin(vstup1, vstup2); printf("Vysledek soucinu %d a %d je %d.\n",vstup1,vstup2, pocitej_soucin (vstup1, vstup2));
system("PAUSE"); } int pocitej_soucin(int a, int b) {
int pom; pom = a * b; return(pom); }
/* lze též return pom;
*/
Nebo: void nazdar(void);
/* musím uvést, aby ho ahoj mohl zavolat */
int ahoj(void) { ...nějaké příkazy... nazdar(); /* u funkcí bez parametrů se uvádí závorky */ ... atd... } void nazdar(void) { ...nějaké příkazy... int v = ahoj(); /* u funkcí bez parametrů se uvádí závorky */ ... atd... }
- používá se hlavně pokud jsou funkce v různých souborech – potom se nedávají funkční prototypy na začátek, ale do vlastního hlavičkového souboru (.h): Např.: funkce1.h obsahuje: /* funkcni prototyp */ int pocitej_soucin(int a, int b);
funkce1.c obsahuje: #include <stdio.h> #include "funkce1.h" void main(void) { int vstup1, vstup2, vysledek; vstup1 = 23; vstup2 = 25; vysledek = pocitej_soucin(vstup1, vstup2); printf("Vysledek soucinu %d a %d je %d.\n",vstup1,vstup2, pocitej_soucin (vstup1, vstup2)); system("PAUSE"); }
na konci nebo v jiném souboru: int pocitej_soucin(int a, int b) {
int pom; pom = a * b; return(pom);
/* lze též return pom;
*/
}
- do hlavičkových souborů se umisťují dále konstanty a deklarace nových datových typů (typedef) Dále k funkcím: - pokud funkce nevrací nic – návratový typ je void - pokud nemá parametry – parametry jsou void - volání funkce bez parametrů: funkce(); /* závorky jsou nutné !!! */ - nezapomenout – parametry funkce se chovají jako lokální proměnné - C umí předat parametry do funkce pouze hodnotou, jinak musím obejít (viz dále - pointery) - lokální proměnné – uvnitř funkce – z vnějšku nejsou vidět, zanikají při skončení "své" funkce - globální proměnné – jsou deklarovány mimo funkci, jsou vidět "všude" - nesmí se umístit do souboru .h – mohl bych jej víckrát "includovat" => proměnná by byla v projektu několikrát – při linkování dojde ke kolizi... – lze ošetřit – viz dále. - pokud bude mít lokální proměnná ve funkci stejné jako nějaká globální proměnná => lokální proměnná překryje ve funkci tu globální. int g; double fn; double vypocet(int fn) { double g; g = 2.45; // měním lokální g, globální g je překryto g = 3.5 * fn; // jde o lokální fn, ten parametr funkce // zde zbytek programu return(nejaky_vysledek); }