Programování v jazyce C



Podobné dokumenty
Algoritmizace a programování

Cílem kapitoly je seznámit studenta se strukturou programu a jeho překladem.

Základní stavební prvky algoritmu

Programování v jazyce C

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Knihovní funkce jazyka C

Algoritmizace a programování

Uložené procedury Úvod ulehčit správu zabezpečení rychleji

Návrh a tvorba WWW stránek 1/38 PHP

awk programovatelný filtr

int => unsigned int => long => unsigned long => float => double => long double - tj. bude-li:

Úvod Petr Kropík viz:

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

Databázovéa informačnísystémy NÁVRH IMPLEMENTACE 2 KONZISTENCE DATABÁZE

3 Vývojová prostředí, základní prvky jazyka Java, konvence jazyka Java

Algoritmus (nebo dřívějším pravopisem algorithmus)

Soubory a databáze. Soubor označuje množinu dat, která jsou kompletní k určitému zpracování a popisují vybrané vlastnosti reálných objektů

Programování 1. hodina. RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

Praktické úlohy- zaměření specializace

Obsah. Úvodem 9 Komu je kniha určena 9 Forma výkladu 9 Konkrétní postup výuky 10 Příklady ke knize 11

5. Ř etězce (třída String)

Objektově orientované databáze

Jazyk C++ I. Šablony 3

Úvod do jazyka C. Proč jazyk C

Otázky k teoretické části zkoušky z předmětu IAJCE 2006/2007

Hotelová škola, Obchodní akademie a Střední průmyslová škola Teplice,Benešovo náměstí 1, příspěvková organizace

NÁVOD K OBSLUZE MODULU VIDEO 64 ===============================

Data v počítači EIS MIS TPS. Informační systémy 2. Spojení: jan.skrbek@tul.cz tel.: Konzultace: úterý

Seznámení žáků s pojmem makra, možnosti využití, praktické vytvoření makra.

Server. Software serveru. Služby serveru

Programovací jazyk C++ Hodina 1

Opakování programování

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Vytvoření nebo odstranění makra Excel

10 Práce s řetězci - pokračování

Sbírka úloh pro elektronickou stavebnici. Stručný popis programovacího jazyka Bascom AVR

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

IUJCE 07/08 Přednáška č. 1

Metody hodnocení rizik

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

Maturitní témata z předmětu Programování a databázové systémy. pro šk. rok 2012/2013

přetížení operátorů (o)

Tekla Structures Multi-user Mode

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

účetních informací státu při přenosu účetního záznamu,

-1- N á v r h ČÁST PRVNÍ OBECNÁ USTANOVENÍ. 1 Předmět úpravy

Aplikace počítačů v provozu vozidel 9

ČÁST PÁTÁ POZEMKY V KATASTRU NEMOVITOSTÍ

Jazyk C++, některá rozšíření oproti C

Bitové operátory a bitová pole. Úvod do programování 2 Tomáš Kühr

Programovací jazyk C(++) C++ area->vm_mm->locked_vm -= len >> PAGE_SHIFT;

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

Adresace paměti. 11.přednáška

INTERNETOVÝ TRH S POHLEDÁVKAMI. Uživatelská příručka

Směrnice pro vedení, vypracování a zveřejňování bakalářských prací na Vysoké škole polytechnické Jihlava

Co najdete v ASPI? (pro uživatele SVI FSE UJEP)

Modul Řízení objednávek.

Prostory jmen. #include<iostream.h> namespace RadimuvProstor { int secti(int a, int b); class Trida { private: int Atribut; public: void metoda();

Práce s řetězci. IUJCE Přednáška č. 10. string.h. vrací: délku řetězce str (bez '\0')

V dalších letech se pak začaly objevovat první normy pro jazyk C++ (ISO/IEC 14882:1998; ISO/IEC 9899:1999; ISO/IEC 14882:2003; ISO/IEC 14882:2011).

Pokyn D Sdělení Ministerstva financí k rozsahu dokumentace způsobu tvorby cen mezi spojenými osobami

GIGAmatic. Tenzometrický přetěžovací převodník. 1. Popis Použití Technické informace Nastavení Popis funkce 6. 6.

1. Požadavky na provoz aplikací IISPP

Pravidla pro využívání lokální počítačové sítě Slovanského gymnázia v Olomouci. Preambule

Lekce 9 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Quido USB 0/ Spínač síťového napětí 230 V ovládaný z PC přes USB rozhraní. 28. února 2011 w w w. p a p o u c h. c o m

Moderní technologie ve studiu aplikované fyziky CZ.1.07/2.2.00/ Reálná čísla

Pokyny České pošty pro označování Doporučených zásilek čárovými kódy

MINISTERSTVO PRO MÍSTNÍ ROZVOJ UŽIVATELSKÁ PŘÍRUČKA IS KP 14+ PRO INTEGROVANÉ NÁSTROJE: ŽÁDOST O PODPORU STRATEGIE CLLD. Verze: 1.

Používání klávesnice. Zobrazit vše. V tomto článku

Projekt: Inovace oboru Mechatronik pro Zlínský kraj Registrační číslo: CZ.1.07/1.1.08/

Zabezpečení Uživatelská příručka

Informační systémy 2008/2009. Radim Farana. Obsah. Skripty a dávky. Nastavení aktuální databáze. USE DatabaseName

INFORMATIKA V CHOVECH PRASAT

Inovace výuky prostřednictvím šablon pro SŠ

Přednáška Tablety a chytré telefony. Ing. Michaela Mudrochová Algoritmus individuálního vzdělávání CZ.1.07/3.1.00/

Dálkové ovládání HP Media remote control (pouze u vybraných modelů) Uživatelská příručka

Metodika pro nákup kancelářské výpočetní techniky

Zabezpečení. Uživatelská příručka

Informační systém pro rezervaci pokojů hotelu SPORT

Obsah. Obsah. Úvod Makra v Excelu Nahrávání maker První setkání s editorem jazyka Visual Basic... 31

Android Elizabeth. Verze: 1.3

Záloha a obnovení Uživatelská příručka

Obsah ÚVOD. Participanti. Nastavení testu. - úvod - participanti - nastavení testu - přehled úkolů testu - soupis problémů a návrh řešení - závěr

Manuál uživatele čipové karty s certifikátem

Základy programování (IZP)

DATABÁZE DŮLEŽITÉ: Před načtením nové databáze do vaší databáze si prosím přečtěte následující informace, které vám umožní:

Rozšířená nastavení. Kapitola 4

Vzdělávací program pro obchodní partnery společnosti ROCKWOOL průvodce školením

VYR-32 POKYNY PRO SPRÁVNOU VÝROBNÍ PRAXI - DOPLNĚK 6

Obsah. KAPITOLA 1 Dříve než začneme 19 Kdysi dávno aneb střípky z historie algoritmických strojů třicátá léta 22

Charakteristika kurzu BE4

Obsah. Úvodem 11 Komu je kniha určena 12 Co v knize najdete 12

Informace ÚIT pro studenty prvních ročníků.

Abeceda elektronického podpisu

Desetiminutový úklid 4 Třicetiminutový úklid 4 Hodinový úklid: 4 Úklid ve třech hodinách 5 Půldenní úklid 5

PROGRAMOVÁNÍ V C++ URČENO PRO VZDĚLÁVÁNÍ V AKREDITOVANÝCH STUDIJNÍCH PROGRAMECH ROSTISLAV FOJTÍK

AutoCAD Architecture 2008

Transkript:

Programování v jazyce C RNDr. Jan Lánský, Ph.D. Katedra softwarového inţenýrství MFF UK Katedra informatiky VŠFS (Autor původní verze slajdů: RNDr. Filip Zavoral, Ph.D.) zizelevak@gmail.com http://kocour.ms.mff.cuni.cz/~lansky/

Studijní povinnosti Zápočet aktivní účast na cvičeních během semestru 'domácí úkoly' (krátké prográmky) 2 povinné 2 dobrovolné (nejsou podmínkou zápočtu, ale lze je pouţít u zkoušky) Zkouška Musíte mě přesvědčit o vašich znalostech Ústní zkouška, diskuze nad zdrojovými kódy Zdrojové kódy musí být vlastní samostatnou tvorbou studenta Rozsah 1500 řádek na E, na lepší známky více IS studijní materiály PJC Priklady ke zkousce.doc 2

Obsah předmětu Programování v jazyce C ZS OOP (v C++) LS C C++ C C++ Nejdůleţitější: vlastní praxe Na přednáškách se nikdo nikdy programovat nenaučil 3

Přednáška Obsah přednášky Překlad programů, spojování Základní vlastnosti C a C++, odlišnosti od jiných prog. jazyků Datové typy, operátory a řídící konstrukce Pole a ukazatele Standardní knihovny Programování není zápis algoritmů Cvičení Praktické programování Microsoft Visual Studio.NET 2008 Ladění programů (!) Prosíím, já jsem napsal program a ono to řeklo 'Váš program provedl neplatnou instrukci a bude ukončen '. Co mám dělat? 4

Pascal vs. C++ Úvod do Programování, Programování heslo: programování = zápis algoritmů algoritmické myšlení, algoritmizace problému soustředění se na řešení problému formulace algoritmu a jeho zápis v nějakém formalismu (jazyku) základní datové a řídící struktury nedůleţité: kontrola vstupů, uţivatelské rozhraní, obedněnost, vazba na OS a HW, přenositelnost, optimalizace, udrţovatelnost výuka (v) Pascalu dobrý jazyk pro zápis algoritmů nezatěţuje technickými detaily (alokace paměti, vazba na OS,...) slabá podpora pro kontrolu vstupů, uţivatelské... 5

Pascal vs. C++ Programování v jazyce C++, OOP heslo: programování = vývoj software důleţité: kontrola vstupů, uţivatelské rozhraní, obedněnost, vazba na OS a HW, přenositelnost, optimalizace, udrţovatelnost zvládnutí knihoven a vývojových nástrojů 'Vše' jiţ bylo výuka (v) C++ naprogramováno standardní jazyk pro vývoj software další jazyky vycházejí z C++ (Java, C#,...) dobrá podpora pro kontrolu vstupů, uţivatelské... nutnost zvládnout technické detaily (alokace paměti, vazba na OS..) velké mnoţství hotového kódu (knihovny, komponenty,...) 6

Literatura Základní učebnice a popis jazyka Miroslav Virius: Programování v C++ (ČVUT, 2. vydání 2004) Miroslav Virius: Pasti a propasti jazyka C++ (Brno, 2. vydání 2005) Bjarne Stroustrup: The C++ Programming Language (3 rd ed.) Bruce Eckel: Myslíme v jazyku C++ (Thinkinkg in C++ 2 nd ed.) C++ In-depth aneb Jak správně C++ pouţívat - pro ty, kdo jiţ C++ nějak znají Scott Meyers: Effective C++ (2 nd ed.), More Effective C++ Herb Sutter: Exceptional C++, More Exceptional C++ Andrew Koenig, Barbara E. Moo: Accelerated C++ Practical Programming by Example Nicolai Josuttis: The C++ Standard Library A Tutorial and Reference James Coplien: Advanced C++ Programming Styles and Idioms Que: ANSI/ISO C++ Professional Programmer's Handbook Andrei Alexandrescu: Modern C++ Design Generic Programming and Design Patterns Applied Normy ISO/IEC 9899: Programming languages - C (1999) ISO/IEC 14882, ANSI: Programming languages - C++ (1998, 2003) 7

Nevhodná literatura - nepoužívat! Martin Beran: Učebnice Borland C++ - hrubé chyby Jan Pokorný: Rukověť uţivatele Borland C++ - staré, BC 3.1 Vladimír Rudolf: ABC programátora v C++ - neúplné, zastaralé Dirk Louis: C und C++ Programierung und Referenz - chyby Dalibor Kačmář: Jazyk C učebnice pro střední školy chyby Brodský, Skočovský: Operační systém Unix a jazyk C neúplné, zastaralé Eric Gunnerson: Začínáme programovat v C# C# není C++ 8

Historie 1970-73 první verze C, společný vývoj s UNIXem 1973 přepsání jádra UNIXu do C 1978 Kerninghan, Ritchie: The C Programming Language 1980 standardy ANSI X3J11, od r. 1999 ISO 9899 1980 AT&T - "C with Classes" 1983 poprvé název C++ (Rick Mascitti) 1985 Stroustrup: The C++ Programming Language 1989 ANSI X3J16 norma C++ 2003 nejnovější ISO/ANSI norma C++ Normy se vyvíjí, aktuální překladače o několik let zpět Implementace novinek často nekorektní nebo neefektivní (STL) 9

hello.c #include <stdio.h> #include <conio.h> int main( int argc, char ** argv) { printf( "Hello\n"); getch(); return 0; 10

hello.c direktiva preprocesoru vloţení souboru deklarace knihovních funkcí název funkce #include <stdio.h> #include <conio.h> hlavička funkce typ návratové hodnoty tělo funkce příkaz sloţené závorky BEGIN END int main( int argc, char ** argv) { printf( "Hello\n"); getch(); return 0; skutečné parametry volání funkce bez parametrů formální parametry 11

Struktura programu Program se skládá z modulů Překládány samostatně kompilátorem Spojovány linkerem Modul z pohledu programátora Soubor s příponou.cpp (.c) Hlavičkové soubory Soubory s příponou.h Deklarují (a někdy i definují) identifikátory pouţívané ve více modulech Vkládány do modulů direktivou include Direktivu zpracovává preprocesor čistě textově Preprocesor je integrován v kompilátoru jako první fáze překladu Modul z pohledu kompilátoru Samostatná jednotka překladu Výsledek práce preprocesoru 12

Překlad jednoho modulu a sestavení knihovní headery knihovny standardní i jiné.h.obj.obj.obj.obj.obj.lib spustitelný program.cpp CC.obj Link.exe kompilace objektový modul (přeloţený kód) spojování (linkování) 13

Oddělený překlad - dělení na moduly Modul - ucelená funkčí jednotka modul.cpp (.c) - implementace modul.h - definice rozhraní rozdělení projektu do modulů a vytváření headerů je umění, nedá se to naučit na přednášce fotbal.h hriste.h hrac.h mic.h fotbal.cpp hriste.cpp hrac.cpp mic.cpp 14

Překlad více modulů oddělený překlad vlastní headery knihovní headery knihovny.h.h.obj.obj.obj.obj.obj.lib.c CC.obj Link.exe kompilace jednoho modulu.c.c.c.obj.obj.obj další moduly 15

Překladače a vývojová prostředí Windows - překladač součástí integrovaného prostředí MS Visual Studio - Visual C++ (VC6.0,.Net,.Net2008) integrovaný make, linker, debugger raději nepouţívat klikabilní konfigurace další překladače - Borland C++ Builder, Intel, Watcom Unix (Linux) - samostatné programy, příkazová řádka gcc make - pro 'opravdové' programátory pokusy o vývojová prostředí (kdevelop) 16

Integrované vývojové prostředí.h.h.obj.obj.obj.obj.obj.lib.c.c.c.obj CC.obj.obj Link.exe editor projekt debugger 17

Make.h.h.obj.obj.obj.obj.obj.lib.c.c.c.obj CC.obj.obj Link.exe makefile make 18

Program a modul Program v C++ nemá (vnořovanou) blokovou strukturu Neexistuje "hlavní blok" Běh programu začíná vyvoláním funkce main Před funkcí main běţí inicializace běhového prostředí, po ní úklid Funkce main musí mít tuto hlavičku: int main( parametry příkazové řádky) Modul: posloupnost globálních deklarací a definic Deklarace Oznámení překladači, ţe identifikátor existuje Určení některých vlastností (typ, parametry) Definice Doplnění zbývajících vlastností (kód funkce, obsah struktury) Překladač vygeneruje kód funkce, vyhradí místo pro proměnnou 19

Funkce Základní programová jednotka je funkce Neexistují vnořené funkce Začátek programu funkce main hlavička funkce tělo funkce int fce1( int x, int y) { return x+y; int fce2( int a) { return fce1( 1, 2*a+5); int fce2( int a) { int fce1( int x, int y) { return x+y; vnořené funkce nelze! return fce1( 2*a+17); začátek programu int main( int argc, char** argv) {... argumenty z příkazové řádky později 20

Funkce - návratový typ Typ funkce = typ návratové hodnoty Hodnota se vrací pomocí klíčového slova return Speciální typ void - 'prázdný' typ ekvivalent procedury Pascalu typ funkce int fce1( int x, int y) { return x+y; návrat celočíselné hodnoty void fce2( char* text) { printf( text); void fce3( char* text) { if(! text) return; printf( text); návrat z funkce 21

Parametry funkce Pevný počet, pevný typ moţnost proměnného počtu parametrů - printf Parametry jsou odděleny čárkou U kaţdého parametru musí být uveden jeho typ Funkce bez parametrů - void kaţdý parametr musí mít typ int fce1( int x, int y, float z) {... int fce2( double a, char* str) {... int fce3( void) {... int fce4( int x, y) {... int fce5 {... 22

Volání funkce Shoda počtu formálních a skutečných parametrů Kompatibilita typů formálních a skutečných parametrů I funkce bez parametrů musí obsahovat operátor () Návratová hodnota - lze ignorovat int fce1( int x, int y, float z) {... int fce3( void) {... int fce2( int a) { fce1( a, 1, a); fce3(); return 0; int fce4( int x, int y, float z) {... int fce5( int a) { fce4; fce4( a, 1); fce4( a, 1, "ahoj"); 23

Lokální proměnné Definice lokálních proměnných C: na začátku těla funkce (přesněji: na začátku bloku) C++: kdekoliv v těle funkce Moţná inicializace při kaţdém běhu funkce neinicializovaná proměnná náhodná hodnota!!! int fce( void) { int x, y; int z = 0; return z + x; deklarace celočíselných proměnných deklarace s inicializací náhodná hodnota!!! 24

Příklad - malá násobilka definice knihovních funkcí inicializovaná celočíselná proměnná kontrola parametrů začátek cyklu konec cyklu hlavní program ignorování návratové hodnoty The END #include <stdio.h> int vynasob( int c) { int i = 1, v; if( c < 1 c > 10) return -1; while( i <= 10) { v = i * c; printf( "%d * %d = %d\n", i, c, v); i = i + 1; return 0; int main() { int cislo = 7; vynasob( cislo); return 0; hlavička funkce, formální parametr neinicializovaná proměnná okanţitý návrat z funkce 2 * 7 = 14 i++ konec, OK konec, OK volání funkce se skutečným parametrem 25

Předávání parametrů hodnotou Všechny parametry se předávají hodnotou 'Výstupní' parametry pouze přes ukazatele nebo reference void swap( int x, int y) { int pom; pom = x; x = y; y = pom; void fce( void) { int a = 1; int b = 2; int c = 0; swap( a, b); c = 2 * a + b; vymění se jen lokální proměnné funkce předají se pouze hodnoty (1, 2), nikoliv 'proměnné' 26

Globální proměnné Definice mimo tělo funkce Viditelné v jakékoliv funkci Moţná inicializace při startu programu Pouţívat s rozvahou!! pouze pro sdílená data lokální proměnná globální proměnná int g = 1; void fce( int x) { int z = 2; g = g + z * x; formální parametr co vrátí main?? int main( void) { fce( 2); fce( 3); return g; skutečný parametr 27

Výraz Norma: "Výraz je posloupnost operací a operátorů specifikující výpočet hodnoty" Přiřazovací 'příkaz' je také výraz jeho hodnotou je přiřazovaná hodnota Výrazy mohou mít vedlejší efekty 1 a+b*sin(x) printf( "Ahoj") q = &b[17]+*p++ "retezec" a = b = 0; if( (x = fnc())!= 0)... uţitečné: test přiřazované hodnoty 28

Příkaz Příkaz je výraz ukončený ';' (středníkem) sloţený příkaz - posloupnost příkazů mezi '{' a '' programová konstrukce if, if-else, switch, while, do-while, for, break, continue, return, goto 1; a+b*sin(x); printf( "Ahoj"); q = &b[17]+*p++; "retezec"; { 1; a+b*sin(x); printf( "Ahoj"); q = &b[17]+*p++; "retezec"; jeden sloţený příkaz 29

Podmíněný příkaz if (výraz) příkaz if (výraz) příkaz else příkaz if( a > 1) printf( "OK"); if( a > 1) printf( "OK"); else printf( "nee"); syntakticky špatně syntakticky správně, ale dělá něco jiného if( a > 1) b = 0; printf( "OK"); if( a > 1) b = 0; printf( "OK"); else printf( "nee"); if( a > 1) { b = 0; printf( "OK"); else { printf( "nee"); if( a > 1) { b = 0; printf( "OK"); else { printf( "nee"); 30

Vnořené podmíněné příkazy Syntakticky správně, ale nepřehledné Na pohled nejasné párování if( a > 1) if( b > 0) printf( "OK"); else printf( "nee"); U vnořených podmínek vţdy pouţívat { if( a > 1) { if( b > 0) printf( "OK"); else { printf( "nee"); if( a > 1) { if( b > 0) printf( "OK"); else printf( "nee"); 31

Vícenásobné větvení konstrukce switch celočíselný výraz switch (výraz) { case konstanta: posloupnost příkazů break; case konstanta: case konstanta: posloupnost příkazů break; default: posloupnost příkazů pokud výraz není roven ţádné z konstant ukončení větve switch( errc) { case 0: b = 0; printf( "OK"); break; case -1: printf( "trochu spatne"); break; case -2: case -3: printf( "hodne spatne"); break; default: printf( "jina chyba"); break; interval nelze zapomenutý break syntakticky OK, ale dělá něco jiného switch( errc) { case 0: b = 0; printf( "OK"); case -1: printf( "spatne"); break; switch( ch) { case '0'..'9': x += ch - '0'; break; case 'A'..'F': x += ch - 'A'; break; 32

Cyklus konstrukce while a do-while while (výraz) příkaz do příkaz while (výraz) ; podmínka na začátku podmínka na konci Pozor! cyklus pokračuje pokud je podmínka platná while( a > 1) a = a / 2; tělo se vţdy alespoň jednou provede while( a > 1) { fce( a); a = a / 2; do { fce( a); a = a / 2; while( a > 1); 33

Cyklus konstrukce for inicializace podmínka inkrement tělo cyklu for (výraz1 ; výraz2 ; výraz3 ) příkaz je ekvivalentem výraz1; while (výraz2 ) { příkaz výraz3 ; jako inicializaci, podmínku i inkrement lze libovolný výraz FOR I := 0 TO 9 DO FCE(I) ekvivalent v jiném jazyce for( i=0; i<=9; i=i+1) { fce( i); i=0; while( i<=9) { fce( i); i=i+1; for( init(a); i<9 && a[i] >0; a[i++]=i*2) { fce( i); for v C++: obecnější, širší moţnosti pouţití 34

Ukončení cyklu - break, continue break okamţité ukončení celého cyklu cyklus s podmínkou uprostřed ošetření chybových stavů continue ukončení (jednoho) běhu těla cyklu for(;;) { errc = fce(); if( errc < 0) break; jinafce(); n = 1; while( n<1000) { val = get(); if( val == 0) continue; n = n * val; 35

Goto Nepoužívat!... pokud k tomu není dobrý důvod Kdyţ uţ, tak pouze dopředu (skok dozadu = cyklus) Dobrý důvod: výskok z vícenásobně vnořených cyklů label návěští for( i=0; i<10; i++) { for( j=0; j<10; j++) { if( fnc( i, j) == ERROR) goto konec_obou_cyklu; konec_obou_cyklu: dalsi_funkce(); nelze break - ukončil by pouze vnitřní cyklus, vnější cyklus by pokračoval 36

Celočíselné typy Základní celočíselné typy jsou znaménkové Pro kaţdý typ existuje unsigned varianta moţné vyuţití unsigned: unsigned char, pole bitů, modulová aritmetika pokud není dobrý důvod, unsigned raději nepouţívat char short int long long long size_t, ptrdiff_t, wchar_t typ 8 bit 16 bit 32 bit 64 bit char 8 8 8 8 short 8 / 16 16 16 16 / 32 int 16 16 32 32 long 16 32 32 32 / 64 long long - - 64 64-2GB.. +2GB 37

Logické a znakové hodnoty a typy C: Aţ do r. 1999: neexistuje typ 'boolean' Porovnání a logické operátory jsou celočíselné výrazy FALSE (nepravda) 0 TRUE (pravda) 1 (libovolná hodnota různá od 0) důsledek: if( x!= 0) if( x) if( x == 0) if(!x) C++, C99 celočíselný typ bool (C99: _Bool) hodnoty true (=1), false (=0) char časté pouţití: test (ne)nulovosti např. ukazatelů norma neurčuje signed / unsigned korektní porovnání na nerovnost pouze 0.. 127 'a' < 'ţ'? záleţí na implementaci většinou char = signed signed char -128.. 127 40 > 200!!! unsigned char 0.. 255 - 'byte' 200-56 wchar_t stddef.h: znak rozšířené sady (Unicode) 38

Výčtový typ enum pohlavi { p_muz, p_zena ; pohlavi p = p_muz; int pp = p_zena; pohlavi q = 0; C: celočíselné konstanty - OK C++: samostatný typ - nelze hodnoty doplní překladač (od 0) enum flags { f1 = 1, f2 = 2, f3 = 4, f4 = 8 ; if( x & f1)... test bitů explicitní hodnoty enum porty { pop3 = 111, ftp = 21, smtp = 80 ; 39

'Reálné' typy float double long double Pozor! Reálné výpočty jsou vţdy nepřesné malá přesnost - nepouţívat! zvýšená přesnost standard pro 'reálné' výpočty double x = 1; double y = x / 3; if( x == 3 * y) printf( "Presne"); else printf( "Nepresne"); raději nepouţívat pouze pro fyzikální nebo numerické veličiny double zustatek = 15.60; long zustatek_v_halerich = 1560; pro přesné hodnoty pouţívejte přesné typy 40

Celočíselné konverze Automatické konverze (integral promotions) Výpočty výrazů a předávání parametrů vţdy v šíři alespoň int signed char, unsigned char, signed short signed int unsigned short signed int (pokud je int delší) / unsigned int vţdy kdyţ je pouţit menší typ neţ int Automatické konverze u binárních operací signed int unsigned int signed long unsigned long float double long double při nestejných operandech 41

Přehled operátorů, asociativita a priorita postfix prefix ++ -- ( ) [ ] ->. :: ++ --! ~ + - & * sizeof ( ) new delete post-in/de-krementace volání funkce index přístup k poloţce struktury kvalifikace identifikátoru pre-in/de-krementace booleovská a bitová negace unární +/- reference, dereference měření velikosti přetypování dynamická alokace dynamická dealokace L.* ->* dereference member-ptru L * / % multiplikativní operátory L + - aditivní operátory L << >> bitové posuny L < <= > >= L ==!= L & L ^ L L && L L? : P = *= /= %= += -= &= ^= = <<= >>= L, uspořádání rovnosti bitové AND bitové XOR bitové OR booleovské AND booleovské OR podmíněný výraz přiřazení kombinované přiřazení sekvence 42

Základní aritmetické operátory + - * / % podle typu operandů automatická konverze na větší typ % - modulo int x=5, y=3; celočíselné dělení reálné dělení double a=5, b=3; x / y 1 x / b 1.666 x % y 2 x % b Error a / b 1.666 a / y 1.666 modulo je pouze celočíselná operace a % b Error a % y Error 43

Bitové a logické operátory & ^ ~ - bitové operace AND, OR, XOR, NOT &&! - logické operace AND, OR, NOT 5 = 0101 2 3 = 0011 2 1 = 0001 2 7 = 0111 2 9 = 1001 2 15 = 1111 2 10 = 1010 2 5 & 3 1 5 && 3 1 5 3 7 5 3 1 5 ^ 3 6 5 ^^ 3 Error 5 ^ 15 10 5 & 0 0 5 && 0 0 5 0 5 5 0 1 oba op. 0 alespoň jeden operand 0 neexistuje alespoň jeden operand = 0 44

Zkrácené vyhodnocování, relační operátory a && b - je-li a=0, b se nevyhodnocuje, výsledek = false (0) a b - je-li a=1, b se nevyhodnocuje, výsledek = true (1) int x[10]; // pole 0..9 if( i < 10 && x[i]!= 0) y = y / x[i]; test mezí pole před přístupem k prvku pole if( x==y && *x++)... Pozor! operátory s vedlejšími efekty se nemusí provést! < <= >= > ==!= výraz typu int (bool) - výsledek vţdy 0 nebo 1 (false, true) porovnávání na (ne)rovnost float/double! porovnání vs. přiřazení! POZOR!!! Přiřazení! (zde hodnota vţdy = 1) if( x = 1)... 45

Přiřazení, inkrementace, bitový posun = += -= *= /= %= &= = ^= <<= >>= kombinované přiřazení a op= b a = a op b i += 2; x[ i+=1] /= 3; ++ -- a++ a = a + 1, výsledkem je stará hodnota a ++a a = a + 1, výsledkem je nová hodnota a přesněji: a++ (tmp = a, a = a + 1, tmp) int sum = 0; int i, x[10];... for( i=0; i<9; sum += x[i++]) ; << >> bitový posun C++ - časté pouţití pro jiné účely (streams) - přetěţování pozor - vţdy si uvědomit, zda jde o pre- nebo post- inkrementaci 46

Podmíněný výraz, sekvence a? b : c ternární operátor po vyhodnocení podmínky a se vyhodnotí buď b (je-li a!= 0) nebo c (je-li a == 0) x = (y>0? y : 0); a, b operátor sekvence ('zapomnění') po úplném vyhodnocení a se vyhodnotí b x = (tmp = y, y = y + 1, tmp); ekvivalent x = y++; 47

Pravidla vyhodnocování a( b,c) vedlejší efekty parametrů jsou vyhodnoceny před zavoláním fce a && b je-li a nulový, b se nevyhodnocuje a b je-li a nenulový, b se nevyhodnocuje a? b : c po vyhodnocení a se vyhodnotí buď b nebo c a, b po úplném vyhodnocení a se vyhodnotí b Ţádná další pravidla nejsou ostatní operátory jsou vyhodnocovány v libovolném pořadí vedlejší efekty se mohou projevit kdykoliv během výpočtu i = 0; p[ i++] = i++; moţné výsledky: p[0] = 0; p[1] = 0; p[0] = 1; 48

Fungující triky vs. chyby Fungující triky Test ukazatele while ( p && p->v < v ) p = p->next; Volání funkce s vedlejším efektem while ( (c = getchar())!= EOF && c!= '\n' ); Kopie řetězce while ( *a++ = *b++ ); Chyby Vícenásobný výskyt modifikované proměnné p[ i++] = i++; nevím, jestli se provede Nadbytečné volání funkce s vedlejším efektem if ( getchar() == 'A' && getchar() == 'B' ) 49

Pole Indexy polí vţdy začínají od 0! Při přístupu se nikdy nekontrolují meze!!! Deklarace: t x[n] - pole x o n prvcích (0..n-1) typu t Přepis náhodného místa v paměti! Nepředvídatelné následky!! int x[5]; for( i=1; i <=5; i++) x[i] = i; 0 1 2 3 4???? 1 2 3 4 5 Vícerozměrné pole je pole polí Deklarace: t x[m][n]; Přístup: x[m][n] = a; význam: m-prvkové pole typu (n-prvkové pole typu t) int x[8][8]; for( i=0; i < 8; i++) for( j=0; j < 8; j++) x[ i ] [ j ] = i * j; Pozor! x[m,n] není prvek dvojrozměrného pole o souřadnicích m a n čárka = operátor sekvence 50

Inicializace pole Při deklaraci pole lze obsah pole inicializovat Nejde o přiřazení, lze pouze při deklaraci Deklarace inicializovaného pole nemusí obsahovat velikost překladač dopočítá z inicializace u vícerozměrných polí pouze "vnější" rozměr Při nesouhlasu velkosti pole a počtu inicializátorů velikost > inicializátory: inicializace začátku, obsah zbytku nedefinován velikost < inicializátory: kompilační chyba (Too many initializers) int cisla[] = { 1, 2, 3, 4 ; char* jmena[] = { "Josef", "Karel", "Jana" ; int matice[][3] = { { 11, 12, 13, { 21, 22, 23 ; 51

Ukazatele Co to je proměnná? místo v paměti, typ (-> velikost), hodnota hodnota se dá číst a většinou i zapisovat je nějak velká (typ) někde bydlí 1 má hodnotu Co to je ukazatel (pointer)? něco, čím si můţu ukazovat na proměnnou (nebo na jiné paměťové místo pole, poloţka struktury, dynamická alokace) K čemu jsou ukazatele dobré: zpracování řetězců, dynamické datové struktury, předávání parametrů odkazem, práce s buffery,... Pro C++ je práce s ukazateli typická 52

Ukazatele Deklarace: t x proměnná x typu t t *p - ukazatel p na typ t p: Operátor reference: p = &x Operátor dereference: x = *p Neinicializovaný ukazatel vs. nulový ukazatel C: #define NULL 0 C++: 0 x: 17 53

Ukazatele - příklad int x = 1, y = 3; int * px, * py; *px = 5; py = NULL; *py = 7; if(! py) etwas(); px = &x; py = &y; (*py)++; px = py; y = x; py = &x; *py = 9; přepsání náhodného místa v paměti? 5 x: 1 :px y: 3 :py? jaký zde bude obsah x a y? 54

Ukazatele - příklad int x = 1, y = 3; int * px, * py; *px = 5; py = NULL; *py = 7; if(! py) etwas(); px = &x; py = &y; (*py)++; px = py; y = x; py = &x; *py = 9; umoţní test x: 1 :px y: 3 :py 0: 7 typicky 'segmentation fault' váš program bude ukončen pro pokus o porušení ochrany paměti 55

Ukazatele - příklad int x = 1, y = 3; int * px, * py; *px = 5; py = NULL; *py = 7; if(! py) etwas(); px = &x; py = &y; (*py)++; px = py; y = x; py = &x; *py = 9; Pozor na prioritu! *py++ *(py++) x: 1 :px y: 3 :py x: 1 :px y: 4 :py přístup k hodnotě proměnné přes ukazatel 56

Ukazatele - příklad int x = 1, y = 3; int * px, * py; *px = 5; py = NULL; *py = 7; if(! py) etwas(); px = &x; py = &y; (*py)++; px = py; y = x; py = &x; *py = 9; x: 1 :px y: 1 :py x: 9 :px jaký zde bude obsah x a y? y: 1 :py 57

Pole a ukazatele, aritmetika ukazatelů int a[5]; int *p; a[2] = 20; p = &a[2]; a[0] = *p - 15; p++; *p = 30; a 0 1 2 3 4?? 20?? p reference na prvek pole 5? 20 30? p inkrementace ukazatele posun na daší prvek 58

Pole a ukazatele, aritmetika ukazatelů p = &a[1]; *(p+3) = 40; 5? 20 30 40 p přičtení čísla k ukazateli posun o n prvků Operátor [] p[i] *(p+i) &p[i] p+i a &a[0] indexování pole (ukazatele) je jen jiný zápis přístupu přes ukazatel identifikátor pole je ukazatel na svůj nultý prvek Automatické konverze pole-ukazatel Je-li výraz typu pole na místě, kde typ pole nemůţe být, automaticky se konvertuje na ukazatel na nultý prvek tohoto pole. Pole nelze přiřazovat ani předávat hodnotou (ukazatel na nultý prvek) p = a je ekvivalentní p = &a[0] 59

Pole a ukazatele, aritmetika ukazatelů int a[5]; int *p; 0 10 20 30 40 p = &a[0]; p = a; *p = a[1]; *(p+2) = a[2] 1; p = a + 2; p[1] = *(a+1); a[3] = p[2]; *(a+2) = p[-1]; 3[a] = 2[p]; nekompatibilní typy nestejná úroveň indirekce a[4] = p + 1; p = a[0]; p[1] = a; a = p + 2; identifikátor pole je konstantní nelze do něj přiřazovat p[i] *(p+i) *(i+p) i[p] 60

Řetězce Jazyk C++ nezná pojem řetězec (!) konvence, knihovny Řetězec je pole znaků (char) zakončené nulou Kaţdý řetězec musí být vždy ukončen nulou "Ahoj" 'A' 'h' 'o' 'j' '\0' char buffer[4]; strcpy( buffer, "Ahoj"); 'A' 'h' 'o' 'j' '\0' '\0' = 0 pozor na uvozovky a apostrofy! vţdy myslet na koncovou nulu! X 'X' "X" proměnná znaková konstanta - celočíselná hodnota řetězec - ukazatel kdyţ chcete říct mezera, napište mezeru (' ') ať vás ani nenapadne napsat 32 přestoţe to na VAŠEM počítačí funguje kód znaku v pouţitém kódování (ASCII, CP1250, ISO08859-2, EBCDIC,...) 61

'Řetězcové proměnné' Inicializované pole (konstantní ukazatel) s1++ nelze! char s1[] = "Uno"; const char *s2 = "Due"; s1: s2: 'U' 'n' 'o' '\0' Inicializovaná proměnná typu ukazatel s2++ se přesune na další znak 'D' 'u' 'e' '\0' anonymní globální proměnná const char[] 62

Řetězce knihovní funkce, délka řetězce v C neexistují 'řetězcové operace' (C++: třída string) přiřazení, zřetězení, porovnání, podřetězec,... vše standardní knihovní funkce #include <string.h> int strlen( const char* s); deklarace řetězcových funkcí počet znaků (bez koncové nuly) char pole[8] = "Ahoj"; x = strlen( pole); // 4 inicializované pole typu char skutečný počet znaků (4) nikoliv velikost pole pole: A h o j \0??? 63

Délka řetězce různé způsoby implementace přístup přes index podmínka for cyklu můţe být libovolná int strlen ( const char* s) { int i = 0; while ( s[i]!= '\0') { i++; return i; int i = 0; while ( *s!= '\0') { i++; s++; return i; přístup přes ukazatel více inkrementací prázdné tělo nezapomenout na ';'!! sloţitější podmínka: test nenulovosti inkrementace ukazatele while(a!=0) while(a) podmínka je splněna pokud je nenulová rozdíl ukazatelů = počet prvků mezi nimi pozor na ± 1! for( i=0; *s!= '\0'; i++) s++; for( i=0; *s!= '\0'; i++, s++) ; int i=0; while ( *s++!= '\0') i++; int i=0; while ( *s++) i++; char *p = s; while (*p++) ; return p-s-1; 64

Řetězce - kopírování char* strcpy( char* d, const char* s); char buf[8]; char pozdrav[] = "Ahoj"; strcpy( buf, pozdrav); zkopíruje obsah s do místa začínajího od d kopíruje pouze do koncové '\0' buf pozdrav A h o j \0??? A h o j \0 65

Řetězce chyby při kopírování char buf[6]; char pozdrav[] = "Dobry den"; strcpy( buf, pozdrav); vţdy pozor na dostatek místa funkce nic nekontroluje!!! váš program provedl... buf pozdrav D o b r y d e n \0 D o b r y d e n \0 char *ptr; char pozdrav[] = "Ahoj"; strcpy( ptr, pozdrav); ptr neinicializovaný!!! kopírování na neinicializovaný ukazatel!!! váš program provedl... ptr pozdrav? A h o j \0 A h o j \0 66

Řetězce zřetězení, vyhledávání char* strcat( char* d, const char* s); char* strchr( const char* s1, int c); char* strstr( const char* s1, const char* s2); připojí s za d vyhledá první pozici c v s1 vyhledá podřetězec s2 v s1 char buf[10]; char* bp; strcpy( buf, "Ahoj"); strcat( buf, "Babi"); bp = strstr( buf, "oj"); po strcpy po strcat A h o j \0????? A h o j B a b i \0? pozor na dostatek místa! buf A h o j B a b i \0? bp 67

Řetězce porovnávání a další funkce int strcmp( const char* s1, const char* s2); s1 < s2-1 s1 = s2 0 co znamená 's1 < s2'? s1 > s2 +1 lexikografické uspořádání (jako ve slovníku) výsledek podle prvního rozdílného znaku A B C E = = = A B C D E další řetězcové funkce: strncat, strncmp, strncpy strrchr Find last occurrence of given character in string strpbrk Find first occurrence of character from one string in another string strspn Find first substring from one string in another string strtok Find next token in string sprintf Write formatted data to a string 68

Funkce printf int printf( const char *format [, argument]... ) Vytiskne na standardní výstup text definovaný formátovacím řetězcem Formátovací řetězec určuje počet a typy dalších parametrů (symbolem %) Výjimka z pravidla, ţe funkce v C má přesně daný počet a typy parametrů. Kompilátor nemá moţnost ověřit zda parametry jsou správné časté pády programu Vrací počet skutečně vytisknutých znaků %s řetězec %d, %i celé číslo %c znak %f reálné číslo %08d zarovná na 8 míst, doplní 0 %5.2f zarovná na 5 míst, 2 desetinná místa \n odřádkuje \t tabulátor \\ \ (cesta k souborům) #include <stdio.h> double r = 2.6; int c = 65; char * buf = "Ahoj"; printf ("Soucet cisel %d + %.2f = %.2f \n", 7, r, r + 7); printf ("Retezec %s zacina na %c \n", buf, buf[0]); printf ("ASCII kód znaku %c je %i \n", c, c); printf ("%s", r); printf ("%i + %i = %i", c, c); 69

Parametry příkazové řádky C:\> myprog.exe -n -w a.txt b.txt int main( int argc, char** argv) pole řetězců (ukazatelů na char) argv 0 argc 5 b. t x t \0 Počet parametrů včetně názvu programu! = počet ukazatelů v argv - w \0 a. t x t \0 - n \0 m y p r o g. e x e \0 70

Zpracování příkazové řádky výpis parametrů C:\> myprog.exe -n -w a.txt b.txt int main( int argc, char** argv) { while( *argv) { printf( "%s\n", *argv); argv++; myprog.exe -n -w a.txt b.txt posun na další parametr výstup řetězce a odřádkování 71

Zpracování příkazové řádky int main( int argc, char** argv) { while( *argv) { printf( "%s\n", *argv); argv++; argv[4] argv[4][1] *argv argv[0] typ: char* argv typ: char** 0 b. t x t \0 a. t x t \0 - w \0 - n \0 argv m y p r o g. e x e \0 **argv argv[0][0] typ: char 72

Zpracování příkazové řádky int main( int argc, char** argv) { while( *argv) { printf( "%s\n", *argv); argv++; 0 b. t x t \0 argv++ a. t x t \0 - w \0 - n \0 **argv argv m y p r o g. e x e \0 73

Zpracování příkazové řádky int main( int argc, char** argv) { while( *argv) { printf( "%s\n", *argv); argv++; 0 b. t x t \0 *argv == 0 a. t x t \0 argv - w \0 - n \0 m y p r o g. e x e \0 74

Zpracování příkazové řádky usage: myprog [-n] [-w] filea fileb int main( int argc, char** argv) { int n=0, w=0; while( *++argv && **argv=='-') { switch( argv[0][1]) { case 'n': n = 1; break; case 'w': w = 1; break; default: error(); if(!argv[0]!argv[1]) error(); doit( argv[0], argv[1], n, w); return 0; options nastavení přepínače zbývající parametry 0 b. t x t \0 a. t x t \0 výkonná funkce argv - w \0 - n \0 p r g. e x e 75 \0

Dynamická alokace paměti C: standardní knihovny <malloc.h> void* malloc( int size); void free( void* p); Velikost datového typu sizeof(char) = 1 vţdy C++: součást jazyka (podrobně později) new T new T[ n] delete p delete[] p int * pole; pole = malloc(20 * sizeof(int)); C++ nutnost přetypování s = (char*) malloc( 20); lépe new char* s; s = malloc( 20); if(! s) error(); strcpy( s, "ahoj"); *s = 'X'; vţdy ověřit!!! váš program provedl... s: X h o j \0 76

Velikost pole určena za běhu programu int main( int argc, char** argv) { char* buf;... buf = malloc( strlen(argv[1]) + strlen(argv[2]) + 1))); if(! buf) error(); strcpy( buf, argv[1]); strcat( buf, argv[2]); spočítá potřebnou velikost ze vstupních parametrů pozor na koncovou '\0' 77

Organizace paměti procesu IP R0 R1... SP Kódový segment Kód programu Datový segment Heap Globální proměnné Dynamicky alokovaná data Zásobník Lokální proměnné a parametry funkcí 78

Organizace paměti procesu kódový segment IP R0 R1... SP Kódový segment Připraven kompilátorem součást spustitelného souboru Kód uţivatelských i knihovních funkcí Obvykle chráněn proti zápisu Datový segment Heap Zásobník int fce( void) {... { int (*fp)( void); fp = fce;... 79

Organizace paměti procesu datový segment IP R0 R1... SP Kódový segment Datový segment Heap Připraven kompilátorem součást spustitelného souboru Explicitně nebo implicitně (nulami) inicializované globální proměnné Řetězcové konstanty Data knihoven Zásobník int bigpole[ 1000]; { int* p = bigpole; char* s = "ahoj";... 80

Organizace paměti procesu - heap IP R0 R1... SP Kódový segment Datový segment Heap Vytvářen startovacím modulem knihoven Neinicializovaná dynamicky alokovaná data malloc/free ( C++: new/delete ) Obsazené bloky různé velikosti Zásobník + seznam volných bloků { char* s; s = malloc( 256);... 81

Organizace paměti procesu - zásobník IP R0 R1... SP Kódový segment Datový segment Heap Zásobník Připraven operačním systémem Lokální proměnné Pomocné proměnné generované kompilátorem Návratové adresy Aktivační záznamy funkcí { char pole[100]; char s[] = "Ahoj"; int x = 1 + 2 * 3;... 82

Statické proměnné globální proměnná neviditelná z jiných modulů C++: lepší řešení - namespace static int x; int fce( int a) { static int y = 0; return y += a; de facto globální (!) proměnná neviditelná z jiných funkcí inicializace: C: před vstupem do main C++: před prvním průchodem C++: raději skrýt do třídy 83

Organizace paměti procesu příklad const int max = 100; char buf[max]; co je v kterém segmentu? char* prefix( char* s) { static int n = 0; char* p = malloc( strlen( s) + 2); *p = '#'; strcpy( p + 1, s); return p; int main( int argc, char** argv) { char* p; strcpy( buf, argv[ argc 1]); p = prefix( buf); p = prefix( p);... 84

Struktury struct osoba { char jmeno[20]; char prijemni[30]; int rok_narozeni; int pohlavi; ; osoba os, *po, zam[20]; osoba beda = { "Béda", "Trávníček", 1980, p_muz ; definice struktury poloţky struktury struktura, ukazatel na strukturu, pole struktur strcpy( os.jmeno, "Venca"); zam[3].rok_narozeni = 1968; po = &zam[3]; po->pohlavi = p_muz; definice proměnné typu struktura s inicializací přístup k poloţkám (*x).y x->y 85

Typové kostrukce - přehled A x[ n] A x[] A * x pole n prvků typu A, n je konstantní výraz pole neznámého počtu prvků typu A (pouze v některých kontextech) ukazatel na typ A void * x ukazatel na neurčený typ *x ++x nelze A const * x const A * x ukazatel na konstantní hodnotu typu A ++x lze ++*x nelze A * const x konstantní ukazatel na typ A ++x nelze ++*x lze A & x A const & x const A & x A x() A x( par) A x( void) C++: reference na typ A C++: reference na konstantní hodnotu typu A funkce vracející typ A - C: bez určení parametrů, C++: bez parametrů funkce s určenými parametry funkce bez parametrů void x( par) funkce bez návratové hodnoty (procedura) 86

Kombinace typových kostrukcí A * x[10] pole ukazatelů A (* x)[10] ukazatel na pole A * x() funkce vracející ukazatel A (* x)() ukazatel na funkci A x[10]() pole funkcí - zakázáno A (* x[10])() pole ukazatelů na funkci A x()[10] funkce vracející pole - zakázáno A (* x())[10] funkce vracející ukazatel na pole typicky se nepouţívá pole = ukazatel na 1. prvek čtení deklarací: od identifikátoru doprava, aţ to nepůjde, tak doleva 87

Kombinace typových kostrukcí - příklad int*(*pf[10])(void); int*(*maso(int*(*p1)(void),int*(*p2)(void)))(void); co to je za maso??? 88

Kombinace typových kostrukcí - typedef int*(*pf[10])(void); int*(*maso(int*(*p1)(void),int*(*p2)(void)))(void); typedef int* fce( void); fce * pf [10]; fce * maso( fce* p1, fce* p2); pouţitím typedef se můţe výrazně zpřehlednit kód 89

Souborový vstup a výstup FILE * deskriptor souboru - deklaruje programátor FILE Neznámý obsah Pro knihovní funkce struktura definovaná v <stdio.h> Otevření souboru: kontrola existence a práv vytvoření vnitřních knihovních struktur asociace s otevřeným souborem předání deskriptoru souboru (FILE*) OS soubor (na disku) 90

Práce se soubory typ 'soubor' (ukazatel na strukturu) #include <stdio.h> FILE* fp; int c; if(!(fp = fopen("c:\\f.txt", "r"))) error(); while( (c = getc( fp))!= EOF) putchar( c); fclose( fp); otevření souboru pozor na '\\'!!! zavření souboru čtení ze souboru 91

Otevření souboru FILE* fopen( const char* fname, const char* mode); r open file for reading w truncate to zero length or create file for writing a append; open or create file for writing at end-of-file r+ open file for update (reading and writing) w+ truncate to zero length or create file for update a+ append; open or create f. for upd., writing at end-of-file rb binary file... mode soubor ex. soubor neex. seek r R Error 0 w Del, W W 0 w: soubor se smaţe +: vţdy čtení i zápis a W W End r+ R/W Error 0 w+ Del, R/W R/W 0 a+ R/W R/W End r: soubor musí existovat a: otevřít na konci 92

Textové vs. binární soubory Textový soubor konverze konců řádek ('\n') na platformově závislou vnější reprezentaci typicky 0x0D 0x0A (Win) nebo 0x0A (Unix) konverze je automatická, programátor se o to nemusí starat vhodné pro ukládání lidsky čitelných dat getc/putc, fgets/fputs, fprintf,... chování fseek/ftell na '\n' nedefinován - nepouţívat Binární soubor ţádné konverze se neprovádí v souboru je přesný binární obraz zapisovaných dat vhodné pro ukládání vnitřních datových struktur lidsky přímo nečitelné typicky fread/fwrite, lze i getc/putc (přístup po bajtech) fseek/ftell OK 93

Funkce pro práci se soubory FILE* fopen( const char* fname, const char* mode); int fclose( FILE* fp); int fprintf( FILE* fp, const char* format,...); int getc( FILE* fp); int putc( int c, FILE* fp); char* fgets( char* buffer, int limit, FILE* fp); int fputs( const char* buffer, FILE* fp); Zjištění velikosti souboru: fseek( fp, 0, SEEK_END); size = ftell( fp); int fread( void* ptr, int size, int n, FILE* fp); int fwrite( const void* ptr, int size, int n, FILE* fp); long ftell( FILE* fp); int fseek( FILE* fp, long offset, int whence); whence: SEEK_SET, SEEK_CUR, SEEK_END 94

Souborový vs. standardní v/v funkce pro práci se standardním vstupem/výstupem int getchar( void); int putchar( int c); int printf( const char* format,...); char* gets( char* buffer); standardní vstup/výstup FILE* stand. otevřený na čtení/zápis před vstupem do main FILE *stdin; FILE *stdout; getchar() getc(stdin) putchar(c) putc(c, stdout) Nepouţívat! Nelze ohlídat přetečení bufferu všechny souborové funkce lze pouţít i pro std. v/v FILE* fp = stdout; if(...) fp = fopen( "...", "r"); c = getc( fp); jednotný zápis na std výstup nebo do souboru 95

Základní knihovní (neobjektové) funkce <string.h> <cstring> strlen, strcmp, strcpy, strncpy, strcat, strchr, strstr, memset, memcmp, memcpy, memchr <stdio.h> <cstdio> getchar, putchar, fopen, fclose, getc, putc, fgets, fputs, fread, fwrite, ftell, fseek, printf, fprintf, vfprintf, fflush, ungetc FILE, stdin, stdout, EOF, SEEK_SET,... <stdlib.h> <cstdlib> malloc, free, atoi, atof, strtol, qsort, rand, exit <ctype.h> <cctype> isalpha, isdigit, isxdigit, isalnum, isspace, ispunct, iscntrl, islower, isupper, tolower, toupper <math.h> <cmath> abs, floor, sin, sqrt, exp, exp, log,... <time.h> <ctime>... a mnoho mnoho dalších time, gmtime, strftime, asctime, clock,... 96

Typy znaků <ctype.h> <cctype> Funkce vrací 0 nebo 1, podle toho zda zadaný znak je daného typu Parametrem funkce je jednotlivý ZNAK, ne celý řetězec isdigit číslice (0,..., 9) isxdigit hexadecimální číslice (0,..., 9, a,..., f, A,..., F) isalnum číslice nebo písmeno (0,..., 9, a,..., z, A,..., Z) isspace bílé znaky (mezera, tabulátor, konec řádku,...) ispunct interpunkční znaménka (?,!,.,...) iscntrl netisknutelné řídící znaky Problém v C: české znaky, isalpha písmeno (a,..., z, A,..., Z) ale i jiné diaktické znaky islower malé písmeno (a,..., z) isupper velké písmeno (A,..., Z) tolower k zadanému písmenu vrací příslušné malé písmeno toupper k zadanému písmenu vrací příslušné velké písmeno 97

Funkce qsort #include <stdio.h> #include <stdlib.h> #include <string.h> int compare( const void *arg1, const void *arg2 ) { return _stricmp( * ( char** ) arg1, * ( char** ) arg2 ); Ignore case void main( int argc, char **argv ) { int i; argv++; argc--; Uţivatelsky napsaná třídící funkce. Návratové hodnoty 0, < 0, a > 0. Parametry: pole k setřídění, počet prvků pole, velikost 1 prvku, porovánací funkce qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare ); for( i = 0; i < argc; ++i ) printf( "%s ", argv[i] ); printf( "\n" ); 98

Direktivy preprocesoru #include <stdio.h> #include <cstdio> #include <iostream> #include "mymodul.h" #define KZR #define KZR 17 #define KZR( pzr) ((pzr) * 2) #undef #ifdef #ifndef #if #else #endif # ## knihovní headery C, C dle nových konvencí, C++ uţivatelské headery definice symbolu viz slajd Spojování modulů - #ifndef definice makra, lépe const int kzr = 17; definice parametrického makra raději vůbec nepouţívat, lépe inline funkce test na (ne)definovanost symbolu obrana před vícenásobným #include viz slajd Spojování modulů - #ifndef test konstantního výrazu - #if sizeof( int) == 4 'ouvozovkování' - #abc "abc" spojení identifikátorů - a##b ab 99

Spojování modulů problém x.c double A() { return B( 7); y.c double B() { return 3.14; error: Undefined 'B' 100

Spojování modulů externí deklarace x.c double B(); double A() { return B(); externí deklarace y.c double B() { return 3.14; 101

Spojování modulů nekonzistence x.c double B(); double A() { return B(); nekonzistence funkce B (počet a typy parametrů, návratová hodnota) y.c int B( int q) { return q+1; x.obj import B export A app.exe y.obj export B C: nedefinované chování C++: linker error 102

Spojování modulů header x.c #include "y.h" double A() { return B( 7); y.h int B( int q); y.c int B( int q) { return q+1; preprocesor int B( int q); double A() { return B( 7); hlavičkový soubor (header) 103

Spojování modulů nekonzistence x.c #include "y.h" double A() { return B( 7); y.h int B( int q); y.c double B() { return 3.14; int B( int q); double A() { return B( 7); nekonzistence 104

Spojování modulů řešení x.c #include "y.h" double A() { return B( 7); y.h int B( int q); y.c #include "y.h" double B() { return 3.14; int B( int q); double A() { return B( 7); int B( int q); double B() { return 3.14; error: Redefinition of 'B' 105

Spojování modulů duplicitní data x.c #include "y.h" double A() { int c; y.h y.c #include "y.h" int c; int c; double A() { int c; int c; x.obj export c export A y.obj export c linker error: Duplicate symbol 'c' 106

Deklarace vs. definice x.c #include "y.h" double A() { y.h extern int c; y.c #include "y.h" int c; extern int c; double A() { extern int c; int c; Definice x.obj import c export A Deklarace y.obj export c 107

Spojování modulů - typy Příklad definice nového typu teď není nutné chápat přesný význam Deklarace proměnné tohoto typu x.c #include "y.h" double A() { return C; y.h enum T { P, Q; extern enum T C; y.c #include "y.h" enum T C; enum T { P, Q; extern enum T C; double A() { return C; enum T { P, Q; extern enum T C; enum T C; 108

Spojování modulů - duplicita typů Přes y.h a z.h je t.h vloţen dvakrát error: Type redefinition: 'T' x.c #include "y.h" #include "z.h" double A() { return C+D; enum T { P, Q; extern enum T C; enum T { P, Q; extern enum T D; double A() { return C + D; t.h enum T { P, Q; y.h #include "t.h" extern enum T C; z.h #include "t.h" extern enum T D; 109

Spojování modulů - #ifndef x.c #include "y.h" #include "z.h" double A() { return C+D; t.h #ifndef _T_H #define _T_H enum T { P, Q; #endif není-li symbol definován... definice nového symbolu (makra) symbol jiţ definován nepřekládá se #ifndef _T_H #define _T_H enum T { P, Q; #endif extern enum T C; #ifndef _T_H #define _T_H enum T { P, Q; #endif extern enum T D; y.h #include "t.h" extern enum T C; z.h #include "t.h" extern enum T D; 110

Programování není zápis algoritmů Běhové prostředí programu Vazba programu na operační systém Přenositelnost mezi platformami Typické chyby a ochrana proti nim Ladění programů debuggerem a bez debuggeru Udrţovatelné programy, kultura programování 111

Vazba programu na operační systém Proces je izolován od ostatních procesů a jádra OS Virtuální adresový prostor a/nebo ochrana paměti Přímá komunikace s I/O zařízeními není moţná Přímá komunikace s jinými procesy by byla moţná technikou sdílené paměti Není ovšem všude dostupná a standardizována Pouţití efektivní ale obtíţné a nebezpečné Veškerá komunikace přes systémová volání Systémové volání zajišťuje: Přechod z uţivatelského reţimu do privilegovaného a zpět Moţnost suspendování procesu uvnitř systémového volání Konkrétní technika systémového volání závisí na HW a OS Softwarové přerušení, brány, speciální volání, falešné výjimky Obvykle není moţné volání přímo z C/C++ Relativně pomalé (změna kontextu, přeplánování) Mnoţina systémových volání je definována OS Můţe být přímo zpřístupněna knihovnou (Unix, "io.h") Nemusí být zveřejněna (Microsoft) 112

Zveřejněné rozhraní operačního systému "C-API" Zpřístupněno knihovnami pro C (výjimečně C++) Nejtypičtějsí část je standardizována Většina je závislá na OS Knihovní funkce obvykle provádějí více neţ jedno systémové volání Některé knihovny mohou zcela změnit původní logiku systémových volání Soubory: Buffering, překlad znakových sad, statefull/stateless Spouštění procesů: spawn = fork + exec Vnitřek knihovních funkcí můţe záviset na verzi OS Připojovány jako DLL v okamţiku startu procesu (Microsoft) Pozor na různé verze!! 113

Standardizovaná rozhraní OS stdio.h - souborový vstup a výstup Přístup "s ukazovátkem" Sjednocení přístupu k souborům a rourám stdin, stdout, stderr Buffering - sníţení počtu systémových volání Následky při pádu programu - fflush Textový/binární mód Překlad do jednotné formy - oddělovač řádků "\n" Neřeší adresářové sluţby signal.h, stdlib.h - řízení procesu Vyvolání/příjem signálu (podle Unixového vzoru) Ukončení procesu system( "winword my.doc") 114

Vlákna (threads) Pro realizaci serverů i některých GUI aplikací Je-li třeba souběţně vykonávat více činností Nebo čekat na více událostí různých druhů Proces můţe mít více vláken (threads) Všechna vlákna ţijí uvnitř společného adresového prostoru Kaţdé vlákno má vlastní zásobník (a tedy jiný SP) První vlákno je spuštěno při spuštění procesu Další vlákna vznikají na pokyn jiţ existujících vláken Vlákna běţí kvazi-paralelně, na multiprocesorech paralelně (!) Všechny moderní OS vlákna podporují Způsoby implementace se mohou výrazně lišit Lze je téţ implementovat na úrovni knihoven bez vědomí OS Norma C ani C++ o vláknech nehovoří Neexistuje přenositelný způsob práce s vlákny Existuje poměrně jednotná terminologie převzatá z teorie OS Existují pokusy o unifikaci prostřednictvím nestandardních knihoven Programování s vlákny je obtíţnější Nešikovná vzájemná komunikace vláken můţe zdrţovat i zablokovat Vyuţití vláken na multiprocesorech vyţaduje zvláštní opatrnost - Pozor na externí knihovny! 115

Odlišnosti mezi platformami Vlastnosti hardware Velikost adresového prostoru a velikostí ukazatelů Pořadí ukládání vícebajtových hodnot (little/big endian) Dostupné formáty celých a reálných čísel Vlastnosti operačního systému Znaková sadou (ASCII/EBCDIC, Win/ISO), oddělovače řádků Konvence jmen souborů (oddělovače, povolené znaky, délka) Další vlastnosti souborového systému (sémantika delete, links, přístupová práva) Základní sluţby a konvence OS (environment, registry) Konvence (/usr/bin,.exe, $HOME) Vlastnosti překladače Volba velikosti základních aritmetických typů Způsob zarovnání poloţek struktur Rozpoznávaná pod-/nad-mnoţinou jazyka Chyby v diagnostice a generovaném kódu Vlastnosti knihoven Dostupnost, pojmenování a sémantika funkcí 116

Přenositelnost mezi platformami Zákaz konstrukcí závislých na vlastnostech hardware a překladače int x; char * p = (char *)&x; struct { char a; int b; S; fwrite( &S, 1, sizeof( S), fp); Uţívání základních typů prostředníctvím typedef typedef unsigned long UINT32; Opatrné uţívání pokročilých konstrukcí (member-pointers, templates) Přednostní pouţívání funkcí definovaných normou jazyka Nelze-li jinak, uţívání direktiv #ifdef Ideál: Program přenositelný bez úpravy zdrojového textu #ifdef _MSC_VER // Microsoft typedef int64 INT64; const char delimiter = '\\'; #else typedef long long INT64; #ifdef UNIX const char delimiter = '/'; #else const char delimiter = '\\'; #endif #endif 117

Ladění programů debuggerem Spustit program v ladicím reţimu Některé zvládnou i připojení k jiţ běţícímu procesu (JIT Debugging) Ladicí reţim nemusí být (a typicky není) pro laděný program identický s normálním Většina funkcí debuggeru je moţná pouze pro programy přeloţené v ladicím nastavení překladače (bez optimalizací) Chybný program se můţe chovat při ladění jinak neţ finální verze Krokovat a spouštět program Odchytit chybující program a zobrazit stav těsně před chybou Nedestruktivně zastavit běţící program Nastavovat breakpointy do kódu Mohou být podmíněné Nastavovat breakpointy na data (změna či splnění podmínky) Některé typy mohou o několik řádů zpomalit běh programu Zobrazovat zásobník volání Zobrazovat lokální i globální proměnné Zobrazovat paměť laděného procesu 118

Ladění programů bez debuggeru Ladicí 'tisky' Co tisknout Kdy a kde tisknout Jak tisknout ('monitor', soubor, databáze,...) Automatické testování Testovací skripty Sady testovacích dat Lokalizace chyby Minimalizace zdrojového textu, kde se chyba vyskytuje Prevence proti zavlečeným chybám Ladicí implementace alokačních funkcí Obloţit kaţdý alokovaný blok prostorem vyplněným značkami Při dealokaci zkontrolovat neporušenost značek a změnit je 119

Bezpečné programování Zapnout všechna varování, která je schopen kompilátor vydat Upravit program do podoby, která nezpůsobí ţádné varování V odůvodněných případech lze varování vypnout pomocí #pragma Dodrţovat pravidla pro přenositelné a vícevláknové programy A to i kdyţ přenositelnost ani vícevláknovost zdánlivě nemá smysl Minimum globálních proměnných, pokud moţno pouze konstantní Procedura smí číst či měnit pouze objekty, které jsou přímo či nepřímo určeny jejími parametry Důsledné uţívání ochranných prostředků kompilátoru const, private,... Důsledná chybová diagnostika Test úspěšnosti kaţdého malloc, fopen,... Testy proti interním chybám a špatným parametrům Ochrana proti uţívání odalokovaných bloků Ochrana proti přetečením polí Všechny funkce manipulující s polem dostávají velikost pole jako parametr Ţádné strcat, gets a podobné nebezpečné funkce Největší nepřítel je chyba, která není vţdy a ihned smrtelná Dereference nulového ukazatele se pozná ihned Dereference neinicializovaného ukazatele způsobí pád později void f( int* p) { assert( p); /*...*/ free(p); p=0; 120

Udrţovatelné zdrojové texty Logické rozdělení do modulů a hlavičkových souborů na niţší úrovni datové struktury a funkce, třídy Jasné oddělení rozhraní od implementace Oddělení obsluhy uţivatelského rozhraní od vlastní logiky aplikace Minimum globálních proměnných ideálně ţádné, příp. třída (struktura) app Komentáře, zejména k rozhraním Indentace, omezená délka řádek Pojmenovávací konvence, logicky zvolené a dlouhé identifikátory Buďto my_big_array nebo MyBigArray Obvykle typy a konstanty začínají velkými písmeny, proměnné malými GetX/SetX konvence pro metody v C++ apod. Pojmenování všech smysluplných konstant Ţádné int x[ 100] ani case 27: Jaké jiné konstanty neţ smysluplné by měly být ve zdrojových textech? Nepouţívat deprecated features const a = 123; bool b; b++; char *s = "abcd"; <stdlib.h> 121

Dynamické seznamy struct osoba { char jmeno[20]; int narozen; osoba *dalsi; ; osoba *zamestnanci; ukazatel na další hlava seznamu jmeno Novak Jason Drson narozen 1905 dalsi 1948 1990 konec seznamu 122