From 16de3e9131b7ccad017beebfbea9fc6268ce713e Mon Sep 17 00:00:00 2001 From: Tomas Mudrunka Date: Wed, 19 Feb 2025 17:26:06 +0100 Subject: [PATCH] zalohy skripta --- c/skripta/c_00.txt | 13 + c/skripta/c_01.txt | 64 + c/skripta/c_02.txt | 96 + c/skripta/c_03.txt | 101 + c/skripta/c_04.txt | 33 + c/skripta/c_05.txt | 45 + c/skripta/c_06.txt | 98 + c/skripta/c_07.txt | 90 + c/skripta/c_08.txt | 128 + c/skripta/c_09.txt | 133 + c/skripta/c_10.txt | 82 + c/skripta/c_11.txt | 82 + c/skripta/c_12.txt | 62 + c/skripta/c_13.txt | 101 + c/skripta/c_14.txt | 70 + c/skripta/c_15.txt | 118 + c/skripta/c_16.txt | 49 + c/skripta/c_17.txt | 98 + c/skripta/c_18.txt | 73 + c/skripta/c_19.txt | 74 + c/skripta/c_20.txt | 75 + c/skripta/c_98.txt | 41 + .../compilation/jazyk_c compilation.html | 3375 +++++++++++++++++ .../jazyk_c compilation_files/css(1).php | 1 + .../jazyk_c compilation_files/css(2).php | 1 + .../jazyk_c compilation_files/css.php | 1 + .../jazyk_c compilation_files/icon_smile.gif | Bin 0 -> 174 bytes .../jazyk_c compilation_files/icon_smile2.gif | Bin 0 -> 174 bytes .../jazyk_c compilation_files/js.php | 1 + .../jazyk_c compilation_files/todo.gif | Bin 0 -> 1335 bytes c/skripta/start.txt | 56 + 31 files changed, 5161 insertions(+) create mode 100755 c/skripta/c_00.txt create mode 100755 c/skripta/c_01.txt create mode 100755 c/skripta/c_02.txt create mode 100755 c/skripta/c_03.txt create mode 100755 c/skripta/c_04.txt create mode 100755 c/skripta/c_05.txt create mode 100755 c/skripta/c_06.txt create mode 100755 c/skripta/c_07.txt create mode 100755 c/skripta/c_08.txt create mode 100755 c/skripta/c_09.txt create mode 100755 c/skripta/c_10.txt create mode 100755 c/skripta/c_11.txt create mode 100755 c/skripta/c_12.txt create mode 100755 c/skripta/c_13.txt create mode 100755 c/skripta/c_14.txt create mode 100755 c/skripta/c_15.txt create mode 100755 c/skripta/c_16.txt create mode 100755 c/skripta/c_17.txt create mode 100755 c/skripta/c_18.txt create mode 100755 c/skripta/c_19.txt create mode 100755 c/skripta/c_20.txt create mode 100755 c/skripta/c_98.txt create mode 100755 c/skripta/compilation/jazyk_c compilation.html create mode 100755 c/skripta/compilation/jazyk_c compilation_files/css(1).php create mode 100755 c/skripta/compilation/jazyk_c compilation_files/css(2).php create mode 100755 c/skripta/compilation/jazyk_c compilation_files/css.php create mode 100755 c/skripta/compilation/jazyk_c compilation_files/icon_smile.gif create mode 100755 c/skripta/compilation/jazyk_c compilation_files/icon_smile2.gif create mode 100755 c/skripta/compilation/jazyk_c compilation_files/js.php create mode 100755 c/skripta/compilation/jazyk_c compilation_files/todo.gif create mode 100755 c/skripta/start.txt diff --git a/c/skripta/c_00.txt b/c/skripta/c_00.txt new file mode 100755 index 0000000..665ab86 --- /dev/null +++ b/c/skripta/c_00.txt @@ -0,0 +1,13 @@ +====== Co bychom měli znát než začneme programovat ====== + * Povinné + * 1B (byte) == 8b (bitů) + další základní výpočty s jednotkami informace/paměti + * základní práce s operačním systémem používaným k výuce + * práce s příkazovým řádkem (CLI) na tomto OS (procházení adresářů, mazání, přejmenování a kopírování souborů, nastavování práv pro spouštění, spouštění programů) + * základy programování z jiného jazyka (cokoli, v nejhorším případě alespoň nějaký značkovací jazyk, jako html, nebo BASIC, který se vyučuje u nás na škole) + + * Nepovinné + * psaní na klávesnici (především umístění různých speciálních znaků) + +**Ohledně jakékoli nejasnosti ohledně čehokoli se prosím kdykoli informujte u vyučujícího ("když už tu teda trčíme...").** + +Také nezapomeňte připomenout svému lektorovi, aby nezapoměl, že nemá zapomenout vám ukázat doplňkové studijní materiály, připravil jsem si pro vás totiž zábavná videa a animace :-) diff --git a/c/skripta/c_01.txt b/c/skripta/c_01.txt new file mode 100755 index 0000000..d345560 --- /dev/null +++ b/c/skripta/c_01.txt @@ -0,0 +1,64 @@ +===== Předmluva ===== +Účelem této příručky je přiblížit vám základy programování hned z několika pohledů: + * První složkou jsou základy praktického programování v ANSI C (napsat, zkompilovat, spustit, upravit). + * Dále se také seznámíme s programátorskou kulturou a základy slušného chování při získávání informací na internetu. + * A nakonec prohloubíme své znalosti o počítači, operačním systému a zužitkujeme nové poznatky při programování. + +===== Počátky ===== +Vývoj jazyka C začal v Bellových laboratořích AT&T mezi léty 1969 a 1973. Ritchie tvrdí, že nejpřínosnější období bylo v roce 1972. Pojmenování "C" zvolili, protože mnoho vlastností přebírali ze staršího jazyka zvaného "B", jehož název byl zase odvozen od jazyka BCPL (ale to není jisté, neboť Thompson také vytvořil jazyk Bon na poctu své ženy Bonnie). + +V roce 1973 se stal jazyk C dostatečně stabilním. Většina zdrojového kódu jádra Unixu, původně napsaného v assemleru PDP-11, byla přepsána do C. Unix tedy patří mezi první operační systémy, které byly napsané v jiném než strojovém jazyce či assembleru. Předchozí byl například systém Multics (napsaný v PL/I) a TRIPOS (napsaný v BCPL).ovat, opravit - to vše pokud možno nezávisle na platformě). + * Dále se podíváme na vyhledávání informací, řešení problémů pomocí internetového vyhledávače a na programátorskou kulturu (Pokud komunikujeme s jinými programátory -byť jen po internetu-, musíme dodržovat jisté konvence. Největší a nejméně snadno dodržiteknou je nechtít po někom to, aby někdo mrhal svým časem nad něčím, co můžete udělat sami). Do této esence patří samozřejmě také konvence ve psaní zdrojového kódu a programování vůbec. + * A nakonec prohloubíme své znalosti ANSI C, to především znamená, že se podíváme se na pointery (ukazatele) a dynamickou alokaci paměti. + +Protože C je velmi komplikovaný jazyk, budeme se držet základů a věcí nezbytných k tomu, abychom měli kompaktní soubor znalostí vhodných k tomu, abychom napsali nějaký pěkný program. + + +===== Proč C? ===== +C je programovací jazyk, který vyvinuli Ken Thompson a Dennis Ritchie pro potřeby operačního systému Unix. V současné době je to jeden z nejpopulárnějších jazyků, zřejmě nejčastější pro psaní systémového softwaru, ale velmi rozšířený i pro aplikace. + +C je nízkoúrovňový, kompilovaný, relativně minimalistický a rychlý programovací jazyk. Je dostatečně mocný na většinu systémového programování, mimoto podporuje také možnost využít ve zdrojovém kódu jazyk assembler, který pracuje víceméně s instrukcemi procesoru pro případ, že by něco (velmi nízkoúrovňového) nebylo možné napsat, to ale pro naše účely nebudeme potřebovat. + +Z toho vyplývá, že operační systémy, překladače, knihovny a interpretry vysokoúrovňových jazyků jsou často implementovány právě v C. + +Ukládání dat je v C řešeno třemi základními způsoby: statickou alokací paměti (při překladu), automatickou alokací paměti na zásobníku, dynamickou alokací na haldě (heap) pomocí knihovních funkcí. Jazyk nedisponuje žádnou abstrakcí nad alokací: s pamětí se pracuje přes datový typ zvaný ukazatel, který drží odkaz na paměť, ale je na něm možné provádět aritmetické operace. Ukazatelé tedy existují nezávisle na proměnných, na které odkazují, a je na odpovědnosti programátora, aby neukazovaly na paměť nealokovanou. + +Jazyky Java a C#, oba odvozené od C, používají méně univerzální způsob odkazování alokovaných proměnných, který snižuje pravděpodobnost chyby v programu. Jazyk C++, původně rozšíření jazyka C, si ovšem ukazatele zachoval. + +Mnoho dalších moderních programovacích jazyků (Nejen kompilovaných) přebírá způsob zápisu (neboli syntaxi) z jazyka C. Patří mezi ně například zmíněná Java či Perl a PHP. + +Dalším plusem je, že se při výuce a psaní programů v C se můžete naučit mnoho podrobností o funkci počítače a rozšířit je na víc než "Tam ten procesor tam počítá s nějakejma číslama a něco si dává někam do paměti", C vám ukáže, jak funguje práce s pamětí, pokud se blíže podíváme na strojový kód (vzniklý kompilací zdrojového kódu) dozvíme se podrobněji jak funguje procesor a také specifika konkrétní architektury. + +V C můžeme nejen psát textové nebo grafické aplikce, ale dokonce programovat webové aplikace podobně, jako například v PHP, nebo dokonce psát programy pro jednočipové mikropočítače (šváby). + + +===== Historie jazyka C ===== +==== Počátky ==== +Vývoj jazyka C začal v Bellových laboratořích AT&T mezi léty 1969 a 1973. Ritchie tvrdí, že nejpřínosnější období bylo v roce 1972. Pojmenování „C“ zvolili, protože mnoho vlastností přebírali ze staršího jazyka zvaného „B“, jehož název byl zase odvozen od jazyka BCPL (ale to není jisté, neboť Thompson také vytvořil jazyk Bon na poctu své ženy Bonnie). + +V roce 1973 se stal jazyk C dostatečně stabilním. Většina zdrojového kódu jádra Unixu, původně napsaného v assemleru PDP-11, byla přepsána do C. Unix tedy patří mezi první operační systémy, které byly napsané v jiném než strojovém jazyce či assembleru. Předchozí byl například systém Multics (napsaný v PL/I) a TRIPOS (napsaný v BCPL). + +==== K&R C ==== +V roce 1978, Ritchie a Brian Kernighan vydali první vydání knihy The C Programming Language. Tato kniha, mezi programátory C známá jako „K&R“, sloužila po mnoho let jako neformální specifikace jazyka. Verze C, kterou takto popsali, bývá označována jako „K&R C“. (Druhé vydání knihy popisovalo novější standard ANSI C.) + +K&R C je považován za základní normu, kterou musejí obsahovat všechny překladače jazyka C. Ještě mnoho let po uvedení ANSI C to byl „nejmenší společný jmenovatel“, který využívali programátoří v jazyce C kvůli maximální přenositelnosti, protože zdaleka ne všechny překladače plně podporovaly ANSI C. + +V několika letech následujících po uvedení K&R C bylo uvedeno a přidáno několik „neoficiálních“ vlastností jazyka, které byly podporovány překladači od AT&T a některých dalších dodavatelů. + +==== ANSI C a ISO C ==== +V pozdních sedmdesátých letech začalo C nahrazovat BASIC jako přední programovací jazyk pro mikropočítače. Během osmdesátých let bylo přejato pro použití na platformě IBM PC a jeho popularita se značně zvýšila. Tou dobou Bjarne Stroustrup a další v Bellových laboratořích začali pracovat na rozšiřování C o objektově orientované prvky. Jazyk, který vytvořili, zvaný C++, je dnes nejrozšířenější programovací jazyk pro aplikace na Microsoft Windows. C zůstává stále populárnější ve světě Unixu. + +Jedním z cílů standardizačního procesu ANSI C byl vytvořit nadmnožinu K&R C zahrnující mnoho „neoficiálních vlastností“. Navíc standardizační komise přidala několik vlastností jako funkční prototypy (vypůjčené z C++) a schopnější preprocesor. + +ANSI C je dnes podporováno téměř všemi rozšířenými překladači. Většina kódu psaného v současné době v C je založena na ANSI C. Jakýkoli program napsaný pouze ve standardním C je přeložitelný a spustitelný na jakékoli platformě, která odpovídá tomuto standardu. Nicméně mnoho programů se dá přeložit pouze na jedné platformě nebo jedním překladačem, kvůli (i) použití nestandadních knihoven, např. pro grafiku, a také (ii) některé překladače v implicitním módu neodpovídají standardu ANSI C. + +==== C99 ==== +Po standardizaci jazyka v roce 1989 se většina vývoje soustředila na jazyk C++. Přesto však na konci 90. let došlo k vydání dokumentu ISO 9899:1999 (obvykle nazývaný C99), který byl následně v březnu 2000 přijat i jako ANSI standard. + +C99 představil několik nových vlastností, které byly mnohdy v překladačích už implementovány jako rozšíření. + +Standard C99 je v některých ohledech přísnější než původní standard C89; například je zakázáno odkazovat na stejnou paměť ukazateli jiných typů. Toto umožňuje vylepšenou optimalizaci, ale může způsobit problémy s kompilací starších programů. + +Žádný kompilátor zatím neobsahuje kompletní implementaci C99, přestože některé jsou poměrně blízko (GCC). Firmy jako Microsoft nebo Borland neprojevily velký zájem o implementaci C99, především kvůli tomu, že většinu nových vlastností poskytuje C++ a to často nekompatibilně s C99 (datový typ complex v C99 versus třída complex v C++). + + diff --git a/c/skripta/c_02.txt b/c/skripta/c_02.txt new file mode 100755 index 0000000..47a1add --- /dev/null +++ b/c/skripta/c_02.txt @@ -0,0 +1,96 @@ +====== Ahoj, světe! ====== +Tzv. "Ahoj, světe!" (v originále "hello, world") je jednoduchý program, který prostě jen vypíše "hello, world", ten je sám o sobě prakticky k ničemu, ale pro programátory je důležitý protože se naučíme jak vypadá program, který nic vlastně nedělá, jak se zkompiluje a spustí, tedy všechny formality, které nás dělí od vlastního programování. + +A takto tedy vypadá hello world v C: + + + #include + + int main(int argc, char *argv[]) //Pro primitivni programy muzeme pouzit jen: int main(void) + { + //Toto je komentar + /* + * A toto je + * viceradkovy komentar + */ + printf("hello, world\n"); + return(0); + } + +Tento text uložíme pomocí nejobyčejnějšího textového editoru do souboru s příponou .c (tedy např.: "hello.c"). Na konci souboru musí být minimálně jeden prázdný řádek a soubor nesmí končit v otevřeném komentáři tedy např.: "/*Za touto vetou bude konec souboru". Jinak kompilátor (nebo spíše preprocesor) nahlásí chybu. + + +===== Rozbor prvního programu ===== +Po kompilaci a spuštění tohoto programu začne počítač vykonávat naše příkazy tak, jak jsou napsány ze shora dolů, z leva do prava. Teď si ukážeme co program udělá krok za krokem, řádek po řádku: + + #include +To není příkaz, který by se prováděl při spuštění programu, ale ještě před kompilací. Jde o tzv. "direktivu preprocesoru" (začínají # - křížkem), preprocesor je program, který připraví náš kód pro kompilátor (odstraní nepotřebné mezery, prázdné řádky, rozvine makra,...). Direktiva preprocesoru #include způsobí to, že bude nahrazena obsahem souboru "soubor", čili na začítek našeho programu se vloží soubor stdio.h, který obsahuje především funkce na práci s příkazovým řádkem a soubory. Pokud je jméno souboru ve špičatých závorkách (#include ), hledá se soubor v adresáři pro hlavičkové soubory, který je součástí kompilátoru, pokud bychom napsali jméno souboru mezi uvozovky (#include "soubor"), preprocesor by hledal soubor ve stejném adresáři, jako se nachází náš program. + + int main(int argc,char *argv[]) { /*Nase prikazy...*/ } +Toto je deklarace funkce main, funkce main je první funkce, která je zavolána po spuštění programu, jinými slovy příkazy uvedené ve složených závorkách ({}) budou provedeny neprodleně po spuštění našeho programu. Klíčové slovo "int" před jménem funkce říká, že funkce vrací integer (tedy celé číslo). Dvě proměnné nadeklarované v závorkách za jménem funkce (int argc, char *argv[]) se používají k získání parametrů od našeho OS, jde o argumenty z příkazové řádky (nebo třeba jména souborů přetažená na ikonku našeho programu). přičemž celé číslo argc obsahuje počet parametrů a pole řetězců (polí znaků) argv[] obsahuje text těchto argumentů. + + /* Komentáře */ +Vše, co je umístěno mezi /* a */ (v našem příkladu můžete vidět zdobnější zápis s hvězdičkou na každé řádce, to zůstává na fantazii programátora...) bude ignorováno, můžeme to tedy použít pro popisování našich programů (to je velmi důležité, jinak se v našem programu ztratíme). Také můžeme použít komentář pomocí // , kdy vše od // až do konce řádku je ignorováno. + + printf("hello, world\n"); +Tento řádek vypíše na obrazovku text "hello, world" a přejde na nový řádek ("\n" značí newline dle zvyku na vašem OS, tj. ekvivalent enteru). Funkce printf() je nadefinovaná v souboru stdio.h (viz. výše) a jako první parametr přijímá text, který chceme vypsat, nebo formátovací řetězec. Tímto prvním argumentem je vždy řetězec (např. text v uvozovkách). Pokud bychom chtěli vypsat uvozovku, musíme použít \" pokud lomítko, tak \\ a pokud znam procenta, tak %%. Všiměte si, že deklarace, definice a volání funkce (náš případ) musí končit středníkem (;), nikoli však novým řádkem, stačí mezera, nebo tabelátor. + + return(0); +Jde opět o volání funkce. Funkce return() (jména funkcí píšeme standartně s () na konci, aby bylo na první pohled jasné, že jde o funkci) způsobí to, že je funkcí, ze které je zavolána (v našem případě main()), vrácena hodnota zadaná jako první parametr této funkce return(). Pokud toto zavoláme z funkce main, znamená to pro nás ukončení programu s návratovou hodnotou 0. Návratové hodnoty jsou čísla (int main(), tedy funkce main() je typu integer == celé číslo), které programy předávají operačnímu systému po skončení, aby měl přehled o úspěšnosti vykonání programu (0 znamená bez chyby a obecně pak platí, že čím vyšší číslo, tím horší chyba). + +Pokud program dojde na konec kódu funkce, je automaticky navrácena hodnota 0, pokud to není změněno pomocí funkce return(); + + +===== Co budeme potřebovat pro psaní a spuštění programů v C ===== +V první řadě budeme potřebovat plaintextový editor (jsme začátečníci a budeme tedy raději konzervativní, takže kódovani utf-8, nebo cp-1250, raději žédné wide-chary a už vůbec ne textové editory typu Word!!!). Naopak se nám hodí editor se zvýrazněnou syntaxí a jinými "vychytávkami", které nám mnohonásobně usnadní psaní kódu a například nám i napovídá, jeden z nejlepších nejuniverzálnějších editorů je SciTe (na enginu Scintilla). + +Můžeme použít například editory dostupné pro náš OS +Microsoft: + * SciTe (doporučuji) + * PSPad (nedoporučuji) + * notepad +Unixy: + * SciTe (doporučuji) + * nano (doporučuji pro příkazový řádek) + * mcedit (balíček mc) + * vim + +Potom budeme také potřebovat program, který převede námi psaný a čitelný strojový kód na strojový kód tj. procesorem čitelné instrukce (ty se ukládají v binárním spustitelné souboru čitelném operačním systémem). A samozřejmě standartní knihovny ANSI C (verzi pro vývojáře). + +Na platformách od Microsoftu to znamená instalci jednoho z těchto balíčků + * MinGW (gcc, g++) - (doporučuji) + * Borland C Compiler + +Na Unixových platformách pak pravděpodobně potřebujeme tyto balíčky + * gcc + * g++ (pokud máme zájem také o C++) + * libc-dev (poslední verze) + +Nebo můžeme sáhnout po celých IDE (Integrované vývojové prostředí) +Jde o jakýsi balíček Vše-V-Jednom. To v praxi znamená potřebný editor uživatelsky přívětivě spolupracující s kompilátorem, jinými slovy nainstalujeme jeden balíček programů místo všech výše zmíněných. + +Ze všech IDE pro Unixy i MS systémy je pro nás nejvýhodnější multiplatformní IDE Dev-C++ (dev-cpp) - (doporučuji). +Pro jednotlivé systémy existují samozřejmě i další IDE: + +Na Windows máme např. + * C++ Builder + * Microsoft Visual Studio (nebo Visual C++) + +Na Unixech pak stojí za zmínku + * Eclipse (s pluginem pro C) + * NetBeans (s pluginem pro C) + * Anjuta + * KDevelop + + + +===== Samostatné cvičení ===== + * Vyberte si jedno z freewarových řešení dle výběru vyučujícího (Dev-C++, nebo SciTe s gcc/g++). + * Vyhledejte si ho pomocí Googlu, stáhněte a nainstalujte ho na váš počítač. + * Vyzkoušejte si kompilaci a spuštění našeho prvního programu (Hello, world!). + * Vyzkoušejte si práci s editorem, zvýraznění syntaxe a případně automatické dokončování kódu. + * Pokuste se náš program zkompilovat podruhé, ale v kódu změňte text, který se bude vypisovat na obrazovku. + +Následující body platí i pro všechna budoucí cvičení: + * Veškeré problémy se pokuste vyřešit nejdříve pomocí Googlu, případně pomocí manuálu dodaného s produktem. + * V případě neúspěchu se obraťte na vyučujícího. diff --git a/c/skripta/c_03.txt b/c/skripta/c_03.txt new file mode 100755 index 0000000..ef0c14b --- /dev/null +++ b/c/skripta/c_03.txt @@ -0,0 +1,101 @@ +====== Datové typy, deklarace, identifikátory, přiřazení, inicializace, definice ====== +Jazyk C disponuje několika základními datovými typy, jiné si můžeme vytvořit sami. Datový typ v praxi popisuje formát nějaké hodnoty, která vyžaduje alokaci předem daného místa v paměti (většinou měříme v bytech), na to se ukládá požadovaná hodnota (samozřejmě binárně), které přísluší (což není úplně tak závazné) konkrétní interpretace (logická hodnota, číslo, znak, text). + + +===== Základní jednoduché datové typy ===== +Celočíselné + * char - 1B + * short - 2B + * int - 2B + * long - 4B + +S Plovoucí desetinnou čárkou + * float - 4B + * double - 8B + * long double - 10B + +//pozn.: Hodnoty se mohou lišit podle konkrétní implementace (kompilátoru). Velikost konkrétního typu v bytech získáte také pomocí makra preprocesoru sizeof(), tedy např sizeof(char) bude nahrazeno číslem 1.// + +Například datový typ char má velikost 1B, to odpovídá 256ti možným kombinacím, standartně jednoduché datové typy počítají s možností uložení záporného čísla, takže např. char může dosahovat hodnot -128 až 127, podobné je to se všemi jednoduchými typy. + +Pokud ale nechceme zbytečně alokovat (zabírat) paměť pro záporná čísla, když víme, že toho nevyužijeme, můžeme použít operátoru "unsigned" (česky "bez znaménka"), tím docílíme toho, že se rozsah všech možných hodnot našeho typu "posune" na 0 a výše. Např. tedy datový typ "unsigned char" může nést hodnotu 0 až 255 tj. nějaký libovolný byte. + + +===== Deklarace, identifikátory ===== +Takže ve zkratce známe několik důležitých datových typů a určitě nás zajímá jejich využití. První možností je, jak již bylo naznačeno, ukládání informací do paměti. Abychom mohli ukládat data do paměti, musíme si nejprve vytvořit proměnnou (staticky-na pevno alokovat část paměti), toho docílíme jednoduchým kusem kódu, vše ostatní už vyřeší kompilátor. + +Této proceduře se říká "deklarace", to znamená, že v paměti zabereme místo a přiřadíme mu "identifikátor" (jméno), který budeme pokaždé používat při práci s tímto prostorem v paměti (to není podmínkou, identifikátoru je totiž přiřazena nějaká konkrétní adresa v paměti, ale o tom až v pokračování pro pokročilé). + +Identifikátory mohou sice obsahovat různé znaky, my se ale zatím budeme držet malých písmen (v případě potřeby lze několik slov oddělit např. podtržítkem ("_")), to nám musí stačit, také se můžeme držet některých tradic (znaky začínájí na "c" ("cmuj_znak"), proměnné používané k řízení cyklů se většinou označují pouze "i" - může nám stačit pro celý jednodušší program bez vnořených cyklů, atd...) + +A takto proběhne deklarace z pohledu programátora: + datovy_typ identifikator[, dalsi_identifikator, ...]; //Deklarace konci strednikem + +Takže pokud například potřebujeme tři proměné, pro uložení hodnot 0 - 4 294 967 295, použijeme tuto konstrukci: + unsigned int moje_cislo, moje_dalsi_cislo, moje_posledni_cislo; + +Pozor ovšem na redeklaraci - tj. pokus o opětovnou deklaraci/definici libovolné proměnné, funkce, nebo čehokoli jiného, jejíž identifikátor je již používán, to je chyba, která většinou zkončí chybou překladače (kompilátoru). + + +===== Přiřazení, inicializace ===== +Přiřazení je operace, která na danou adresu ukládá námi vybraná data, probíhá pomocí operátoru rovnítko ("=") levé a pravé hodnoty (l-hodnota, r-hodnota - od left, right). + +Obecný zápis je tento: + l-hodnota = r-hodnota; //I prirazeni opet konci strednikem + +L-hodnota je v levo, tj. cíl přiřazení, r-hodnota je v pravo, tj hodnota přiřazení, po úspěšném přiřazení platí, že se l-hodnota rovná r-hodnotě. +Pokud bychom tedy do námi deklarované proměnné moje_cislo chtěli přiřadit hodnotu 5, postupujeme takto: + moje_cislo = 5; + +Pokud je hodnota do proměnné jednou přiřazena, lze ji samozřejmě přepsat jinou (až na vyjímky, o tom později...). + +Pokud je to poprvé, co do nově nadeklarované proměnné přiřazujeme hodnotu, takovému přiřazení říkáme také inicializace. + + +===== Definice ===== +Definice je výraz pro inicializaci provedenou zároveň při deklaraci (nebudeme polemizovat o rozdílu slov deklarace a definice z pohledu českého jazyka...). + +Zápis definice je tento: + datovy_typ identifikator = nova_hodnota[, dalsi_identifikator = nova_hodnota, ...]; //Samozrejme strednik + +Konkretne napriklad takto: + unsigned char pocet_psu = 10; + +Ovšem zde se naskytuje další možnost udělat chybu a to je redeklarace: + unsigned char pocet_psu = 10; + unsigned char pocet_psu = 11; //Chybne pridani jednoho psa - pokus o redeklaraci! +Spravny zapis je samozřejmě tento: + unsigned char pocet_psu = 10; //Definice + pocet_psu = 11; //Spravne pridani jednoho psa - pouze prirazeni + + +====== Funkce printf() podrobněji ====== +funkce printf nabízí kromě výpisu textu tak, jak je zadán do jejího parametru také možnost výpisu obsahu proměnných. +Pokud bychom například chtěli vypsat proměnné pocet_psu a pocet_kocek, docilime toho timpo zpusobem: + + printf("Pocet psu: %d\nPocet kocek: %d\n", pocet_psu, pocet_kocek); //Ansi-C funkce ze stdio.h - Nezapomeneme na #include !!! + +Symbol %d bude nahrazen číslem načteným z naší proměnné, s každým podobným operátorem přibyde funkci printf() jeden povinný parametr, tzn., že pokud je v našem řetězi dvakrát "%d", musíme kromě prvního parametru (tzv. formátovacího řetězce) specifikovat ještě další dva parametry, tj. např. dvě proměnné v požadovaném pořadí. + +Tady je seznam všech nejdůležitějších operátorů pro formátovací řetězec funkce printf: + +Pro čísla typu int + * %d - vypíše číslo dekadicky + * %u - vypíše číslo dekadicky neznaménkově (unsigned) + * %x - vypíše číslo hexadecimálně malými písmenky + * %X - vypíše číslo hexadecimálně velkými písmenky + * %o - vypíše číslo oktálně + +Pro ostatní typy + * %ld - vypíše číslo typu long dekadicky + * %f - vypíše číslo typu float dekadicky + * %Lf - vypíše číslo typu long double dekadicky + +Pro pole + * %s - vypíše řetězec (tomu se budeme věnovat později) + + +===== Samostatné cvičení ===== + * Co vypíše následující příkaz?: + * printf("Pocet psu: %d\nPocet kocek: %d\n", 34, 5); + * Napište a zkompilujte program, který na začátku deklaruje jednu proměnnou a druhou definuje libovolným celým číslem, první proměnnou inicializujte také libovolným číslem. Pro obě proměnné si zvolte příslušné (a paměťově výhodné) datové typy. Nakonec pomocí příkazu printf() vypište na monitor tato čísla desítkově i šestnáctkově, ve formátovacím řetězci použijte několik přechodů na novou řádku, vtipný text a ještě vypište jedno číslo specifikované konstantou přímo jako argument funkce printf(). Smíte použít pouze jediné volání funkce printf(). Celý zdrojový kód progamu vhodně okomentujte. diff --git a/c/skripta/c_04.txt b/c/skripta/c_04.txt new file mode 100755 index 0000000..d66c049 --- /dev/null +++ b/c/skripta/c_04.txt @@ -0,0 +1,33 @@ +====== Výhody a nevýhody programování textových aplikací ====== +V našich seminářích se budeme zabívat především psaním aplikací pro CLI (tedy příkazový řádek). +Účelem této hodiny je poskytnout vám objektivní pohled na tyto aplikace ve srovnání s aplikacemi grafickými. + +===== Pokud v C píšeme konzolové aplikace, získáme tyto výhody: ===== + * Textové aplikace jsou rychlejší. + * Při vzdáleném přístupu k počítači se text (SSH/Telnet) přenáší rychleji než grafika (VNC/MST). + * Zkušenějším uživatelům usnadňují práci a posouvají pro ně efektivitu úplně jinam, než si BFU (běžný Franta uživatel) dokáže představit. + * Bude velmi snadné, aby další aplikace/skripty mohly využívat naší aplikaci (např. je běžnou praxí, že se nejdříve napíše textová aplikace a grafika se píše až jako nástavba na ni - úplně samostatný spustitelný soubor). + * Veškeré výpisy programu i vstupy do něj můžeme ukládat nebo načítat do souboru, případně rovnou zpracovávat výstup jiného programu. + * Tyto aplikace mohou být použity jako webové aplikace (buď jako binární CGI aplikace, nebo prostřednictvím interpretovaných skriptů). + * Textové aplikace (především ty v čistém Ansi C) jsou snadno přenositelné na všechny platformy, pro které jsou dostupné kompilátory (Nejen Windows a Unixy, ale také obrovské množství dalších systémů). + * Pokud se naučíte psát textové aplikace, bude pro vás snadné vytvářet grafické aplikace pomocí tzv. GUIBuilderů známých například z vývojového prostředí Visual Basicu implementovaného Microsoftem nebo IBM. Pro více info viz. níže. + +===== Nevýhody textových programů ===== + * Pokud píšete aplikace pro běžné uživatele, budou pro ně neefektivní, protože neovládají příkazový řádek na potřebné úrovni. + * Tyto uživatelé si samozřejmě budou stěžovat ;D (Dobrým kompromisem pro jednodušší aplikace je napsat si další program, který bude fungovat jako grafická nadstavba). + +===== Výhody grafických aplikací ===== + * Spousta tzv. "eye-candy" -> Spokojení uživatelé + * Ovládání zvládne i p*blb + +===== Nevýhody grafických aplikací ===== + * Je obtížné je ovládat pomocí jiných programů a tedy nemůžeme práci s nimi potřebně automatizovat. + * Jsou náročnější na systémové prostředky. + +===== GUIBuildery - prostředí pro jednoduchý návrh grafického rozhraní programů v C/C++ ===== + * Borland C++ Builder (Windows) + * Kylix (Linux - kompatibilní s C++ Builderem a Delphy - zastaralé) + * Microsoft Visual Studio (Windows) + * wxDev-Cpp (Windows, programy ale možno kompilovat i na Linuxu s potřebnými knihovnami - wxWidgets) + * GLade (Linux - GTK+2) + * další... (cokoli, s čím se vám dobře pracuje...) diff --git a/c/skripta/c_05.txt b/c/skripta/c_05.txt new file mode 100755 index 0000000..d9fb3d4 --- /dev/null +++ b/c/skripta/c_05.txt @@ -0,0 +1,45 @@ +====== Konstanty, konstantní proměnné ====== +Konstata je výraz pro jakákoliv data, se kterými program pracuje a píšeme je přímo do zdrojového kódu. +Konstantou může být např. číslo, znak, řetězec, pointer, a další... +Konstanta se chová jako výraz, jako R-Hodnota (lze ji přiřadit, ale nelze přiřadit do ní). +S konstantami jsme se již setkaly v kapitole probírající přiřazení. + +===== Typy konstant s okomentovaným příkladem ===== + int 32 //cele cislo (Integer) + long L940 //cislo typu long + float 2.345 //cislo s plovouci radovou carkou (teckou) + float F940 //Jiny zapis floatu (bez tecky by nebylo jasne, ze jde o float) + double 3.45 //cislo double + char 'A' //znak (pro binarni data pouzivejte unsigned char nebo lepe int) + char[] "Muj text" //retezec - pole znaku - viz. znak + +===== Možnosti zápisu celých čísel (příklady) ===== + decimálně 123 + hexadecimálně 0x1A6F + oktálně 029 + + +===== Možnosti zápisu znaků (literály - platí i pro řetězce) ===== + decimálně \0232 ('\0232') + hexadecimálně \x0A ('\x0A') + + +===== Speciální znaky ===== + \n ('\n') Přechod na další řádek + \r ('\r') Přechod na začátek řádku + \t ('\t') Tabelátor + + +===== Příklady literálů ===== + char str[] = "\tPole ch\x41ru, neboli retezec,\nje to tak."; + char str[] = "Preruseny" " retezec\n"; + char str[] = "Preruseny " "retezec " + "muze pokracovat i na dalsi radce!\n"; + + +===== Konstantní proměnné ===== +Konstantní proměnná je taková proměnná, která se po inicializaci stává konstantou (nelze ji měnit, je to tedy neproměnná proměnná ;D). +Deklarace konstantní proměnné probíhá pomocí tzv. "typového modifikátoru", v našem případě "const". + +Příklad: + const int a, b = 32; //Promenna b jiz nepujde zmenit, promenna a pujde zmenit pouze jednou (inicializovat). diff --git a/c/skripta/c_06.txt b/c/skripta/c_06.txt new file mode 100755 index 0000000..a38fbfc --- /dev/null +++ b/c/skripta/c_06.txt @@ -0,0 +1,98 @@ +====== Základní operátory ====== +R-hodnota (viz. dříve) se může skládat z více prvků s vlastnostmi r-hodnoty. To uděláme za pomoci nějakých operátorů, se dvěmi hodnotami můžeme provádět různé operace (aritmetické, logické a další). k tomu nám slouží různé operátory. + +===== Příklad ===== + + int x, a, b = 2; + x = (a = (b * 2) - 3); + +Na konci tohoto kódu budou proměnné "x" a "a" držet hodnotu 1. + +Z toho také vyplívá, že celé přiřazení (l-hodnota = r-hodnota) je zároveň r-hodnotou a lze ho přiřadit do jiné l-hodnoty (např. proměnné). +Také si všimněme, že lze použít závorky () k seskupování výrazů a úpravě jejich priorit (víme, že násobení má přednost před sčítáním), tato základní asociativita funguje stejně jako v matematice, pokud si nejsme jisti, nemusíme experimentovat a prostě se pojistíme závorkou. + + +===== Přehled operátorů ===== +Zde naleznete seznam různých operátorů. Některé z nich budeme používat a vysvětlíme si je, ale většinu z nich zatím potřebovat nebudeme, ale k tomuto seznamu se určitě budete potřebovat vracet. + + + sčítání + - odčítání + * násobení + / dělení + + % dělení modulo (zbytek po dělení) + + ++, -- inkrementace resp. dekrementace hodnoty, prefixový i postfixový zápis + = *= /= %= += -= <<= >>= &= |= ^= jednoduché přiřazení a přiřazení s výpočtem + + < menší než + > větší než + <= menší nebo rovno + >= větší nebo rovno + == rovnost + != nerovnost + + && logický součin (and) + || logický součet (or) + + ! logická negace + ~ bitová negace + + <<, >> bitový posun vlevo resp. vpravo + & bitový součin (and) + | bitový součet (or) + ^ bitový vylučovací (exkluzivní) součet (xor) + + ?: podmíněné vyhodnocení zprava doleva + + . tečka, přímý přístup ke členu struktury + -> nepřímý přístup ke členu struktury + , čárka, oddělení výrazů + + sizeof získání velikosti objektu v bytech + (typ) přetypování na typ uvedený v závorkách + + & reference (získání adresy objektu) + * dereference (získání objektu dle adresy) + +===== Porovnávání ===== +V kapitole, kde budeme probírat podmínky a cykly určitě využijeme porovnávací operátory (<,>,<=,>=,==,!=), logickou negaci (!) a logický součin a součet (&&,||). +Pokud jde o porovnávací operátory, tak vždy vrací hodnotu true (1 nebo jiná nenulová hodnota), nebo false (0), tj. pravda/nepravda. +Logický součin (&&) vrací true pouze pokud jsou obě hodnoty true. Pokud je první hodnota false, tak se druhá nevyhodnocuje (zjednodusene vyhodnocovani). +Logický součet (||) vrací true pokud je alespoň jedna z hodnot true. Pokud je první hodnota true, tak se druhá nevyhodnocuje (zjednodusene vyhodnocovani). +Logická negace vrací opak (!1 je 0, !0 je 1). + + +===== Příklady ===== + +int a = 2, b = 3, x = 4, y = 2; +b = !(b == a); //b bude true +b = (b != a); //b bude true (jde o prakticky jiny zapis stejneho vypoctu) +b = (a = 2); //casta chyba - nedojde k porovnani, ale prirazeni 2 do a a nasledne do b +x = (x <= y); //x bude false +y = !((1 <= 2)||(b = 7)); //y bude false, prirazeni 7 do b neprobehne (pouzito zjednodusene vyhodnocovani) +y = 128; //y bude true +y = 0; //y bude false +y = !y; //y bude true + + +===== Inkrementace, dekrementace,... ===== +Hodnotu proměnné můžeme změnit i jiným způsobem, než je přiřazení: + + +int a = 31, b; +a++; //a bude zvětšena o 1 (jiný zápis: a = a+1; ) +a *= 2; //a bude vynásobeno 2 (jiný zápis: a = a*2; ) +b = a++; //a bude přiřazeno do b a následně zvětšeno o 1 +b = --a; //a bude zmenšeno o 1 a nasledne prirazeno do b + + +===== Operátor sizeof() ===== +sizeof je makro preprocesoru, které nám vrátí velikost daného datového typu (viz. kapitola jednoduché datové typy) v bytech. Víme, že například celé číslo (int) zabírá v paměti většinou 2 byty, výraz sizeof(int) nám tedy vrátí u většiny kompilátorů číslo 2. + + +===== Samostatné cvičení ===== + * Vymyslete přiřazení co nejsložitějšího výrazu, jehož výsledkem bude hodnota false. + * Jakou hodnotu bude mít následující výraz: + * (((!(1 > 2 || 2 > 1)) * 2 + 4) / 2) == 7 + diff --git a/c/skripta/c_07.txt b/c/skripta/c_07.txt new file mode 100755 index 0000000..2057acd --- /dev/null +++ b/c/skripta/c_07.txt @@ -0,0 +1,90 @@ +====== Standartní vstup a výstup ====== + +===== Řádkový výstup ===== +Již jsme se seznámili s použitím funkce printf(), další užitečnou funkcí je putchar(), která vypíše jeden znak/byte. + +==== Vstup ==== +Samozřejmě budeme potřebovat také odezvu ze strany uživatele, k tomu nám budou sloužit funkce scanf(), která je opakem printf() a getchar(), která je opakem putchar(). + +Funkce getchar() nám vrací ASCII hodnotu jediného načteného znaku. + +Funkce scanf() nám oproti tomu zapíše získaná data na danou adresu v paměti, to nebudeme hlouběji rozebírat, důležité ale je, že před identifikátor proměnné musíme napsat operátor ampersand ("&"). Pokud tedy budeme například chtít načíst z klávesnice desítkové číslo, použijeme tento zápis: + + + int a; + scanf("%d", &a); + + +==== Převod řetězce na číslo ==== +Často potřebujeme, aby nám uživatel zadal číslo, z terminálu můžeme číst ale pouze znaky (případně řetězce). Naštěstí pro nás existují v Ansi C funkce, které nám dovolí uskutečnit tento převod, jsou to tyto: + + * atoi() - ascii to int + * atol() - ascii to long + * atof() - ascii to float + + +==== Souhrnné příklady ==== + + + char text[] = "Toto je nějaký text"; + int cislo = 5; + printf("Toto je text: %s a tohle cislo: %d\n", text); //Vypíše: Toto je text: Toto je nějaký text a tohle cislo: 5(a odřádkuje) + + char ascii_cislo[] = "64"; + cislo = atoi(ascii_cislo); //Priradi do promene cislo cislo urcene retezcem ascii_cislo[], tj.: 64. + + char vstup[1024]; //Toto není příliš optimální řešení, protože se v něm skrývá bezpečnostní hrozba, nebo možnost kolapsu našeho programu, pokud uživatel zadá více jak 1024 znaků... My se tímto problémem ale zatím zabývat nebudeme, ovšem nutno poznamenat, že správné řešení by bylo úplně jiné. + int vstup_cislo; + scanf("%s", &vstup); + scanf("%d", &vstup_cislo); + + +==== Další převody ==== +Další velice používanou funkcí pro převody (např. čísla na řetězec) je sprintf(). +Tato funkce pracuje obdobně, jako printf() (kterou doufám již všichni známe), s tím rozdílem, že sprintf() přijímá ještě první argument, kterým je identifikátor řetězce, do kterého bude po zformátování výsledný řetězec uložen (printf() by ho jen vypsalo). + + +==== Řešený příklad ==== + +/* calc.c + * Napište program, který načte z řádky dvě čísla, sečte je a výsledek vypíše formou rovnice. + * K získání prvního celého čísla použijte přímo scanf(), druhé převeďte z řetězce získaného ze scanf() pomocí atoi(). + * Program zkompilujte a otestujte. + */ + +#include +#include + +int main() { + char a[10]; + int x, y; + printf("Prvni scitanec: "); + scanf("%d", &x); //Prvni cislo nacteme rovnou jako dekadickou hodnotu + + printf("Druhy scitanec: "); + scanf("%s", &a); //Do retezce a ulozime ascii zapis cisla (pismenka) z klavesnice + y = atoi(a); //Do integeru y ulozime cislo ziskane z retezce a + + printf("Vysledek: %d+%d = %d\n", x, y, (x+y)); //Vypiseme vysledek +} + + +Například takto vypadá program za běhu: + harvie@harvie-ntb:~/Desktop/skripta/c$ gcc calc.c -o calc -std=c99 && chmod +x calc #kompilace + harvie@harvie-ntb:~/Desktop/skripta/c$ ./calc #spusteni + Prvni scitanec: 2 + Druhy scitanec: 3 + Vysledek: 2+3 = 5 + harvie@harvie-ntb:~/Desktop/skripta/c$ + + +==== Přesměrování vstupu a výstupu ==== +Zjistěte si, jakým způsobem umí váš operační systém přesměrovávat vstup a výstup do souborů a ze souborů, tak aby se výstup programu nevypsal na obrazovaku, ale do souboru, nebo naopak se vstup načetl ze souboru, nebo byl výstup přesměrován na vstup jiného programu. (většinou k tomu slouží operátory příkazového řádku >,>>,<,|). + +Kromě použití operátorů příkazové řádky tohoto také můžeme docílit pomocí funkce freopen() aplikované na handly stdin, stdout, nebo stderr, to ale pro nás není zatím nutné umět. + + +==== Samostatná cvičení ==== + * Upravte program tak, aby fungoval nad desetinými čísly (float) + * Předchozí program upravte tak, aby po spuštění vypsal 3 očíslované možnosti a podle zadaného čísla buď sčítal, odčítal, nebo násobil. + diff --git a/c/skripta/c_08.txt b/c/skripta/c_08.txt new file mode 100755 index 0000000..c2e9377 --- /dev/null +++ b/c/skripta/c_08.txt @@ -0,0 +1,128 @@ +====== Podmínky a cykly ====== +Tyto dvě důležité věci jsou častou součástí většiny programů. + + +===== Podmínka ===== +Podmínka je operátor, který nám umožní vykonat nějaký kód pouze pokud je splněna nějaká podmínka. Podmínka se vyhodnocuje tak, že se vypočítá hodnota výrazu předaného podmínce a pokud tato hodnota odpovídá logické pravdě (to většinou znamená nenulové číslo), vykoná se daný příkaz. + +Jednoduchá podmínka může vypadat například takto: + + +int a = 1, b = 2; +if(a + +Jaké operátory máme a jak se vyhodnocují jsme se již dozvěděli z kapitoly operátory, na druhou stranu to nemusí být na první pohled jasné, proto ještě v rychlosti shrnu alespoň srovnávací (komparační) operátory: + + == - je rovno + != - není rovno + > - větší než + < - menší než + >= - větší nebo rovno + <= - menší nebo rovno + ! - logická negace + && - logické AND (A) + || - logické OR (NEBO) + +Pokud tyto operátory použijeme na dvě čísla (operandy), výslednou hodnotou bude vždy logická hodnota (pravda/nepravda - true/false - 1/0), u většiny kompilátorů je to 0 nebo 1. Pokud tedy vyhodnocujeme podmínku (např. pomocí if()), pokaždé, když ji předáme nenulovou hodnotu, je proveden následující příkaz. Např.: + + +if(1) if(255) if(!0) printf("tento prikaz bude proveden vzdy\n"); +if(!1) if(0) printf("tento prikaz nebude proveden nikdy\n"); + + +S if souvisí ještě jeden operátor a tím je else, tím můžeme určit co se stane, když podmínka splněna nebude. + + +if(a>b) printf("a je mensi nez b\n"); else printf("a je vetsi nez b\n"); + + +===== Složený příkaz (Blok kódu) ===== +Pokud několik příkazů uzavřeme do složených závorek, začnou se vůči kódu mimo ně chovat jako jeden příkaz. V podmínkách a cyklech můžeme tedy vykonat více příkazů tam, kde bychom mohli normálně vykonat pouze jeden. např. následující kód vypíše 3x "Nejaky text\n". + + +int podminka = 1; + +if(podminka) printf("Nejaky text\n"); +if(podminka) { printf("Nejaky "); printf("text\n"); } +if(podminka) { + printf("Nejaky "); + printf("text\n"); + } + + +Následující kód pak zmenší hodnotu většího ze dvou čísel. + + +if(a>b) { + a--; +} else { + b--; +} + + +===== Cyklus while ===== +Jde o základní cyklus, jediné, čím se liší od podmínky je to, že se příkaz neustále opakuje, dokud je podmínka splněna. +Příklady: + + +while(1) printf("#"); //Budeme do nekonečna vypisovat znak '#' + +int i = 30; +while(i>10) { //Budeme zmensovat i, dokud bude vetsi nez 10 + i--; +} + + +===== Cyklus for ===== +Cyklus for je podobný cyklu while, akorát s tím rozdílem, že kromě podmínky obsahuje také příkazy, které se spustí před začátkem cyklu a pak při každé iteraci (opakování). + +Následující while cyklus + + +int i = 30; +while(i>10) { + i--; + printf("%d", i); +} + +tedy můžeme zapsat pomocí for-u i takto: + +int i; +for(int i=30;i>10;i--) printf("%d", i); + + +Což je mnohem přehlednější. + +===== Vnořené (zahnízděné) cykly ===== +Dobré je si také uvědomit, že můžeme mít například dva cykly v sobě. + +===== Řešený příklad ===== +Napište program, který vypíše za sebe čísla od 0 do 10 a zpět oddělené čárkami. + + +#include +#include + +int main() { + int x=1, a=0; + for(int i=0;i<=20;i++){ + printf("%d", a); + if(i<20) printf(","); + if(a>=10) x=(-1); + a+=x; + } + printf("\n"); +} + +//EOF + + +Výstup: + harvie@harvie-ntb:~/Desktop/skripta/c$ ./loops + 0,1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0 + +===== Samostatná cvičení ===== + * Upravte předchozí program tak, aby nepoužíval více než jeden cyklus + * Napište program, který 10x pod sebe vypíše číslice od 0 do 9. + * Upravte předchozí program tak, aby vykreslil šachovnici (8x8) z 0 a 1. diff --git a/c/skripta/c_09.txt b/c/skripta/c_09.txt new file mode 100755 index 0000000..31daebc --- /dev/null +++ b/c/skripta/c_09.txt @@ -0,0 +1,133 @@ +====== Pole ====== +Pole je datový typ skládající se z určitého počtu jiných datových typů. +Zatím jsme se s poli setkali jen jako s řetězci (řetězec je pole jednotlivých znaků, pole končí znakem s ASCII hodnotou \x00). + +Nejlepší bude, pokud si to vysvětlíme na jednoduchém příkladu. Například budeme potřebovat uložit 10 čísel int, které budou všechny sloužit k podobnému účelu, ale je možné, že se jejich počet bude v budoucnosti měnit, nebo jsme líní pro je jednotlivě deklarovat (a byli bysme hloupí, kdybychom to tak dělali). + +Použijeme tedy např. tuto deklaraci: + int cisla[10]; + +Tím jsme poprosili systém o 10*sizeof(int) bytů (neboli paměť potřebnou pro uložení 10 integerů, typicky to bude 20B). + +Nyní můžeme s čísli jednoduše pracovat, musíme si však pamatovat, že ačkoli jsme nadeklarovali 10 integerů, k prvnímu přistupujeme pomocí [0] a k desátému pomocí [9], proč tomu tak je si vysvětlíme za chvilku. + +===== Příklad ===== + +int cisla[10], a = 2; +cisla[0] = 1; +cisla[1] = 2; +cisla[a] = cisla[0]*cisla[1]+cisla[2]; +cisla[2]++; +//promenna cisla[2] drzi nyni hodnotu 5 + +cisla[10] = 18; //Zde by zase pravděpodobně došlo k pádu programu, protože se pokoušíme přistupovat k neexistující 11. položce pole. + + +===== Uložení pole v paměti ===== +držme se naší deklarace z předchozího příkladu, tedy: + int cisla[10]; +V tom případě jsme si říkali, že bude v paměti alokováno 10*sizeof(int) bytů, to bude vypadat následovně: + + __ __ __ __ __ __ __ __ __ __ + |00|00|00|00|00|00|00|00|00|00| + -- -- -- -- -- -- -- -- -- -- + ^ ^ + |_ Toto je adresa &cisla |_ Toto je adresa &cisla+9*sizeof(int) (neboli cisla[9]) + (neboli cisla[0]) + +Pokud si tedy zkusíme vytisknout printf("%d\n", &cisla);, získáme adresu v paměti (to dělá operátor &), na které je naše pole uložené, touto adresou je obyčejné číslo, je ale zvykem zapisovat ho šestnáctkově, toto je pro nás ale zatím dostačující. + +Tím, že použijeme zápis cisla[0] dojde k tomu, že získáme přístup k sizeof(int) bytům na adrese &cisla, tedy k prvnímu integeru, když chceme přistupovat k druhému integeru v poli použijeme cisla[1], protože tím se dostáváme z adresy &cisla o jeden int dále (tedy: &cisla+1*sizeof(int)), je tedy zřejmé, že pokud se pokusíme pracovat s cisla[10], octneme se již v části paměti, která nepatří našemu programu a náš program bude ukončen, protože v jiném případě by náš program mohl ovlivňovat práci jiného programu. + + +===== Zjištění velikosti pole ===== +Je možné, že neznáme velikost pole, a potřebujeme ho zpracovat (např. v cyklu), k tomu opět použijeme operátor sizeof(). V následujícím příkladu si také můžete všimnout, že při deklaraci pole můžeme jeho velikost určit jinou celočíselnou proměnnou (to je možné až v novějších verzích jazyka C). +Následující kus kódu ukazuje, jak zjistit a vypsat velikost pole. + + +int i = 30; +int cisla[i]; +//Nejaky jiny kod +printf("Pocet cisel: %d\n", sizeof(cisla)/sizeof(int)); + + +Příkaz sizeof(cisla) nám vrátí počet bytů, které pole skutečně zabírá v paměti, to může být různé. nás ale zajímá kolik prvků (int) pole má a s kolika můžeme ve skutečnosti pracovat. K tomu musíme ještě toto číslo vydělit hodnotou sizeof(int) (nebo sizeof(jiny_typ_naseho_pole)), ta totiž určuje, kolik každý prvek pole zabírá v paměti. + +Když si to shrneme: Víme, kolik místa zabírá pole v RAMce a víme, kolik má zabírat jeden jediný prvek, jednoduše tedy vydělíme (vrátíme se ve vzpomínkách do 2. třídy ZŠ ;) a máme požadované číslo, pokud nás ovšem zajímá nejvyšší "offset" (to číslo v hranatých závorkách), jaké můžeme použít, nesmíme ještě zapomenout odečíst 1. + +===== N-rozměrná pole ===== +Můžeme také vytvářet mnohorozměrná pole (např.: dvou-rozměrná, tří-rozměrná, sto-rozměrná, n-rozměrná), takové mnohorozměrné pole je laicky řečeno pole polí, nebo pole polí polí polí polí, typickým příkladem je pole řetězců. + +Deklarace takového pole může vypadat takto: + + +int a[3][40]; //a je pole 40ti polí o 3 integerech +//Podobná pole si většinou představujeme jako 3x40 čtverečků (40 je výška) +char c[4][6][8]; +//Takové pole si pro změnu můžeme vizualizovat jako 8mi patrový kvádr, přičemž každé patro se zkládá z 4x6 kostiček (každá kostička drží nějaký znak). + + +U složitějších polí si můžeme představit například několik takových kvádříků uspořádaných do několika polic v několika skříních v několika řadách,... +Prostě jakkoli. + + +Pokud máme například pole int pole[2][3], pak pole[0] je pole 3 integerů jako např. int druhe[3]. + +Ostatní práce s poli je naprosto analogická k polím jednorozměrným. + + +===== Řešený příklad - zpracování pole v cyklu ===== + + +Toto je velmi často používaná věc! Více se dozvíte v kapitole "podmínky a cykly", tady jen uvádím jednoduchý příklad. +Můžeme si zde všimnout dvou totožných cyklů, přičemž jeden je while() a druhý for(). + + +/* arrays.c + * Napiste program, ktery naplni pole integeru nahodnymy cisly a potom je vypise. + * Pouzijte cykly for i while + */ + +#include +#include + +int main() { + int i, cisla[10]; + + i=0; + while(i + +===== Samostatná cvičení ===== + * Pomocí dvou vnořených cyklů naplňte dvojrozměrné pole znaků (char[x][y]) šachovnicí (8x8) z 1 a 0, pomocí dalšího vnořeného cyklu ji pak vytiskněte + * Velikost šachovnice bude možno libovolně měnit pomocí dvou proměnných (int x = 8, y = 8;). + * Očekávaný výsledek: +01010101 +10101010 +01010101 +10101010 +01010101 +10101010 +01010101 +10101010 + + * Upravte program z předchozího cvičení tak, aby byly protilehlé rohy spojeny osmičkami. + * Upravte program z předchozího cvičení tak, aby byl čtverec lemován nulami. + *Očekávaný výsledek: +00000000 +08101080 +01810800 +00188010 +01088100 +00801810 +08010180 +00000000 + diff --git a/c/skripta/c_10.txt b/c/skripta/c_10.txt new file mode 100755 index 0000000..2be8fb9 --- /dev/null +++ b/c/skripta/c_10.txt @@ -0,0 +1,82 @@ +====== Argumenty programu ====== +Další možností, jak můžeme našemu programu předat nějaká data, je to, že mu je zdělíme už při spouštění. To se provádí pomocí tzv. argumentů (můžeme se také setkat s pojmem parametry), ty předáme programu tak, že je napíšeme za jeho název oddělené mezerami. To je přesně to, k čemu dochází pokud např. ve vašem operačním systému otevíráte nějaký textový dokument, video nebo cokoli v jiném programu. V takovém případě grafické prostředí, které pravděpodobně používáte k ovládání počítače vyvolá příkaz podobný těmto: + + * prehravac_filmu film.avi + * cesta/super\ jukebox jedna\ pisnicka.ogg "druha - pisnicka.mp3" + * "c:\program files\msoffice\word\word.exe" dokument.doc + +Můžeme si všimnout, že všechny parametry jsou odděleny mezerami, pokud je nutné, aby parametr obsahoval mezeru, dáme ho buď do uvozovek, nebo před mezeru dáme zpětné lomítko (to se na windows nepoužívá), pokud ovšem potřebujeme, aby argument obsahoval uvozovku, dáme před ni také zpětné lomítko. + +Také by bylo dobré poznamenat, že prvním argumentem (i když se takto neoznačuje) je vždy název programu. + +===== Argumenty z hlediska programátora ===== +Operační systém předává našemu programu argumenty pomocí dvou proměnných. +První z nich je int argc, která obsahuje počet argumentů, pokud tedy například předáme programu dva argumenty, tak bude platit, že argc == 3, protože kromě těchto dvou souborů bylo programu předáno ještě jméno spustitelného souboru (tedy název programu). +Druhou proměnnou, která už obsahuje data konkrétních argumentů je char *argv[], jde o pole řetězců, to tedy znamená, že např. argv[0] bude první argument (název programu), argv[1] druhý, atd... + +Aby náš program mohl od systému parametry převzít, musíme je nadeklarovat v hlavičce funkce main(), tedy např.: + + +int main(int argc, char *argv[]) { + //Telo programu +} + + +===== Padám, padáš, padáme! ===== +V případě, že by se náš program pokusil přistupovat k nezadanému argumentu, dojde k jeho pádu, protože operační systém toto místo (kde náš argument není) již používá k jiným účelům a je nežádoucí, aby k němu náš program získal přístup. Je tedy vhodné pomocí hodnoty argc vždy ověřovat, jestli konkrétní argument existuje. V opačném případě bychom se mohli od operačního systému dočkat ukončení programu a vypsání podobné chybové hlášky: "Neoprávněný přístup do paměti (SIGSEGV)", nebo známější anglická hláška "Segmentation fault. Core dumped.". + +Takové ošetření by mohlo vypadat například takto: + + +int main(int argc, char *argv[]) { + if(argc > 1) { + printf("Byl zadán argument %s\n", argv[1]); + } else { + printf("Nebyl zadán žádný argument!\n"); + } +} + + +===== Řešený příklad ===== + +/* args.c + * Napiste program, ktery vypise pocet parametru, prvni parametr a nasledujici dva secte jako cela cisla a vypise ve tvaru rovnice + */ + +#include +#include + +int main(int argc, char *argv[]) { + int x, y; + printf("Pocet parametru: %d\n", argc); + printf("Jmeno programu: %s\n", argv[0]); + x = atoi(argv[1]); + y = atoi(argv[2]); + printf("Prvni scitanec: %d\n", x); + printf("Druhy scitanec: %d\n", y); + printf("Vysledek: %d+%d = %d\n", x, y, (x+y)); +} + + +===== Výstup programu: ===== + +harvie@harvie-ntb:~/Desktop/skripta/c$ ./args 2 3 +Pocet parametru: 3 +Jmeno programu: ./args +Prvni scitanec: 2 +Druhy scitanec: 3 +Vysledek: 2+3 = 5 + +Nyní se program pokusí přistupovat k neexistujícímu argumentu: + +harvie@harvie-ntb:~/Desktop/skripta/c$ ./args 2 +Pocet parametru: 2 +Jmeno programu: ./args +Neoprávněný přístup do paměti (SIGSEGV) + + +===== Samostatná cvičení ===== + * upravte předchozí příklad tak, aby kontroloval počet parametrů a v případě jejich neexistence použil místo daného sčítance nulu. + * Napište program, který pomocí cyklu while vypíše všechny argumenty pod sebe. + * Napište program, který pomocí cyklu for vypíše všechny argumenty pod sebe. + diff --git a/c/skripta/c_11.txt b/c/skripta/c_11.txt new file mode 100755 index 0000000..9bb7b9b --- /dev/null +++ b/c/skripta/c_11.txt @@ -0,0 +1,82 @@ +====== Preprocesor ====== +Už jsme si nastínili, že než se námi napsaný zdrojový kód dostane do kompilátoru, projde vyčištěním, doplněním a částečnou optimalizací v tzv. preprocesoru. Nyní si ukážeme, jak používat některé jeho direktivy (funkce), předtím je snad jen dobré poznamenat, že direktivy preprocesoru se označují znakem # (hash,mřížka,křížek,sharp). + +===== Inkludování - vkládání jiného souboru ===== +Preprocesor nám umožňuje vložit do zdrojového kódu veškerý obsah jiného souboru, této direktivy využijeme např. při odděleném překladu, nebo při vkládání hlavičkových souborů různých knihoven. Například inkludováním si zpřístupníme Ansi C funkce pro práci s textovým vstupem a výstupem (klávesnice, obrazovka, soubory). + +Vložení probíhá pomocí direktivy pomocí direktivy #include, např.: + + +#include //Se špičatými závorkami se soubor hledá v adresáři, kde má překladač standartní hlavičkové soubory (jako je stdio.h) +#include "mujprogram.h" //S uvozovkami se soubor hledá ve stejném adresáři, jako je náš zdrojový kód, pokud není nalezen, hledá se ve standartním adresáři +#include NAZEV_KONSTANTY //Viz. symbolické konstanty + + +Musíme si ale dávat pozor, aby jsme omylem neinkludovali sami sebe, nebo jiný soubor, který inkluduje nás, to by pravděpodobně vedlo k zaseknutí preprocesoru v nekonečné smyčce. Jak tomu předcházet: viz. podmíněný překlad. + + +===== Symbolické konstanty ===== +Rozdílem použití této konstanty (ve srvonání např. s definicí běžné konstanty) je to, že ji nelze po kompilaci měnit, protože preprocesor představuje z tohoto hlediska pouze pomůcku, která vyhledá v kódu identifikátory makra a nahradí je hodnotou tohoto makra (asi jako to dělá váš oblíbený textový editor pomocí funkce "najít a nahradit"). To je výhodné např. pro uchování číselných hodnot (dříve se makra používala k definici velikosti statického pole, dnes již musí Ansi C podle normy umět alokovat pole za běhu, aby bylo možné jeho velikost určit pomocí proměnné), naopak jsou makra nevhodná například pro uchování větších řetězců, které používáme na více místech (rozkopírování několika stejných desítek bytů na několik míst v kódu nikomu ještě nepřidalo). + +Použití: + +Nahradit všechny výskyty NAZEV_MAKRA textem retezec: + #define NAZEV_KONSTANTY [retezec] + +Zrušit definici makra NAZEV_KONSTANTY: + #undef NAZEV_KONSTANTY + +Jak jste si mohli všimnout, je zvykem psát identifikátory symbolických konstant celé velkými písmeny (opět až na vyjímky), abychom je oddělili od normálních proměnných. + +===== Makra ===== +//Pokud jste ještě nečetli kapitolu Funkce, tak následující odstavec klidně přeskočte.// + +Také existují ještě zajímavější druhy symbolických konstant a těmi jsou makra, ty se liší tím, že obsahují (podobně jako funkce) argumenty, takové nám mohou nahradit menší funkci, to sice také prodlužuje kód (a velikost výsledného programu), ale nadruhou stranu tím ušetříme čas na volání funkce (což může být někdy poměrně dost), o případných zbytečných automatických přetypování a přiřazování ani nemluvě. + +Použití: + #define nasobek(a,b) ((a)*(b)) + +zápis: + nasobek(1,2) +se potom rozvine na: + ((1)*(2)) + +Zde musíme dát pozor na závorky, pokud bychom napsali jen: #define nasobek(a,b) a*b, mohlo by se nám potom stát, že makro použijeme (slovo zavoláme by nebylo příliš vhodné) například tímto způsobem: + int i = nasobek(2+3,1+2)*7 +pak by se makro rozvinulo v: + int i = 2+3*1+2*7 +a to je úplně jiný výraz než námi předpokládaný + int i = ((2+3)*(1+2))*7 + +===== Podmíněný překlad (podmínky preprocesoru) ===== +Podmíněný překlad je možnost preprocesoru vypouštět některé části kódu na základě toho, jestli je definována nějaká symbolická konstanta, typicky jde o potlačení ladících výpisů (které by nám v případě, že je zakážeme pomocí běžné podmínky if() a například čísla, kterým je ovládáme zbytečně okupovali prostor v paměti a výkon procesoru). + +Použití: + + +#define LADIT //Budeme ladit + +int main() { + //nejake prikazy + #if defined(LADIT) + //ladici prikazy + #endif +} + + +Dalším využitím podmíněného překladu je například předcházení zacykleným inkludováním, následující soubor se nenainkluduje dvakrát: + + +#define UZ_INKLUDOVANO +#ifndef UZ_INKLUDOVANO + //Zamysleny obsah souboru +#endif + + +===== Předdefinované symbolické konstanty preprocesoru ===== +Z preprocesoru můžeme také zjišťovat různé informace a zařídit se podle nich, k tomu nám pomůžou předdefinované symbolické konstanty mezi ně patří např.: + * Datum a čas překladu + * Soubor a řádek ve zdrojovém kódu + * Operační systém + * Verze C / Podpora C++ + * Další informace o cílovém systému diff --git a/c/skripta/c_12.txt b/c/skripta/c_12.txt new file mode 100755 index 0000000..45e3db3 --- /dev/null +++ b/c/skripta/c_12.txt @@ -0,0 +1,62 @@ +====== Funkce - úvod ====== +Při programování neustále voláme nějaké funkce, funkci, která nám vypíše to, zjistí tamto, vypočítá tohle, ukončí program, otevře soubor, čte ze souboru a takřka cokoli složitějšího děláme pomocí funkcí. + +===== Volání funkce ===== +Volání funkce (jak už víme) probíhá například zápisem: + + +int b = 4; +int y = secti(1, b); + + +Podobný zápis předá jedničku a hodnotu proměnné int b funkci secti() a do proměnné x nám uloží návratovou hodnotu funkce (konkrétně tohoto callu - neboli zavolání). Tuto hodnotu není nutné nikam ukládat. Můžeme ji také např. použít v jiném výrazu, jako argument jiné funkce, nebo dokonce prostě zahodit/nepoužít. + + +===== Definice funkce ===== +Ovšem se nám může stát, že budeme potřebovat použít jeden algoritmus, nebo blok kódu na více místech našeho programu a pokud bychom ho jen rozkopírovali, nebo (dokonce) opsali, byli bysme pro smích všem programátorům (včetně začátečníků). Napíšeme si tedy vlastní funkci, je to jednoduché: + + +//Definice nasi prvni funkce - nachazi se mimo funkci main() +int secti(int prvni, int druhe) { //Sem za hlavicku funkce je dobre psat jednoduchy popis funkce (napr. "secte dve cisla int") + //Telo funkce secti(): + int x; + x = prvni+druhe; //Secteme prvni a druhe a ulozime do x + return x; //Vratime x +} //Pozor!!! tady jiz neni strednik + +//A nyni muzeme vyzkouset nas stary dobry ukazkovy kod +int main(int argc, char *argv[]) { //Volani ale jiz provedeme z funkce main(): + int b = 4; + int y = secti(1, b); + printf("%d\n", x); +} + + +===== Pravidla ===== +Při psaní nových funkcí samozřejmě také platí jistá pravidla, například to jsou: + + * Identifikátor nové funkce nesmí být použit ničím jiným (zdá se to zřejmé, ale pokud bychom například chtěli nadefinovat novou funkci printf(), tak neuspějeme, i když platí jisté vyjímky). + * Typ vraceného čísla (return hodnoty) musí být stejný jako typ funkce například funkce int secti() nemůže vracet hodnotu čísla float x, můžeme se také spolehnout na tzv. automatické přetypování tedy např.: +int secti(int a, int b) { return a+b; } //Tato funkce je hezčejší a rychlejšejší než ta, co jsme si ukázali. + + * Na konci definice fce nepíšeme (stejně jako například za cykly) středník! (jde o hloupou, ale častou chybu). + + +===== Parametry funkce ===== +Funkci předáváme parametry (tím, jak to ve skutečnosti probíhá v procesoru se zatím zatěžovat nebudeme), jsou to např. nějaká čísla, se kterými můžeme ve funkci dále pracovat. Rozlišujeme dvoje parametry - tzv. skutečné parametry a tzv. formální parametry. + + * Skutečný parametr je ten, kterým funkci voláme, tedy například při volání secti(2,3); jsou 2 a 3 skutečnými parametry funkce secti(). + * Formální parametr je ten, se kterým pracujeme v těle funkce, tedy například ve funkci s hlavičkou int secti(int prvni, int druhe); tyto dvě a všechny ostatní proměnné, které vytvoříme v těle funkce nijak neovlivňují zbytek programu a mohou se jmenovat stejně (mít stejný identifikátor) jako např. jiná proměnná ve funkci main(). + + +===== Návratová hodnota ===== +Návratová hodnota je cokoli, co funkce vrátí (zavoláním funkce return(), nebo dosažením konce funkce), vždy jde o stejný datový typ, jako je typ funkce (návratová hodnota je jakousi hodnotou této funkce). Pokud nezavoláme funkci return(), ale funkce se ukončí dosažením konce svého kódu, je automaticky vrácena 0. + +===== Cvičení ===== + * Vysvětlete zjednodušeně, co znamená hlavička funkce main(): int main(int argc, char *argv[]) { /*Nejaky kod*/ } + * Čím je funkce main() specifická? + +===== Samostatná cvičení ===== + * Napište co nejjednodušší funkci, která korektně umocní dvě čísla typu float (jedno druhým). + * Napište funkci, která vypíše "hello, world\n" tolikrát, kolik bude hodnota jediného parametru typu int. + diff --git a/c/skripta/c_13.txt b/c/skripta/c_13.txt new file mode 100755 index 0000000..2a410b7 --- /dev/null +++ b/c/skripta/c_13.txt @@ -0,0 +1,101 @@ +====== Globální proměnné, přetěžování funkcí, funkční prototypy, rekurzivní funkce ====== +Minule jsme si ukázali základy práce s funkcemi, dnes si to ještě o něco ztížíme. + +===== Globální proměnná ===== +Říkali jsme si, že pokud ve funkci pracujeme s proměnnými, tyto neovlivňují zbytek programu, naopak ani nemůžeme pracovat s jinými proměnnými v programu (funkce běží v jiném tzv. kontextu). Pokud bychom ale stejně chtěli nadefinovat proměnnou, která bude použitelná v celém programu (má tzv. Globální viditelnost), můžeme to udělat například její definicí/deklarací mimo funkci main, takový kód by vypadal zhruba takto: + + +int vypis_x() { printf("x = %d\n", x); } //Vypise globalni promennou x +int inc_x() { x++; } //Zvetsi globalni promennou x o 1 + +int x = 2; //Globalni prommena x = 2 + +int main(int argc, char *argv[]) { //Hlavni funkce (ta se vetsinou nekomentuje!) + vypis_x(); + x = 4; //x = 4 + inc_x(); //x = 5 + vypis_x(); + x = inc_x(); //x = 0 (funkce inc_x() sice x zvysi na 6, ale nasledne vrati hodnotu 0, ktera je zde do x prirazena) + vypis_x(); +} + + +Můžeme si všimnout, že když definujeme novou funkci, děláme to také raději mimo fci main(), tato naše funkce je pak "viditelná" (dostupná) kdekoli. + +===== Přetěžování funkcí ===== +Psal jsem, že identifikátor funkce nesmí s ničím kolidovat. To není tak úplně pravda. Můžeme mít několik funkcí se stejným jménem, ale jiným počtem neby typem parametrů, nejlépe to je vidět na následujícím příkladu: + + +int secti(int a, int b) { return a+b; } +int secti(int a, int b, int c) { return a+b+c; } +int secti(char c) { putc c; } + + +Pak pomocí volání secti() můžeme sečíst dvě, nebo tři čísla (a nemusíme tedy přemýšlet, jak se jmenuje funkce na sečtení tří čísel), pokud zavoláme secti() s jedním parametrem typu char, tak dokonce tato funkce udělá něco úplně jiného a to je vypsání znaku (což je stejně nečekané, jako sčítání s jedním číslem ;). + + +===== Funkční prototypy ===== +Zatím jsme vždy funkci definovali jen před místem, kde jsme ji použili (to je logické, protože proměnnou také musíme vždy nejdříve nadefinovat, než s ní začneme pracovat). Mohlo by se ale stát, že otevřeme soubor se zdrojovým kódem našeho programu, a než se dostaneme k funkci main(), která obsahuje hlavní logiku našeho programu, budeme se muset prokousat spoustou pomocných funkcí, které pro nás nemají tak velký význam. + +Můžeme tedy funkci nad main() jen "nadeklarovat" (toto označení není úplně na místě, ale přesto je takřka pravdivé) a napsat (nadefinovat) ji níže. Tomu se říká použití funkčního prototypu. Funkční prototyp je vlastně pouze hlavička dané funkce zakončená středníkem. Funkční prototyp také nemusí obsahovat seznam parametrů (a jejich datových typů), v tom případě ale funkci nelze přetěžovat a kompilátor neví jaké parametry má očekávat (jede odzhora dolů) a proto nemůže opravit chyby jako volání s nesprávným počtem, nebo typem parametrů, které takřka vždy musí skončit s oblíbenou hláškou "Segmentation fault", neboli neoprávněný přístup do paměti. + +V případě, že používáme funkční prototypy, tak stručný komentář píšeme k prototypu, nikoli k tělu funkce. + +Bývá také zvykem, že se funkční prototypy dávají do hlavičkového souboru (viz. kapitola Preprocesor), který se jmenuje stejně jako náš zdrojový kód, s tím rozdílem, že místo přípony .c má příponu .h, to je užitečné, pokud chceme tyto funkce používat i v jiných souborech našeho projektu (tomu se říká tzv. oddělená kompilace). Tento hlavičkový soubor se pak includuje nejen do našeho zdrojového kódu, ale do všech dalších souborů, které chtějí mít k těmto funkcím přístup. + + +int tisk(int x); //Funkce vypise prvni parametr jako int a vrati jeho dvojnasobek (pozor, tady strednik pro zmenu je!) +//int tisk(); //Toto je druha moznost zapisu funkcniho prototypu, tedy bez parametru... + +int main(int argc, char *argv[]) { + tisk(4); +} + +int tisk(int x) { + printf("%d\n", x); +} + + +===== Rekurzivní funkce ===== +Rekurzivní funkce je funkce, které volá sama sebe, musíme ale pamatovat na to, že pokud nebude počet rekurzivních volání konečný, tak bude nekonečný, to v praxi znamená, že takový program se logicky zasekne v nekonečné smyčce, což vyústí v jednu ze tří věcí. Buď dojde paměť, nebo jiné prostředky, program začne velmi špatně hospodařit s časem CPU a "vycucne" výkon, který potřebují jiné programy, nebo zůstane stát na místě a dokola opakovat nějakou jednoduchou akci. + +Možná není na první pohled zřejmé, k čemu jsou takové funkce dobré, uvedu vám tedy příklad z praxe, který jsem sám několikrát použil a je používaný ve spoustě programů. Představte si, že potřebujete vypsat, nebo prohledat obsah adresáře včetně podadresářů a jejich podadresářů, atd... Jak to tedy uděláme? Jednoduše si napíšeme funkci, která otevře zvolený kořenový adresář (jeho jméno se předává jako parametr) a projíždí si ho položku po položce, když narazí na soubor, tak ho zpracuje (např. vypíše jeho název), pokud ale narazí na adresář, tak ho nejen vypíše, ale potom ještě rekurzivně zavolá sama sebe a předá si cestu k tomuto adresáři tak, že k názvu kořenového adresáře připojí jméno adresáře k prohledání, aby vznikla celá cesta. Dovedete si tedy představit, že ve finále si tímto postupem projedeme všechny složky a podsložky a jejich podsložky ve zvoleném adresáři. + +Takže rekurzivní funkce jsou velmi výhodné, je-li třeba operovat například nad nějakými stromovými strukturami, na druhou stranu se ale dají použít i jinak než ke zkoumání nebo vytváření (např. kreslení) stromů. + +Tady je příklad jednoduché rekurzivní fce: + + +int rekurze(int x, int y, int z) { + if(x>z) return(rekurze(x-y, y, z)); + return(x); +} + + +Pokud tuto funkci zavoláme (např.: rekurze(10, 1, 0);), bude volat sama sebe a postupně odečítat od zadaného parametru x parametr y, dokud nebude platit, že x<=z, pak vrátí x, v našem případě bude návratem hodnota 0. + + +===== Samostatná cvičení ===== + * Napište rekurzivní funkci, která vypíše "hello, world\n" tolikrát, kolik bude hodnota jediného parametru typu int. + * Nadefinujte globální proměnnou typu int a napište funkci, která zvětší její hodnotu o číslo zadané jako parametr. + * Tuto funkci přetěžte a udělejte druhou, která sečte nejdřív dva parametry dohromady a pak toto číslo teprve přičte k vaší globální proměnné. + * Pro tyto dvě funkce vytvořte funkční prototypy a přesuňte jejich kód pod funkci main(), ve které je odzkoušejte. + * Zkuste vypočítat, kolikrát se zavolá fce rekurze() z výkladu (výše) při volání rekurze(10, 1, 0);, potom to vyzkoušejte, použijte k tomu globální proměnnou int a. + * Co funkce vratí pro hodnoty 4 a 3?: +int ff1(x, y) { + if (x>0) return ff1(x-1, y)+1; + return y; +} + + * Co funkce vratí pro hodnoty 2 a 7?: +int ff2(x, y) { + if (x < y) return ff2(x+1,y); + return x; +} + + * Co funkce vratí pro hodnoty 2 a 4?: +int ff3(x, y) { + if (x == 0) return 0; + return ff3(x-1,y)+y; +} + \ No newline at end of file diff --git a/c/skripta/c_14.txt b/c/skripta/c_14.txt new file mode 100755 index 0000000..f5869f7 --- /dev/null +++ b/c/skripta/c_14.txt @@ -0,0 +1,70 @@ +====== Pointery (ukazatele) ====== +Doteď platilo, že když jsme potřebovali pracovat s nějakým kusem paměti (proměnnou), jednoduše jsme ji nadeklarovali (nebo nadefinovali) a kompilátor se za nás postaral o to, aby se po spuštění programu nalézala v paměti a my s ní mohli pracovat. + + +===== Referencování ===== +Základní operací kterou musíme znát je použití referenčního (& - Ampersand) a dereferenčního (* - Hvězdička) operátoru. + +Pokud aplikujeme referenční operátor na některou z proměnných (nebo cokoli jiného, co je fyzicky uložené v paměti), dostaneme adresu v paměti, na které je tento objekt umístěn. Např. následující kód, který by normálně měl vytisknout hexadecimální (šestnáctkovou) interpretaci hodnoty proměnné cislo nám díky operátoru "&" před identifikátorem proměnné vytiskne adresu v paměti (na které je samozřejmě uložen obsah naší proměnné). + + +int cislo = 2; +printf("0x%X\n", &cislo); + + +Nutno ještě podotknout, že bývá zvykem, že se šestnáctkové číslo (to, které vypíšeme pomocí "%x" nebo "%X") pro rozlišení od čísel v jiných číselných soustavách (desítkové, dvojkové, osmičkové) zapisuje s "0x" na začátku, formátovací řetězec pro 'slušné' vypsání čísla v šestnáctkovém tvaru pomocí standartní funkce printf() (adresy v paměti a adresy vůbec nebývá zvykem udávat jinak než šestnáctkově) by tedy vypadal například takto: "0x%X", s odřádkováním pak takto: "0x%X\n". + +A proč se operátoru "&" říká "referenční"? Je to jednoduše proto, že nám vrací referenci (neboli odkaz) na proměnnou a sice v podobě její adresy. + + +===== Dereferencování ===== +Ještě užitečnější možností, než je referencování je možnost tzv. dereference. Dereferencování nám umožňuje naopak pracovat s pamětí, pokud známe její adresu. Dereferencování probíhá pomocí operátoru "*". To můžete vidět na následujícím příkladu: + + +int data, adresa; + +data = 32; //Inicializace promenne +adresa = &data; //Do promenne adresa ulozime adresu promenne data (pomoci referencovani) +printf("0x%X\n", adresa); //Vytiskneme si adresu +printf("%d\n", *adresa); //Na promennou adresa pouzijeme dereferencni operator a vytiskneme tedy hodnotu promenne data + +*adresa = 23; //Zapiseme 23 do pameti urcene adresou ulozenou v promenne adresa +printf("%d\n", data); //Tim, ze jsme zapisovali na adresu ziskanou referenci romenne data, jsme zmenili i hodnotu promene data + +//Nyni lze tedy tvrdit, ze hodnoty data a *adresa jsou to same. +//Stejne jsou i hodnoty &data a adresa. + + +Pokud používáme proměnnou pouze na uložení jiné adresy a pomocí dereference přes ní přistupujeme k datům na této adrese, takové proměnné říkáme pointer. Toto označení není špatné ani v případě, že jím titulujeme přímo tuto adresu. + +Dalším pěkným příkladem může být také toto: + + +int data; +*(&(*(&data))) = 32; //To je to same jako: data = 32; + + +===== Neoprávněný přístup do paměti ===== +Neoprávněný přístup do paměti je zatím asi jediná chyba, která nás při programování potkala, pokud tedy mluvíme o chybách, které neodchytí kompilátor (nebo preprocesor), ale nastanou až za běhu programu. V podstatě jde o to, že pokud se program pokusí číst nebo zapisovat do paměti, kterou si nealokoval (tudíž je buď volná, nebo patří někomu jinému), systém ho zarazí a z bezpečnostních důvodů ukončí (takový přístup může signalizovat, že se někdo pokouší program nabourat, nebo sám o sobě způsobit jiné škody). + +Jak si takový neoprávněný přístup nasimulovat? + + +int *a, b; +a = 31337; //Toto je vymyslena adresa, ktera pravdepodobne nepatri nasemu programu (teoreticky by mohla, ale pravdepodobnost je celkem miziva) +*a = 32; //Pokusime se zapsat na neplatnou adresu -> Pad programu +b = *a; //Pokusime se cist z neplatne adresy -> Taktez Segmentation fault (sem se uz program nedostane, protoze havaroval) + + +===== Správná deklarace pointerů ===== +Všiměte si, že jsem v nadpisu použil slovo deklarace pointerů, nikoli definice. To proto, že adresa uchovávaná v pointeru by měla být zjištěna až za běhu programu. Pokud jí zapíšeme přímo do kódu, tak program buď spadne, nebo bude-li fungovat, tak jenom někde a někdy, podle toho, co na dané adrese je. + +Chceme li tedy vytvořit pointer například na integer, uděláme to takto: + + +int *cislo, a; +cislo = &a; //inicializace + + +S tím jsme se již setkali v předchozích příkladech, ale já jsem to záměrně nechal až na konec. +Proč je u pointeru nutné určit, na jaký datový typ bude ukazovat si povíme později. Pro nás je ale důleřité, že pointer nezabírá tolik místa, jako může být nutné pro uložení dat, která budou na cílové adrese. To si jednak musíme uvědomit při deklaraci a za druhé nám to může urychlit program tak, že nějaké funkci předáme pouze pointer (ta ho musí očekávat) a funkce tak pracuje skrze tento pointer (adresu) přímo nad našimi daty, aniž by se vytvářela jejich kopie v kontextu funkce. Této možnosti se říká předání odkazem a dalo by se to přirovnat k situaci ze skutečného života, kdy potřebujete vykonat nějakou stavební úpravu a můžete (s nadsázkou) buď odnést celý dům k zedníkovi, nebo můžete zedníkovi donést jen papírek s adresou tohoto domu (tedy pointer). \ No newline at end of file diff --git a/c/skripta/c_15.txt b/c/skripta/c_15.txt new file mode 100755 index 0000000..fc4bcd1 --- /dev/null +++ b/c/skripta/c_15.txt @@ -0,0 +1,118 @@ +====== Dynamická alokace paměti ====== +Než začneme s dynamickou alokací paměti, je ještě je dobré vědět, že je slušné, dobré, praktické, důležité a nevím jaké ještě to, že pokud máme pointer na neexistující objekt (v C znamená pojem objekt něco jiného, než v oběktových, nebo objektově orientovaných jazycích), tak bysme měli tento pointer nastavit na hodnotu NULL (my se spokojíme s přiřazením 0), takovému pointeru se pak říká nulový pointer, nebo pointer na NULL. Například takto: + + +int a, b; +a = &b; +*a = 32; +a = NULL; //Zrusime pointer + + +===== Funkce pro dynamické přidělování paměti ===== +Abychom mohli využívat tyto funkce, musíme nainkludovat hlavičku stdlib.h (tedy: #include ). Je pravděpodobné, že na některých kompilátorech (především těch z GNU rodiny) by se vám program zkompiloval i bez vložení tohoto hlavičkového souboru, protože jde o jeden z nejzákladnějších, tak je možné, že již je nainkludován, ale to není dobře, protože pokud se takový program pokusíte zkompilovat jinde, tak se vám to nepodaří, to také vyčtete z varovných hlášek, kterými vás gcc poučí, pokud soubor nenainkludujete. Jde především o funkce malloc() a free(). První z nich nám umožní za běhu programu alokovat potřebné množství paměti, ta druhá ji potom zase dokáže uvolnit (tedy navrátit operačnímu systému a umožnit tak její využití k jiným účelům). + +===== Funkce malloc() ===== +Tato funkce přijímá jediný parametr, kterým je počet bytů, které si má od OS vyžádat, potom vrátí pointer na alokované místo (jeho první byte). Pokud se z nějakého důvodu nepodaří tuto paměť získat, malloc() vrací nulový pointer. Když potřebujeme alokovat např. integer, musíme si zjistit, jakou velikost má int na našem kompilátoru. Již víme, že se to provádí pomocí operátoru sizeof(), tedy sizeof(int). Následující příklad ukazuje správnou alokaci a inicializaci dvou integerů, jeden staticky, druhý za běhu programu: + + +#include + +int main() { + int a, *b; + b = NULL; //Pro jistotu a ze zvyku priradime do b nulu (abychom se omylem nepokusili pracovat s cizi pameti) + + a = 2600; + + b = malloc(sizeof(int)); //Pokusime se alokovat pamet o velikosti integeru + if(!b) { //Pokud se nam nepodari alokovat pamet + printf("Chyba pri malloc()!\n"); //Vypiseme chyb. hlasku + exit(1); //A skoncime s chybovym kodem 1 + } + + *b = 1337; +} + + +Možná je dobré vědět, že operačnímu systému se nemusí vždy hodit množství paměti, jaké vyžadujete a přidělí vám trochu víc (nebo samozřejmně nic, tedy NULL). + + +===== Funkce free() ===== +Funkci předáme jako parametr pointer/adresu již předem alokované paměti, funkce se postará o to, aby byla tato paměť uvolněna a navrácena OS k dalšímu použití. Věřím, že na demonstraci postačí jednoduchý příklad: + + +int *a; +a = NULL; +a = malloc(sizeof(int)); +if(!a) { + printf("Chyba pri malloc()!\n"); + exit(1); +} +*a = 31337; + +free(a); //Uvolnime pamet +a = NULL; //Pointer, ktery ukazuje na "cizi pudu" nastavime na NULL + + +Takže si musíme pamatovat, že takový pointer, který nám zůstal po uvolnění funkcí free() musíme co možná nejdříve nastavit na NULL. Nebývá žádnou zvláštností, když se tyto dvě neoddělitelné operace zapisují na jeden řádek (kompaktnější vzhled a logika kódu): + + free(a); a = NULL; + + +===== Kam se starým smetím? ===== +Může se nám také díky nějaké chybě v logice programu, nebo nějaké jiné nepozornosti stát, že budeme alokovat a alokovat paměť, ale už ji zapomeneme uvolňovat. A protože C (ani C++) nemá tzv. Garbage collector (Sběrač smetí), musíme uvolnit paměť, než pointer na ní zahodíme. Z následujícího příkladu by to mělo být jasné: + + +int *data; +data = malloc(sizeof(int)); +data = malloc(sizeof(int)); //Alokujeme podruhe, tim prijdeme o adresu prvniho alokovaneho prostoru, a uz nikdy se nam ho nepodari uvolnit + + +Většinou se samozřejmě paměť uvolní při ukončení programu (OS by měl uvolnit vše, co po programu v paměti zbylo), ale určitě nelze 100% věřit tomu, že například M$ Windows někde sem tam něco nezapomenou. Zkuste si například tento kód: + + while(1) malloc(1024); + +Otevřete si správce procesů (htop, top, tasklist, taskmgr) a zjistěte, kolik paměti náš proces zabírá (virtuální, fyzické i celkové). Pošlete procesu signál pro ukončení (nebo ukočete program, jak jste na vašem OS zvyklí) a sledujte, jak se paměť pomalu uvolňuje. + + +===== Opakovací ukázka pointerů a dynamické alokace paměti ===== + * Ujistěte se, že chápete celý následující kód, v opačném případě se okamžitě obraťte na nejbližšího profesora (nebo rychle utečte). + * Předpovězte, co program zhruba vypíše a svoje doměnky si vyvraťte jeho kompilací a spuštěním: + + +#include +#include + +int main() { + + int prvni; //Staticky (za prekladu) alokovana promenna typu int + + int *druha; //Staticky alokovany pointer na promennou typu int + druha = malloc(sizeof(int)); //Dynamicky (za behu) alokovana promenna typu int + if(!druha) { + printf("Chyba!\nNepodarilo se alokovat promennou *druha\n"); + exit(1); + } + + prvni = 11; + prvni = 22; + prvni = *(&prvni)+1; + //druha = 22; //Ukazkova chyba -> SIGSEGV + *druha = 22; + + //Hodnoty promennych + printf("Hodnoty promennych:\n"); + printf("prvni == %d\n", prvni); + printf("druha == %d\n\n", *druha); + + //Vypis adres, na kterych jsou promenne ulozeny + //Desitkove a pak hexadecimalne (s prefixem 0x) + printf("Adresy v promennych pameti:\n\n"); + printf("prvni je na %d = 0x%X\n", &prvni, &prvni); + printf("druha je na %d = 0x%X\n\n", druha, druha); + + free(druha); //Uvolnime alokovanou pamet + + exit(0); //Na konci programu se samozrejme teoreticky uvolni vse + +} + \ No newline at end of file diff --git a/c/skripta/c_16.txt b/c/skripta/c_16.txt new file mode 100755 index 0000000..196d732 --- /dev/null +++ b/c/skripta/c_16.txt @@ -0,0 +1,49 @@ +====== Dynamická pole ====== +V této kapitole si představíme způsob, kterým můžeme pracovat s polem alokovaným až za běhu programu. + +===== Alokace ===== +Na následujícím příkladu si ukážeme, jak je to doopravdy s definicí (nebo deklarací) polí. + + +unsigned char static[10]; +unsigned char *dynamic; + + +V obou případech vytvoříme pointer na char (případně pole), jediný rozdíl je v tom, že static je konstanta, kterou nelze měnit a obsahuje pointer na již alokované místo v paměti (to se alokovalo při definici), ale dynamic neobsahuje nic (resp. není inicializovaný) a nealokuje žádné místo (alokuje pouze místo pro sebe). + +Takže když chceme dynamic začít používat stejně jako static, stačí nám použít tento zápis: + + +unsigned char static[10]; +unsigned char *dynamic; //Deklarace pointeru na char (případně pole charů) + +dynamic = malloc(10); //Alokujeme 10 bytů a pointer na ně přiřadíme do pole +if(!dynamic) { + printf("Nelze alokovat paměť!\n"); + exit(1); +} + + +Nyní můžeme k oběma polím přistupovat následujícím způsobem: + + +static[3] = 'a'; +dynamic[3] = 'a'; + +*(static + 3 * sizeof(char)) = 'a'; +*(dynamic + 3 * sizeof(char)) = 'a'; + + +Jak vidíte, k oběma polím (jak statickému tak dynamickému) můžeme přistupovat naprosto totožným způsobem, tedy pomocí operátoru [], který (jak jsme nyní zjistili) také zahrnuje dereferenci, nebo pomocí čistě dereferenčního operátoru a pointerové aritmetiky. + +===== Pokročilé postupy ===== +Pokud potřebujeme pole o proměnné velikosti, tak jediným možným způsobem zůstává vždy alokovat nové pole (o jiné velikosti) a stará data do něj v cyklu přetáhnout. Je samozřejmě vhodné staré pole uvolnit (pomocí free()). + +===== Přetečení bufferu ===== +Dobré je také vědět, že pokud načítáme jakákoli data od uživatele (např. z argumentů, klávesnice, sítě nebo souboru) a chceme je uložit do pole (např. řetězce), musíme pohlídat, aby data nepřetekla nad velikost pole, v takovém případě by mohlo dojít k pádu programu pokud by programu byl předán příliš dlouhý řetězec, nebo dokonce zápisu nebezpečného kódu na významná místa v paměti, pokud by se někdo pokusil program napadnout záměrně. Je tedy nutné si hlídat, jestli nepřekračujeme maximální offsety pole. + + +===== Samostatná cvičení ===== + * Napište program, který dokáže do statického pole načíst z klávesnice libovolný řetězec tak, aby nebyla přesažena velikost pole. Nezapomeňte na to, že poslední znak pole musí být nulový. + * Vytvořte obdobu předchozího programu, s tím, že se pole alokuje dynamicky. + * Zkuste napsat program tak, aby zvládl načíst libovolně dlouhý řetězec do pole o proměnné velikosti. diff --git a/c/skripta/c_17.txt b/c/skripta/c_17.txt new file mode 100755 index 0000000..64025f4 --- /dev/null +++ b/c/skripta/c_17.txt @@ -0,0 +1,98 @@ +====== Spouštění externích programů ====== +Tato kapitola by měla nastínit, jakým způsobem je možné zavolat externí program (příkaz), stejně, jako byste ho třeba napsali do příkazové řádky. + +===== Funkce system() ===== +Funkce system() dokáže spustit příkaz a to dokonce s využitím operátorl příkazového interpretu (např.: <,>,>>,|), ten jí předáme jako obyčejný řetězec, tedy například system("ls");, s tím, že výstup tohoto příkazu bude vypsán na obrazovku. + +Samozřejmě si musíme uvědomit, že ve chvíli, kdy použijeme podobné volání externího programu, se náš (relativně přenositelný) program stává závislý na existenci daného příkazu na cílové platformě. Tedy například pokud budeme chtít uživateli zobrazit seznam souborů voláním příkazu "ls", program nám bude bezproblémově fungovat na většině UNIXových systémů naopak na Windows bychom museli tento příkaz změnit na "dir". + +V případě, že je nezbytně nutné volat externí programy, je dobré na začátku programu nadefinovat symbolické konstanty s cestou k tomuto programu, nebo příkazy například načítat z nějakého konfiguračního souboru, který se bude pro každou platformu lišit, také je možné aby náš program nějakým způsobem automaticky ověřoval, jestli program existuje, nebo třeba od někud zjistil, na jaké běží platformě a podle toho se zařídil. + +===== Další funkce pro práci s externími programy ===== +Existuje spousta dalších funkcí, které vám umožní pokročilejší práci se spustitelnými soubory, jako je například nahrazení našeho programu v paměti jiným, spuštění na pozadí, otevření procesu jako souboru a čtení a zápis dat na jeho I/O. + +====== Práce s proměnnými prostředí ====== +Proměnné prostředí jsou proměnné, které nám poskytuje program, který náš program spouští (většinou příkazový řádek, nebo grafické prostředí). Tyto proměnné jsou nahrány do paměti našeho programu spolu s jeho kódem. + +Typickou proměnnou prostředí je "PATH", proměnná, ve které jsou uložené cesty k adresářům, ve kterých se hledá program, který se pokoušíme spustit, pokud není nalezen v aktuálním adresáři. Pokud vás zajímá, jaké další proměnné váš OS běžně poskytuje, zkuste si příkazy export na UNIXech, nebo set na Windows, pomocí těchto příkazů lze také nastavit nové proměnné, nebo změnit stávající. Existuje funkce getenv(), která nám vrátí pointer na danou proměnnou. Následující příklad ukazuje, jak vytisknout námi zvolenou proměnnou prostředí: + + +#include +#include + +int main () +{ + char *p; + p = getenv( "PATH" ); + if (p != NULL) printf ("PATH: %s", p); +} + + +====== Větvení procesu, paralelní zpracování programu ====== +===== Funkce fork() ===== +Pokud potřebujeme v našem programu opustit lineární řízení, jinak řečeno - dělat dvě (a více) věcí najednou. Můžeme pomocí systémového volání fork() vytvořit dokonalou kopii procesu našeho programu, která se bude lišit pouze tím, že návratová hodnota fork() v ní bude 0 a samozřejmě bude mít jiné PID (identifikační číslo procesu). Volání fork() (neboli větvení) je výsadou pouze UNIXových (a samozřejmě UNIX-Like) systémů a na MS Windows bychom podobnou věc museli řešit jinak a daleko složitěji. + +Abych vás nenapínal, tady je první příklad: + + +int main() { + if(fork()) return; + /* Tento kod se bude jiz provadet na pozadi... */ + sleep(10); + printf("BAF!\n"); +} + + +V našem případě jsem zavolali fork() hned na začátku programu, tím se vytvořili kopii našeho procesu, v originále se návratová hodnota volání fork() rovnala 1, to jsme ověřili podmínkou, takže v prvním procesu se nám vykonal return() a tím pádem se první proces zavřel. Máme tedy nový proces, který ovšem není tak pevně svázán s naší příkazovou řádkou a ta se tedy uvolní (a budeme moci normálně dále pracovat a spouštět další programy). Protože se nám ale v procesu nakopírovalo číslo file deskriptoru (ukazatele na soubor), pomocí kterého se dá vypisovat do konzole (na STDOUT), může náš tak trochu záškodnický program na pozadí za 10 sekund vypsat nic netušícímu uživateli "BAF!" a to klidně doprostřed výpisu jiného programu (podobně, jako se vám třeba v BASHi můžou vypisovat oznámení o nových mailech). + +Spuštění programu na pozadí je ale pouze začátkem toho, co fork() doopravdy umí. Podívejme se na následující kód.: + + + /* nejaky kod */ + if(!fork()) { + udelej_neco(); + return; + } + /* dalsi kod */ + + +V tomto případě se zavolá na pozadí pouze funkce udelej_neco() a program bude ihned pokračovat dále. Typickým příkladem může být stahování nějakého velkého souboru (nebo více souborů) z webového serveru (pro zjednodušení jsem použil externí program wget volaný pomocí system()): + + +#include + +int main() { + if(!fork()) { system("wget http://server/soubor1"); return; } + if(!fork()) { system("wget http://server/soubor2"); return; } + if(!fork()) { system("wget http://server/soubor3"); return; } + if(!fork()) { system("wget http://server/soubor4"); return; } + return; +} + + +Tím docílíme toho, že se budou všechny 4 soubory stahovat najednou a ne jeden podruhém, jako kdybychom pouze 4x pod sebou zavolali system(). Díky tomu, že jsem do podmínky přidal vikřičník jsem si zajistil to, že se soubor bude stahovat v kopii a nikoli v originálním procesu. Původnímu procesu se říká parrent (rodič) a kopie se označuje jako child (dítě) i když v případě fork() jsou oba procesy spíše bratry či sestřičkami. Důležité je také to, že po stažení souboru zavoláme return(), protože kdybychom to neudělali, tak by se každý soubor mohl stáhnout vícekrát, protože se náš program v paměti zkopíroval i s tím, co má dělat potom. + +Stinnou stránkou celé věci je to, že jednotlivé procesy se nemohou vzájemně příliš dorozumívat, musíme pak přistoupit k použití prostředků jako jsou soubory, pojmenované pajpy (fifo roury), unix domain sockety a nebo dokonce síťové sockety. + +Další věcí je, že náš program bude velmi těžkopádný, pokud budeme používat fork() ve větším měřítku, například pokud bychom psali webový (nebo jiný) server, tak musíme obsluhovat více uživatelů najednou. Pokud bychom ale na každého uživatele vytvořili jednu kopii procesu, může se nám stát, že nám brzo začnou docházet systémové prostředky (mluvíme o serverech s ~100 requesty najednou), pokud nám nedojdou hardwarové prostředky, tak se nám zaplní process table (vyčerpáme maximální počet procesů povolený operačním systémem), proto je lepší počet 'forků' omezit a ještě lépe používat thready (viz. dále). + +Pro zájemce: Existuje lokální DoS útok pojmenovaný ForkBomb, který způsobí zaplnění tabulky procesů a vede neodvratně k zamrznutí systému, protože nelze vytvořit žádný nový proces, nemůžeme ani spustit program, který by útok ukončil. Uvádím to proto, že k podobné věci může dojít pokud někde voláme fork() v cyklu (např. potřebujeme n podprocesů) a omylem vytvoříme nekonečnou smyčku. + +Např. takto: + + while(1) fork(); + +Na UNIXových systémech se dá proti nečekané chybě bránit tím, že nastavíme limit počtu procesů pro každého uživatele, v případě podobného výmrzu můžeme jako jiný uživatel (typicky root) procesy pozabíjet. Na Windows proti této chybě takřka není ochrana. A ačkoli v jádře systému Windows nic jako fork() neexistuje, může nastat podobný problém, pokud se nám omylem podaří to, že jeden program neustále spouští sám sebe. + +===== Thready ===== +Další možností jak může náš program dělat více věcí najednou jsou takzvané thready (vlákna) ty se od forku liší v tom, že nejde o kopii procesu, ale jeho součást. Thread je tím pádem jakýsi podřadný proces. Narozdíl od forku existují thready i na Windows. Další výhodou je, že thready mohou dále komunikovat se zbytkem procesu, například pomocí globálních proměnných (například proměnné deklarované mimo funkci main()), potom je ale třeba hlídat, aby se dva thready nepokusily zapisovat do stejné proměnné (== stejného místa v paměti), potom by mohlo dojít k poškození těchto společných dat. K tomu se používá tzv. synchronizace threadů. Práce s thready už je ale složitější a proto si ji zde nebudeme ukazovat... + + +===== Samostatná cvičení ===== + * Napište program, který vypíše, na jakém místě se v paměti nachází proměnná prostředí, jejíž název byl zadán jako parametr. + * Napište program, který vezme všechny argumenty (kromě prvního), spojí je do jednoho řetězce (oddělené mezerami) a výslednou větu vytiskne orámovanou znakem (případně prvním znakem řetězce), který je udaný prvním argumentem (vlevo a vpravo bude jeden znak mezera). Výsledný výstup pak mže vypadat napříkad takto: + + ./ramecek * "Ahoj lidi," jak\ se máte? + *************************** + * Ahoj lidi, jak se máte? * + *************************** diff --git a/c/skripta/c_18.txt b/c/skripta/c_18.txt new file mode 100755 index 0000000..832f547 --- /dev/null +++ b/c/skripta/c_18.txt @@ -0,0 +1,73 @@ +====== Práce se soubory ====== +Doteď jsme naše data ukládali jen do paměti RAM. O všechna data uložená v paměti RAM přijdeme v okamžiku ukončení programu, nebo vypnutí počítače. To nemusí bý vždy postačující a můžeme chtít svoje data uložit nějakým trvanlivějším způsobem, ideálním řešením bude jejich zapsání na pevný disk, konkrétně do souboru. + +Klasickým příkladem práce se soubory je jednoduchý tetový editor (nano, gedit, SciTE, notepad, atd...). Takový editor při svém spuštění načte zvolený soubor do paměti, kde s ním může uživatel pracovat a před svým ukončením tato data z paměti uloží i s úpravami zpět do souboru na příslušném paměťovém médiu. + +Ovšem si pamatujte, že problematika základní práce se soubory je mnohem komplikovanější, než jak je zde popsána a pokud máte zájem, doporučuji si projít odkazy na konci této publikace. + +===== Otevření souboru ===== +Abychom mohli pracovat se souborem, musíme ho nejdříve otevřít. Se soubory se dá pracovat například pomocí tzv. file deskriptorů, neo také ukazatelů (je to podobné, jako nám již známé pointery, s tím rozdílem, že neukazují na disk, ale obsahují číslo, které operační systém tomuto souboru přiřadil a podle kterého ho dále rozlišuje). Funkce na práci se soubory opět zpřístupníme vložením hlavičkového souboru . + +Jak tedy takové otevření a čtení ze souboru funguje, to pochopíte z následujícího kusu kódu: + + +FILE *fp; //Nadeklarujeme deskriptor fp +fp = fopen("soubor.txt", "r"); //Otevíráme "soubor.txt" v režimu "r", tedy "pro čtení" +if(fp == NULL) { //Osetrime chyby (napr. soubor neexistuje, nebo nemame prava pro cteni) + printf("Nepodarilo se otevrit soubor!\n"); + exit(1); +} + +char retezec[101]; +fgets(retezec , 100, fp); //Nacteme 100 bytů (znaků) z fp do retezce retezec +puts(retezec); //Vytiskneme tento retezec na obrazovku + +fclose(fp); //Zavreme soubor + + +A tady je například správný postup, jak vypsat celý soubor znak po znaku na obrazovku, všimněte si, že každý znak po celou dobu porovnávám s konstantou EOF, v případě, že jí odpovídá, znamená to, že je soubor na konci (EOF znamená End Of File): + + +int c; +while((c = fgetc(fp)) != EOF) putc(c); + + +===== Režimy fopen() ===== +Když pomocí fopen() otevíráme soubor, můžeme ho otevřít celkem asi v 9ti režimech. Toto jsou 3 základní: + + * "r" - read - čtení + * "w" - write - zápis + * "a" - append - zápis (přidání) na konec + +Ke každému režimu můžeme ještě připojit "b", tedy: "rb", "wb", "ab", to znamená, že se soubory bude zacházeno čistě po binární stránce, tedy že to, co do souboru zapíšete v něm určitě bude a naopak, že přečtete to, co v něm skutečně je. Bez písmenka b dochází k automatické konverzi tzv. line-end kódování, já nechci zabíhat příliš do podrobností, ale v zásadě jde o to, že každá skupina operačních systémů (UNIX + UNIX-like, Windows a staré MAC OSy) ukládají znak odřádkování (Enteru) jinak. Na linuxu je to jen LF, na Windows CR+LF a na starších MAC OSech je to LF+CR, pokud ale v C pracujeme se soubory v textovém režimu (bez "b"), tak s těmito odlišnostmi můžeme pracovat naprosto transparentně (tj. Enter je pokaždé "\n" nezávisle na systému). Pokud bychom ale například pracovali s nějakým binárním (např. spustitelný soubor, hudba, video), mohlo by takřka náhodné změnění některých bytů na jiné způsobit poměrně velké potíže, proto vždy pracujeme s binárními soubory jinak. U binárních souborů je také špatně, pokud je byte po bytu načítáme do charu, protože ačkoli char je datový typ o velikosti 1B, stejně nemohou být všechny hodnoty korektně interpretovány, proto k načítání bytů z bin. soubori použijeme integer. + +===== Funkce na čtení ze souboru ("r") ===== + * fgetc(deskriptor); + * Vrati jeden byte (znak) ze souboru + * fgets(retezec, delka, deskriptor); + * Precte delka znaku do retezec + * fscanf(deskriptor, "%s", retezec); + * Precete radek do retezec + +===== Funkce na zápis do souboru ("w", "a") ===== + * fputc(byte, deskriptor); + * Zapise byte do souboru + * fputs(retezec, deskriptor); + * Zapise retezec do souboru + * fprintf(deskriptor, format_retezec, dalsi argumenty); + * Jako printf(), ale zapisuje do souboru + + +===== Předotevřené soubory ===== +Je dobré vědět, že v C jsou otevřené následující soubory, se kterými pracují funkce jako printf() a pod, když tisknou na obrazovku, nebo načítají z klávesnice, vy toho můžete využít tak, že je zpracujete pomocí funkcí na práci s normálními soubory, nebo je třeba zavřete pro potlačení výstupu. Pak je můžete dokonce opět otevřít a způsobit tak, že všechen výstup vašeho programu, který se normálně provádí na obrazovku bude místo toho uložen do vámi zvoleného souboru. Na druhou stranu nesmíme zapomenout na to, že už nelze zaručit, že znovu půjde otevřít tyto soubory do původního stavu, aby například opět vypisovali na obrazovku. Např. v Linuxu to možné je, v ostatních UNIX-like systémech asi také, ale s jinými takové zkušenost nemám. Na Windows to pravděpodobně možné nebude. + + * stdout - "w" - stanartní výstup + * stderr - "w" - standartní chybový výstup + * stdin - "r" - standartní vstup + + +===== Samostatná cvičení ===== + * Napište program, který vypíše celý soubor (určený 1. argumentem) otevřený v textovém módu. + * Napište program, který binárně zapíše obsah souboru určeného 1. argumentem do souboru určeného druhým argumentem. Půjde o alternativu programu na kopírování souborů (cp, copy, atd...), tento program vyzkoušejte zkopírováním jiného spustitelného souboru, zvukového záznamu a videa, nebo jiného binárního souboru. Tyto kopie musí mít stejnou velikost a být funkční stejně jako jejich originály. + * Napište program, který znak po znaku přečte celý binární soubor a vypíše číselnou hodnotu každého znaku na nový řádek hexadecimálně, desítkově a binárně. + * Napište program, který na střídačku binárně čte byte po bytu ze dvou souborů a zapisuje do jednoho souboru. Pokud tedy 1. soubor bude obsahovat byty "AAAAA" a druhý "BBBBB", pak bude výsledný soubor obsahovat "ABABABABAB", potom napište program, který zvládne za byty správně rozdělit tak, aby byly soubory opět použitelné (stejně jako u kopírování). \ No newline at end of file diff --git a/c/skripta/c_19.txt b/c/skripta/c_19.txt new file mode 100755 index 0000000..2d2b13d --- /dev/null +++ b/c/skripta/c_19.txt @@ -0,0 +1,74 @@ +====== Napojení C na další systémy ====== + +===== Napojení na webové aplikace (CGI a PHP) ===== +V někerých případech se může stát, že budete potřebovat, aby váš program napsaný v C spolupracoval s vaší webovou aplikací, dnes si představíme dva nejjednodušší způsoby, jak toho docílit. První se bude zabívat CGI rozhraním (Common Gateway Interface) a druhý nám ukáže, jak napojit program na webovou aplikaci pomocí wrapperu napsaného v PHP. + +===== Common Gateway Interface (CGI) ===== +CGI je rozhraní, které nám umožní, aby webserver předával požadavek přímo našemu programu. Jaké jsou výhody a nevýhody C proti jiným webovým server-side jazykům (jako PHP, JSP, nebo ASP) je celkem průhledné. C je sice rychlejší, ale musí být zkompilováno pro danou platformu. Nemůžete tedy jednoduše vzít vaší aplikaci, kterou jste do teď provozovali na Linuxu (na procesoru řady x86) a všechny soubory jednoduše uploadnout na HPBSD server (s procesorem PA-RISC), ale budete muset všechny binární soubory ze zdrojových kódů překompilovat pro tuto platformu. + +Když napíšete a zkompilujete CGI aplikaci, potřebujete ještě webserver, který CGI podporuje a musíte ho nastavit podle instrukcí dle konkrétního serveru, potom nahrajete spustitelné soubory do příslušného adresáře. Nastavení serveru tady rozebírat nebudu. + +Jaký je tedy rozdíl mezi normálním programem a CGI programem? Jde o obyčejný textový program pro příkazový řádek, s tím rozdílem, že výstup (například text vypsaný pomocí printf()) se nevypisuje na obrazovku, ale do obsahu vrácené webové stránky, nejdříve, ale musíme poslat alespoň minimální HTTP hlavičku (pro více informací si přečtěte něco o HTTP protokolu), pokud tedy chceme například vygenerovat HTML dokument s nadpisem první úrovně, kód bude vypadat takto: + + +#include + +int main() { + printf("Content-type: text/html\n"); //HTTP hlavicka udavajici typ obsahu + printf("\n"); //Po posledni hlavicce se posila prazdny radek. + //Nyni uz muzeme zahajit vystup: + printf("

Hello world!

\n"); +} +
+ +Ještě bychom měli vědět, jak se dostaneme k datům předávaným metodami GET nebo POST. Oba dva typy parametrů jsou předávány jako řetězec ve formátu, v jakém je server dostane od klienta, většinou takový řetězec vypadá například takto (běžný URL query string): + + prvnipromena=224&druha=Zapis%20data&treti&ctvrta=posledni + +Pokud jsou data předávána v GETu, nahdete je v proměnné prostředí pojmenované "QUERY_STRING", pokud tedy například chceme získat a vytisknout celý GET požadavek, uděláme to pomocí funkce getenv() zhruba takto: + + +#include +#include + +int main () { + char *get; + get = getenv("QUERY_STRING"); //Získáme pointer na QUERY_STRING + + printf("Content-type: text/html\n\n"); + if (p != NULL) printf("

CGI - GET

\n", get); //Vytiskneme QUERY_STRING + return 0; +} +
+ +Pokud ale chceme získat data z POSTu, budou v přesně stejném tvaru, jako v případě GETu, s tím rozdílem, že budou čekat na standartním vstupu, jinými slovy to znamená, že je můžeme načítat například pomocí funkcí scanf(), nebo getc(), to tady dále rozebírat nebudu, protože to je poměrně základní znalost. + + +===== Wrapper v PHP ===== +PHP (Portable Hypertext Preprocesor) je interpretovaný programovací jazyk (podobně, jako PERL, nebo Python), který se dá provozovat například i na webovém serveru. Pro nás je důležité, že obsahuje některé funkce, pomocí kterých se lze odvolávat i na binární spustitelné soubory, požadavky na spustitelný soubor jsou víceméně stejné, jako u CGI, ale s tím rozdílem, že tento soubor nemusí být primárně určen jako webová aplikace, nebo se nacházet ve speciálním adresáři, úplně postačí, když bude mít dobře nastavená práva pro spouštění. + +Jak toto propojení v PHP vytvoříme? Poslouží nám k tomu funkce jako system(), nebo popen() (které se mimochodem chovají stejně, jako jejich jmenovci v Ansi C), shell_exec() a nebo proc_open(). Z následující tabulky pochopíte, co jednotlivé funkce umožňují: + + * system() - spustí program se zadanými parametry a vypíše výstup (stdout) + * shell_exec() - spustí program se zadanými parametry a vrátí výstup (stdout) + * popen() - otevře program podobně jako například soubor, buď pro čtení stdoutu nebo zápis na stdin programu + * proc_open() - dovoluje otevřít program tak, aby bylo možné zároveň pracovat se všemi jeho výstupy i vstupem (stdout, stderr, stdin) + +Jednoduchý PHP skript, který nám spustí náš smyšlený program napsaný v C, který může obsluhovat smyšlený teploměr by vypadal například takto: + + +

Teploty

+Vevnitř\n"); + echo(htmlspecialchars(shell_exec('./thermo -in'))."\n"); + echo("

Venku

\n"); + echo(htmlspecialchars(shell_exec('./thermo -out'))."\n"); +?> +
+ +Všiměte si, že jsem použil ještě funkci PHP nazvanou htmlspecialchars(), která zajistí, že například špičaté závorky budou převedeny na příslušné HTML entity, místo toho, aby způsobily nekorektní zobrazení dokumentu. Sám podobný skript používám, abych si mohl přes webové rozhraní vypisovat aktuální informace o serveru (teplota procesoru, disků, volné místo na disku, přihlášení uživatelé, spuštěné procesy, atd...). To je tedy vše, co si o spolupráci programů napsaných v C s vebovými aplikacemi můžeme říct, aniž bychom přesáhli rámec naší hodiny. + + +===== Jiné systémy ===== +Podobně, jako z PHP voláme program napsaný v C, můžeme z C také volat jiný program, nebo můžeme například pomocí socketů vytvořit spojení například s naslouchajícím serverem. Propojení dvou programů může také probíhat pomocí roury, nebo pojmenované FIFO (first in, first out) roury. + diff --git a/c/skripta/c_20.txt b/c/skripta/c_20.txt new file mode 100755 index 0000000..ff67db7 --- /dev/null +++ b/c/skripta/c_20.txt @@ -0,0 +1,75 @@ +====== Freestyle Coding Contest ====== +//Pozn.: Tato lekce může být použita suplujícím v případě absence vyučujícího, je ale nutné slevit z nároků a říct studentům, aby aplikace upravili tak, aby nemuseli používat znalosti, které ještě nemají, nebo si vymysleli jednodušší zadání, jehož správnost (a především správnost vypracování programu) bude ověřena při první možné příležitosti vyučujícím lektorem.// + +V poslední lekci jsem si pro vás připravil zadání různých malých (a do jisté míry užitečných) prográmků, které byste se svými znalostmi měli být schopni vytvořit. Protože ale nemusí být úplně průhledné, jak takový program napsat (ačkoli teoretické znalosti byste na to mít měli), v případě nejasností požádejte profesora o pomocnou berličku v místech, která vám nejsou úplně jasná (samozřejmě až po chvilce namáhání hlavy ;). Pokud nemáte žádný vlastní nápad, můžete si vybrat jeden (nebo několik) z následujících projektů: + +===== Kalkulátor ===== +Pokuste se napsat co nejkomplexnější a nejpřívětivější program na provádění různých druhů výpočtů. Program můžete například doplit i o pokročilé funkce, jako vykreslení grafu (pomocí písmenek) průběhu různých funkcí při různých vstupních hodnotách (stačí například sin()), nebo libovolnou jinou funkci dle zájmu (výpočet obvodu kruhu, nebo cokoli, co ve své kalkulačce chcete mít). + +===== Interpreter jednoduchého jazyka ===== +Vymyslete si jednoduchý interpretovaný programovací jazyk a napište pro něj interpreter. Stačí například 3-5 příkazů, pro zjednodušení může mít každý příkaz délku 1 znak, nebo řádek. V jednodušší obdobě nemusí jazyk být schopný dělat nic smysluplného, například pokud první písmenko řádku určuje akci a zbytek jsou data, která se mají zpracovat a "P" znamená vytisknout a "M" vynásobit dvěmi a vytisknout, může náledující program: + + PTento text bude vypsan + CToto je komentar + M23 //toto cislo bude vynasobeno dvěmi a vypsáno + +Po zpracování vaším interpreterem například vytvořit následující výpis: + + Tento text bude vypsan + 46 + +Co bude jazyk dělat je čistě na vás, může také například do dvojrozměrného pole kreslit čáru (L,P,N,D,T = vlevo, vpravo, nahoru, dolu, tisk) a když narazí na příkaz pro tisk, tak toto "plátno" vytiskne (vypíše). + +Tedy program **DDDPPPNNLLDT** vypíše například toto: + + # + #### + ## # + #### + +Můžete si samozřejmě doplnit další příkazy (změna písmenka/barvy), nebo napsat něco úplně jiného. + + +===== Shell ===== +Napište jednoduchý příkazový řádek (podobný například BASHi, nebo CMD) implementujte do něj funkci pro spouštění zadaných příkazů. Na internetu zjistěte, jakým způsobem lze zjistit aktuální adresář a vypisujte ho jako součást výzvy (na začátek řádky). Můžete implementovat i další virtuální příkazy na mazání, přesouvání a kopírování souborů, apod... Záleží opět jen na vaší fantazii. + +===== Mnohojazyčná aplikace ===== +Napište program, který obsahuje několik jednoduchých textových menu a libovolnou funkčnost (můžete se inspirovat jinými příklady). Veškeré texty v programu se budou načítat ze souboru specifikovaného v jiném (konfiguračním souboru). Vytvořte najméně dva datové soubory s lokalizacemi programu do vašeho mateřského jazyka a libovolného jiného. Soubor s jazykem nastavený v konfiguračním souboru by měl jít dočasně změnit pomocí argumentu programu. + +===== Engine textové hry ===== +Napište engine a alespoň jeden datový soubor pro textovou hru (elektronický gamebook), uživatel bude o pohybu mezi místnostmi této adventury (načtené ze souboru, jehož jméno zadá v parametru) rozhodovat zadáním čísla místnosti, číslo místnosti může odpovídat jedné konkrétní řádce v textovém souboru. Do enginu můžete dodělat možnosti soubojů (pomocí náhodných čísel), nebo kontrolu, jestli hráč dostal skutečně na výběr číslo místnosti, které zadal. + +===== Primitivní textový editor ===== +Program pro CLI (příkazový řádek) přijme jako argumenty režim (R - přečíst (vypsat na obrazovku), W - přečíst a zapsat, nebo A - přečíst a přídat) a jméno souboru, bude ho vypisovat po 15 řádkách (pokaždé počká na enter), až se dostane na konec souboru, tak pokud je pomocí prvního argumentu aktivován režim, který umožňuje zápis do souboru, vypíše řetězec "\n----- NEJAKY TEXT -----\n" (NEJAKY TEXT budou informace o souboru) a vše, co od té chvíle uživatel napíše na klávesnici zaznamená do souboru (přepíše celý soubor). Uživatel svůj vstup ukončí pomocí programátorem zvolené klávesy stlačené současně s Control (CTRL), nesmí ale jít o kombinace CTRL+C nebo CTRL+D. Pokud uživatel zadá volbu R, program místo toho rovnou skončí. + +Pokud program argument s názvem souboru neobdrží, automaticky vypíše seznam souborů (pomocí volání system() a příslušného programu - tj. ls, dir,...) a na jméno souboru se dotáže. Pokud soubor neexistuje, nabídne jeho vytvoření. Pokud je zadán první argument, tento soubor zpracuje v daném režimu, v jiném případě se uživatele taktéž zeptá. + +===== Ascii Grafika ===== +Tento program by měl dokázat vykreslovat (alespoň) 3 libovolné různé obrazce, prvním parametrem je určen tvar, druhým znak (barva) a dalšími potřebné parametry (rozměry). Způsob, jakým bude tvar vykreslován a jakým bude prováděn výpočet nechám na vás, důležité je ale, aby se tvar zobrazoval korektně nezávisle na zadaném rozměru. Výstup (u těch opravdu nejjednodušších obrazců) může vypadat například takto: + + +Čtverec (c): +./grafika c # 4 4 +#### +# # +# # +#### + +Kruh (k): +./grafika k o 3 + o o +o o + o o + +Trojúhelník (t): +./grafika t A 5 + A + A A +AAAAA + + +===== Další nápady ===== +Můžete samozřejmě vymyslet a zrealizovat svůj ještě zajímavější nápad, nebo libovolná zadání libovolně modafakovat. + +Nejlepší programátor (čistota kódu*nápaditost) bude odměněn diplomem "Fr335ty13 C0din9 C0nt35+ - Zlatý byte" (nebo taky ne ;)... + diff --git a/c/skripta/c_98.txt b/c/skripta/c_98.txt new file mode 100755 index 0000000..84e3cc3 --- /dev/null +++ b/c/skripta/c_98.txt @@ -0,0 +1,41 @@ +====== Vysvětlivky ====== + +Akronym - Zkratka vzniklá spojením počátečních písmen slov ve slovním spojení, nebo větě. +BFU - Běžný Franta Uživatel - slangové ozn. pro uživatele bez hlubších znalostí, pravděpodobně to jednou bude váš typický uživatel. Aplikace je nutno přizpůsobovat těmto uživatelům. +CLI - Command Line Interface - Akronym pro příkazový řádek. +IDE - Integrated developing environment - Integrované vývojové prostředí - Zkládá se především z editoru a kompilátoru (případně může obsahovat debugger nebo GUIBuilder). +UI - User Interface - Uživatelské rozhraní - rozhraní, pomocí kterého uživatel komunikuje s aplikací. +GUI - Graphical User Interface - Specifický druh UI využívající grafiku (většinou tzv. okenní aplikace). +C - Programovací jazyk. +Ansi C - Americká norma popisující konvence, které musí dodržet kompilátor. Používá se zároveň i jako označení současné verze jazyka C. +C++ - Programovací jazyk vycházející z jazyka C. Byl rozšířen především o podporu objektů. +Decimální - Desítkový +HexaDecimální - Šestnáctkový +Binární - Dvojkový +Oktální - Osmičkový +Preprocesor kompilátoru - Program, který připravuje zdrojový kód pro kompilátor (maže nepotřebné mezery, komentáře, atd...). +Kompilátor - Program, který převádí zdrojový kód na binární objektový kód. +Assembler - Jazyk symbolických adres. Programovací jazyk využívající přímo instrukce procesoru (jen zapsané čitelnější formou). +Linker - Program vytvářející spustitelný soubor z objektového kódu vytvořeného při kompilaci. + +====== Prameny ====== +Tady naleznete seznam zdrojů, které sem (kromě svých vlastních znalostí) použil k napsání těchto skript a které vám důrazně doporučuji si pročíst, nebo je prohledávat při nejasnostech ohledně Ansi C, nebo C jako takového. + +Povinná četba každého Céčkaře + * Pavel Herout - Učebnice Jazyka C (Kopp) - I. a II. díl + * Jon Erickson - Hacking: umění exploitace (Zoner press) + +Knihovní funkce Ansi C + * http://www.java2s.com/Code/C/CatalogC.htm - Seznam standartizovaných funkcí s popisem + * http://dione.zcu.cz/studium/doc/lang/ansi-c/ - Západočeská univerzita - seznam funkcí se syntaxí + * http://www.sallyx.org/ - Několik pěkných článků o C + * http://www.soom.cz/index.php?name=articles/rubrika&sid=3 - Různé články o C pro začátečníky + +Všeobecné informace + * cs.wikipedia.org + * en.wikipedia.org + +Všechno ostatní + * google.com + * Existují pokročilé techniky googlování, které vám pomohou snázeji najít to, co skutečně hledáte + diff --git a/c/skripta/compilation/jazyk_c compilation.html b/c/skripta/compilation/jazyk_c compilation.html new file mode 100755 index 0000000..3f33819 --- /dev/null +++ b/c/skripta/compilation/jazyk_c compilation.html @@ -0,0 +1,3375 @@ + + + + + skripta:jazyk_c:compilation + + + + + + + + + + + + + + + + + + +
+ +
+
−Obsah
+
+ + +
+
+ +
     _                 _       ____
+    | | __ _ _____   _| | __  / ___|
+ _  | |/ _` |_  / | | | |/ / | |
+| |_| | (_| |/ /| |_| |   <  | |___
+ \___/ \__,_/___|\__, |_|\_\  \____|
+                 |___/
+
+
+	Jazyk C
+	Základy praktického programování
+
+	V Praze 2oo7 pro SSPÅ 
+	Tomáš Harvie Mudruňka a kolektiv
+ +

+ +TODO mergnout adresare c a sbirka do wiki… +

+ + + +

Předmluva

+
+ +

+Tento text vznikl puvodne jako skripta pro Smíchovskou Střední Průmyslovou Školu, nyní ho v jeho vlastním zájmu chci publikovat na wiki, kde je volně k použití i k editaci… +

+ +

+Skripta si nekladou za cil byt dokonalou referencni priruckou, ani wiki o jazyce C, ucelem je vytvorit ucebni texty pro jednotlive lekce kurzu programovani v jazyce C v rozsahu stravitelnem studenty stredni skoly. +

+ +

+Se skripty v celém rozsahu můžete zatím nakládat v souladu s licencí +Creative Commons: Uveďte autora-Neužívejte dílo komerčně-Zachovejte licenci 3.0 Česko +

+ +

+Kromě plaintextové verze mám v plánu text vyexportovat také do následujících formátů +

+
    +
  • PDF
    +
  • +
  • HTML
    +
  • +
  • nroff (manuálové stránky)
    +
  • +
+ +

+ +~~Tomáš Mudruňka~~ + +

+ +
+ +

Rozpis lekcí

+ + +

Co bychom měli znát než začneme programovat

+
+
    +
  • Povinné
    +
      +
    • 1B (byte) == 8b (bitů) + další základní výpočty s jednotkami informace/paměti
      +
    • +
    • základní práce s operačním systémem používaným k výuce
      +
    • +
    • práce s příkazovým řádkem (CLI) na tomto OS (procházení adresářů, mazání, přejmenování a kopírování souborů, nastavování práv pro spouÅ¡tění, spouÅ¡tění programů)
      +
    • +
    • základy programování z jiného jazyka (cokoli, v nejhorším případě alespoň nějaký značkovací jazyk, jako html, nebo BASIC, který se vyučuje u nás na Å¡kole)
      +
    • +
    +
  • +
+
    +
  • Nepovinné
    +
      +
    • psaní na klávesnici (především umístění různých speciálních znaků)
      +
    • +
    +
  • +
+ +

+ +Ohledně jakékoli nejasnosti ohledně čehokoli se prosím kdykoli informujte u vyučujícího („když už tu teda trčíme…“). +

+ +

+Také nezapomeňte připomenout svému lektorovi, aby nezapoměl, že nemá zapomenout vám ukázat doplňkové studijní materiály, připravil jsem si pro vás totiž zábavná videa a animace :-) + +

+ +
+ +

Předmluva

+
+ +

+Účelem této příručky je přiblížit vám základy programování hned z několika pohledů: +

+
    +
  • První složkou jsou základy praktického programování v ANSI C (napsat, zkompilovat, spustit, upravit).
    +
  • +
  • Dále se také seznámíme s programátorskou kulturou a základy sluÅ¡ného chování při získávání informací na internetu.
    +
  • +
  • A nakonec prohloubíme své znalosti o počítači, operačním systému a zužitkujeme nové poznatky při programování.
    +
  • +
+ +
+ +

Počátky

+
+ +

+Vývoj jazyka C začal v Bellových laboratořích AT&T mezi léty 1969 a 1973. Ritchie tvrdí, že nejpřínosnější období bylo v roce 1972. Pojmenování „C“ zvolili, protože mnoho vlastností přebírali ze staršího jazyka zvaného „B“, jehož název byl zase odvozen od jazyka BCPL (ale to není jisté, neboť Thompson také vytvořil jazyk Bon na poctu své ženy Bonnie). +

+ +

+V roce 1973 se stal jazyk C dostatečně stabilním. Většina zdrojového kódu jádra Unixu, původně napsaného v assemleru PDP-11, byla přepsána do C. Unix tedy patří mezi první operační systémy, které byly napsané v jiném než strojovém jazyce či assembleru. Předchozí byl například systém Multics (napsaný v PL/I) a TRIPOS (napsaný v BCPL).ovat, opravit - to vše pokud možno nezávisle na platformě). +

+
    +
  • Dále se podíváme na vyhledávání informací, řeÅ¡ení problémů pomocí internetového vyhledávače a na programátorskou kulturu (Pokud komunikujeme s jinými programátory -byÅ¥ jen po internetu-, musíme dodržovat jisté konvence. Největší a nejméně snadno dodržiteknou je nechtít po někom to, aby někdo mrhal svým časem nad něčím, co můžete udělat sami). Do této esence patří samozřejmě také konvence ve psaní zdrojového kódu a programování vůbec.
    +
  • +
  • A nakonec prohloubíme své znalosti ANSI C, to především znamená, že se podíváme se na pointery (ukazatele) a dynamickou alokaci paměti.
    +
  • +
+ +

+ +Protože C je velmi komplikovaný jazyk, budeme se držet základů a věcí nezbytných k tomu, abychom měli kompaktní soubor znalostí vhodných k tomu, abychom napsali nějaký pěkný program. +

+ +
+ +

Proč C?

+
+ +

+C je programovací jazyk, který vyvinuli Ken Thompson a Dennis Ritchie pro potřeby operačního systému Unix. V současné době je to jeden z nejpopulárnějších jazyků, zřejmě nejčastější pro psaní systémového softwaru, ale velmi rozšířený i pro aplikace. +

+ +

+C je nízkoúrovňový, kompilovaný, relativně minimalistický a rychlý programovací jazyk. Je dostatečně mocný na většinu systémového programování, mimoto podporuje také možnost využít ve zdrojovém kódu jazyk assembler, který pracuje víceméně s instrukcemi procesoru pro případ, že by něco (velmi nízkoúrovňového) nebylo možné napsat, to ale pro naše účely nebudeme potřebovat. +

+ +

+Z toho vyplývá, že operační systémy, překladače, knihovny a interpretry vysokoúrovňových jazyků jsou často implementovány právě v C. +

+ +

+Ukládání dat je v C řešeno třemi základními způsoby: statickou alokací paměti (při překladu), automatickou alokací paměti na zásobníku, dynamickou alokací na haldě (heap) pomocí knihovních funkcí. Jazyk nedisponuje žádnou abstrakcí nad alokací: s pamětí se pracuje přes datový typ zvaný ukazatel, který drží odkaz na paměť, ale je na něm možné provádět aritmetické operace. Ukazatelé tedy existují nezávisle na proměnných, na které odkazují, a je na odpovědnosti programátora, aby neukazovaly na paměť nealokovanou. +

+ +

+Jazyky Java a C#, oba odvozené od C, používají méně univerzální způsob odkazování alokovaných proměnných, který snižuje pravděpodobnost chyby v programu. Jazyk C++, původně rozšíření jazyka C, si ovšem ukazatele zachoval. +

+ +

+Mnoho dalších moderních programovacích jazyků (Nejen kompilovaných) přebírá způsob zápisu (neboli syntaxi) z jazyka C. Patří mezi ně například zmíněná Java či Perl a PHP. +

+ +

+Dalším plusem je, že se při výuce a psaní programů v C se můžete naučit mnoho podrobností o funkci počítače a rozšířit je na víc než „Tam ten procesor tam počítá s nějakejma číslama a něco si dává někam do paměti“, C vám ukáže, jak funguje práce s pamětí, pokud se blíže podíváme na strojový kód (vzniklý kompilací zdrojového kódu) dozvíme se podrobněji jak funguje procesor a také specifika konkrétní architektury. +

+ +

+V C můžeme nejen psát textové nebo grafické aplikce, ale dokonce programovat webové aplikace podobně, jako například v PHP, nebo dokonce psát programy pro jednočipové mikropočítače (šváby). +

+ +
+ +

Historie jazyka C

+
+ +
+ +

Počátky

+
+ +

+Vývoj jazyka C začal v Bellových laboratořích AT&T mezi léty 1969 a 1973. Ritchie tvrdí, že nejpřínosnější období bylo v roce 1972. Pojmenování „C“ zvolili, protože mnoho vlastností přebírali ze staršího jazyka zvaného „B“, jehož název byl zase odvozen od jazyka BCPL (ale to není jisté, neboť Thompson také vytvořil jazyk Bon na poctu své ženy Bonnie). +

+ +

+V roce 1973 se stal jazyk C dostatečně stabilním. Většina zdrojového kódu jádra Unixu, původně napsaného v assemleru PDP-11, byla přepsána do C. Unix tedy patří mezi první operační systémy, které byly napsané v jiném než strojovém jazyce či assembleru. Předchozí byl například systém Multics (napsaný v PL/I) a TRIPOS (napsaný v BCPL). +

+ +
+ +

K&R C

+
+ +

+V roce 1978, Ritchie a Brian Kernighan vydali první vydání knihy The C Programming Language. Tato kniha, mezi programátory C známá jako „K&R“, sloužila po mnoho let jako neformální specifikace jazyka. Verze C, kterou takto popsali, bývá označována jako „K&R C“. (Druhé vydání knihy popisovalo novější standard ANSI C.) +

+ +

+K&R C je považován za základní normu, kterou musejí obsahovat všechny překladače jazyka C. Ještě mnoho let po uvedení ANSI C to byl „nejmenší společný jmenovatel“, který využívali programátoří v jazyce C kvůli maximální přenositelnosti, protože zdaleka ne všechny překladače plně podporovaly ANSI C. +

+ +

+V několika letech následujících po uvedení K&R C bylo uvedeno a přidáno několik „neoficiálních“ vlastností jazyka, které byly podporovány překladači od AT&T a některých dalších dodavatelů. +

+ +
+ +

ANSI C a ISO C

+
+ +

+V pozdních sedmdesátých letech začalo C nahrazovat BASIC jako přední programovací jazyk pro mikropočítače. Během osmdesátých let bylo přejato pro použití na platformě IBM PC a jeho popularita se značně zvýšila. Tou dobou Bjarne Stroustrup a další v Bellových laboratořích začali pracovat na rozšiřování C o objektově orientované prvky. Jazyk, který vytvořili, zvaný C++, je dnes nejrozšířenější programovací jazyk pro aplikace na Microsoft Windows. C zůstává stále populárnější ve světě Unixu. +

+ +

+Jedním z cílů standardizačního procesu ANSI C byl vytvořit nadmnožinu K&R C zahrnující mnoho „neoficiálních vlastností“. Navíc standardizační komise přidala několik vlastností jako funkční prototypy (vypůjčené z C++) a schopnější preprocesor. +

+ +

+ANSI C je dnes podporováno téměř všemi rozšířenými překladači. Většina kódu psaného v současné době v C je založena na ANSI C. Jakýkoli program napsaný pouze ve standardním C je přeložitelný a spustitelný na jakékoli platformě, která odpovídá tomuto standardu. Nicméně mnoho programů se dá přeložit pouze na jedné platformě nebo jedním překladačem, kvůli (i) použití nestandadních knihoven, např. pro grafiku, a také (ii) některé překladače v implicitním módu neodpovídají standardu ANSI C. +

+ +
+ +

C99

+
+ +

+Po standardizaci jazyka v roce 1989 se většina vývoje soustředila na jazyk C++. Přesto však na konci 90. let došlo k vydání dokumentu ISO 9899:1999 (obvykle nazývaný C99), který byl následně v březnu 2000 přijat i jako ANSI standard. +

+ +

+C99 představil několik nových vlastností, které byly mnohdy v překladačích už implementovány jako rozšíření. +

+ +

+Standard C99 je v některých ohledech přísnější než původní standard C89; například je zakázáno odkazovat na stejnou paměť ukazateli jiných typů. Toto umožňuje vylepšenou optimalizaci, ale může způsobit problémy s kompilací starších programů. +

+ +

+Žádný kompilátor zatím neobsahuje kompletní implementaci C99, přestože některé jsou poměrně blízko (GCC). Firmy jako Microsoft nebo Borland neprojevily velký zájem o implementaci C99, především kvůli tomu, že většinu nových vlastností poskytuje C++ a to často nekompatibilně s C99 (datový typ complex v C99 versus třída complex v C++). +

+ +
+ +

Ahoj, světe!

+
+ +

+Tzv. „Ahoj, světe!“ (v originále „hello, world“) je jednoduchý program, který prostě jen vypíše „hello, world“, ten je sám o sobě prakticky k ničemu, ale pro programátory je důležitý protože se naučíme jak vypadá program, který nic vlastně nedělá, jak se zkompiluje a spustí, tedy všechny formality, které nás dělí od vlastního programování. +

+ +

+A takto tedy vypadá hello world v C: +

+
+
hello.c
+
  #include <stdio.h>
+ 
+  int main(int argc, char *argv[]) //Pro primitivni programy muzeme pouzit jen: int main(void)
+  {
+    //Toto je komentar
+    /* 
+     * A toto je
+     * viceradkovy komentar
+     */
+    printf("hello, world\n");
+    return(0);
+  }
+
+ +

+ +Tento text uložíme pomocí nejobyčejnějšího textového editoru do souboru s příponou .c (tedy např.: „hello.c“). Na konci souboru musí být minimálně jeden prázdný řádek a soubor nesmí končit v otevřeném komentáři tedy např.: “/*Za touto vetou bude konec souboru“. Jinak kompilátor (nebo spíše preprocesor) nahlásí chybu. +

+ +
+ +

Rozbor prvního programu

+
+ +

+Po kompilaci a spuštění tohoto programu začne počítač vykonávat naše příkazy tak, jak jsou napsány ze shora dolů, z leva do prava. Teď si ukážeme co program udělá krok za krokem, řádek po řádku: + +

+
#include <stdio.h>
+ +

+To není příkaz, který by se prováděl při spuštění programu, ale ještě před kompilací. Jde o tzv. „direktivu preprocesoru“ (začínají # - křížkem), preprocesor je program, který připraví náš kód pro kompilátor (odstraní nepotřebné mezery, prázdné řádky, rozvine makra,…). Direktiva preprocesoru #include <soubor> způsobí to, že bude nahrazena obsahem souboru „soubor“, čili na začítek našeho programu se vloží soubor stdio.h, který obsahuje především funkce na práci s příkazovým řádkem a soubory. Pokud je jméno souboru ve špičatých závorkách (#include <soubor>), hledá se soubor v adresáři pro hlavičkové soubory, který je součástí kompilátoru, pokud bychom napsali jméno souboru mezi uvozovky (#include „soubor“), preprocesor by hledal soubor ve stejném adresáři, jako se nachází náš program. + +

+
int main(int argc,char *argv[]) { /*Nase prikazy...*/ }
+ +

+Toto je deklarace funkce main, funkce main je první funkce, která je zavolána po spuštění programu, jinými slovy příkazy uvedené ve složených závorkách ({}) budou provedeny neprodleně po spuštění našeho programu. Klíčové slovo „int“ před jménem funkce říká, že funkce vrací integer (tedy celé číslo). Dvě proměnné nadeklarované v závorkách za jménem funkce (int argc, char *argv[]) se používají k získání parametrů od našeho OS, jde o argumenty z příkazové řádky (nebo třeba jména souborů přetažená na ikonku našeho programu). přičemž celé číslo argc obsahuje počet parametrů a pole řetězců (polí znaků) argv[] obsahuje text těchto argumentů. + +

+
/* Komentáře */
+ +

+Vše, co je umístěno mezi /* a */ (v našem příkladu můžete vidět zdobnější zápis s hvězdičkou na každé řádce, to zůstává na fantazii programátora…) bude ignorováno, můžeme to tedy použít pro popisování našich programů (to je velmi důležité, jinak se v našem programu ztratíme). Také můžeme použít komentář pomocí , kdy vše od až do konce řádku je ignorováno. + +

+
printf("hello, world\n");
+ +

+Tento řádek vypíše na obrazovku text „hello, world“ a přejde na nový řádek („\n“ značí newline dle zvyku na vašem OS, tj. ekvivalent enteru). Funkce printf() je nadefinovaná v souboru stdio.h (viz. výše) a jako první parametr přijímá text, který chceme vypsat, nebo formátovací řetězec. Tímto prvním argumentem je vždy řetězec (např. text v uvozovkách). Pokud bychom chtěli vypsat uvozovku, musíme použít \“ pokud lomítko, tak
+a pokud znam procenta, tak %%. Všiměte si, že deklarace, definice a volání funkce (náš případ) musí končit středníkem (;), nikoli však novým řádkem, stačí mezera, nebo tabelátor. + +

+
return(0);
+ +

+Jde opět o volání funkce. Funkce return() (jména funkcí píšeme standartně s () na konci, aby bylo na první pohled jasné, že jde o funkci) způsobí to, že je funkcí, ze které je zavolána (v našem případě main()), vrácena hodnota zadaná jako první parametr této funkce return(). Pokud toto zavoláme z funkce main, znamená to pro nás ukončení programu s návratovou hodnotou 0. Návratové hodnoty jsou čísla (int main(), tedy funkce main() je typu integer == celé číslo), které programy předávají operačnímu systému po skončení, aby měl přehled o úspěšnosti vykonání programu (0 znamená bez chyby a obecně pak platí, že čím vyšší číslo, tím horší chyba). +

+ +

+Pokud program dojde na konec kódu funkce, je automaticky navrácena hodnota 0, pokud to není změněno pomocí funkce return(); +

+ +
+ +

Co budeme potřebovat pro psaní a spuštění programů v C

+
+ +

+V první řadě budeme potřebovat plaintextový editor (jsme začátečníci a budeme tedy raději konzervativní, takže kódovani utf-8, nebo cp-1250, raději žédné wide-chary a už vůbec ne textové editory typu Word!!!). Naopak se nám hodí editor se zvýrazněnou syntaxí a jinými „vychytávkami“, které nám mnohonásobně usnadní psaní kódu a například nám i napovídá, jeden z nejlepších nejuniverzálnějších editorů je SciTe (na enginu Scintilla). +

+ +

+Můžeme použít například editory dostupné pro náš OS +Microsoft: +

+
    +
  • SciTe (doporučuji)
    +
  • +
  • PSPad (nedoporučuji)
    +
  • +
  • notepad
    +
  • +
+ +

+Unixy: +

+
    +
  • SciTe (doporučuji)
    +
  • +
  • nano (doporučuji pro příkazový řádek)
    +
  • +
  • mcedit (balíček mc)
    +
  • +
  • vim
    +
  • +
+ +

+ +Potom budeme také potřebovat program, který převede námi psaný a čitelný strojový kód na strojový kód tj. procesorem čitelné instrukce (ty se ukládají v binárním spustitelné souboru čitelném operačním systémem). A samozřejmě standartní knihovny ANSI C (verzi pro vývojáře). +

+ +

+Na platformách od Microsoftu to znamená instalci jednoho z těchto balíčků +

+
    +
  • MinGW (gcc, g++) - (doporučuji)
    +
  • +
  • Borland C Compiler
    +
  • +
+ +

+ +Na Unixových platformách pak pravděpodobně potřebujeme tyto balíčky +

+
    +
  • gcc
    +
  • +
  • g++ (pokud máme zájem také o C++)
    +
  • +
  • libc-dev (poslední verze)
    +
  • +
+ +

+ +Nebo můžeme sáhnout po celých IDE (Integrované vývojové prostředí) +Jde o jakýsi balíček Vše-V-Jednom. To v praxi znamená potřebný editor uživatelsky přívětivě spolupracující s kompilátorem, jinými slovy nainstalujeme jeden balíček programů místo všech výše zmíněných. +

+ +

+Ze všech IDE pro Unixy i MS systémy je pro nás nejvýhodnější multiplatformní IDE Dev-C++ (dev-cpp) - (doporučuji). +Pro jednotlivé systémy existují samozřejmě i další IDE: +

+ +

+Na Windows máme např. +

+
    +
  • C++ Builder
    +
  • +
  • Microsoft Visual Studio (nebo Visual C++)
    +
  • +
+ +

+ +Na Unixech pak stojí za zmínku +

+
    +
  • Eclipse (s pluginem pro C)
    +
  • +
  • NetBeans (s pluginem pro C)
    +
  • +
  • Anjuta
    +
  • +
  • KDevelop
    +
  • +
+ +
+ +

Samostatné cvičení

+
+
    +
  • Vyberte si jedno z freewarových řeÅ¡ení dle výběru vyučujícího (Dev-C++, nebo SciTe s gcc/g++).
    +
  • +
  • Vyhledejte si ho pomocí Googlu, stáhněte a nainstalujte ho na váš počítač.
    +
  • +
  • VyzkouÅ¡ejte si kompilaci a spuÅ¡tění naÅ¡eho prvního programu (Hello, world!).
    +
  • +
  • VyzkouÅ¡ejte si práci s editorem, zvýraznění syntaxe a případně automatické dokončování kódu.
    +
  • +
  • Pokuste se náš program zkompilovat podruhé, ale v kódu změňte text, který se bude vypisovat na obrazovku.
    +
  • +
+ +

+ +Následující body platí i pro všechna budoucí cvičení: +

+
    +
  • VeÅ¡keré problémy se pokuste vyřeÅ¡it nejdříve pomocí Googlu, případně pomocí manuálu dodaného s produktem.
    +
  • +
  • V případě neúspěchu se obraÅ¥te na vyučujícího.
    +
  • +
+ +
+ +

Datové typy, deklarace, identifikátory, přiřazení, inicializace, definice

+
+ +

+Jazyk C disponuje několika základními datovými typy, jiné si můžeme vytvořit sami. Datový typ v praxi popisuje formát nějaké hodnoty, která vyžaduje alokaci předem daného místa v paměti (většinou měříme v bytech), na to se ukládá požadovaná hodnota (samozřejmě binárně), které přísluší (což není úplně tak závazné) konkrétní interpretace (logická hodnota, číslo, znak, text). +

+ +
+ +

Základní jednoduché datové typy

+
+ +

+Celočíselné +

+
    +
  • char - 1B
    +
  • +
  • short - 2B
    +
  • +
  • int - 2B
    +
  • +
  • long - 4B
    +
  • +
+ +

+ +S Plovoucí desetinnou čárkou +

+
    +
  • float - 4B
    +
  • +
  • double - 8B
    +
  • +
  • long double - 10B
    +
  • +
+ +

+ +pozn.: Hodnoty se mohou lišit podle konkrétní implementace (kompilátoru). Velikost konkrétního typu v bytech získáte také pomocí makra preprocesoru sizeof(), tedy např sizeof(char) bude nahrazeno číslem 1. +

+ +

+Například datový typ char má velikost 1B, to odpovídá 256ti možným kombinacím, standartně jednoduché datové typy počítají s možností uložení záporného čísla, takže např. char může dosahovat hodnot -128 až 127, podobné je to se všemi jednoduchými typy. +

+ +

+Pokud ale nechceme zbytečně alokovat (zabírat) paměť pro záporná čísla, když víme, že toho nevyužijeme, můžeme použít operátoru „unsigned“ (česky „bez znaménka“), tím docílíme toho, že se rozsah všech možných hodnot našeho typu „posune“ na 0 a výše. Např. tedy datový typ „unsigned char“ může nést hodnotu 0 až 255 tj. nějaký libovolný byte. +

+ +
+ +

Deklarace, identifikátory

+
+ +

+Takže ve zkratce známe několik důležitých datových typů a určitě nás zajímá jejich využití. První možností je, jak již bylo naznačeno, ukládání informací do paměti. Abychom mohli ukládat data do paměti, musíme si nejprve vytvořit proměnnou (staticky-na pevno alokovat část paměti), toho docílíme jednoduchým kusem kódu, vše ostatní už vyřeší kompilátor. +

+ +

+Této proceduře se říká „deklarace“, to znamená, že v paměti zabereme místo a přiřadíme mu „identifikátor“ (jméno), který budeme pokaždé používat při práci s tímto prostorem v paměti (to není podmínkou, identifikátoru je totiž přiřazena nějaká konkrétní adresa v paměti, ale o tom až v pokračování pro pokročilé). +

+ +

+Identifikátory mohou sice obsahovat různé znaky, my se ale zatím budeme držet malých písmen (v případě potřeby lze několik slov oddělit např. podtržítkem („_“)), to nám musí stačit, také se můžeme držet některých tradic (znaky začínájí na „c“ („cmuj_znak“), proměnné používané k řízení cyklů se většinou označují pouze „i“ - může nám stačit pro celý jednodušší program bez vnořených cyklů, atd…) +

+ +

+A takto proběhne deklarace z pohledu programátora: +

+
datovy_typ identifikator[, dalsi_identifikator, ...]; //Deklarace konci strednikem
+ +

+ +Takže pokud například potřebujeme tři proměné, pro uložení hodnot 0 - 4 294 967 295, použijeme tuto konstrukci: +

+
unsigned int moje_cislo, moje_dalsi_cislo, moje_posledni_cislo;
+ +

+ +Pozor ovšem na redeklaraci - tj. pokus o opětovnou deklaraci/definici libovolné proměnné, funkce, nebo čehokoli jiného, jejíž identifikátor je již používán, to je chyba, která většinou zkončí chybou překladače (kompilátoru). +

+ +
+ +

Přiřazení, inicializace

+
+ +

+Přiřazení je operace, která na danou adresu ukládá námi vybraná data, probíhá pomocí operátoru rovnítko (“=“) levé a pravé hodnoty (l-hodnota, r-hodnota - od left, right). +

+ +

+Obecný zápis je tento: +

+
l-hodnota = r-hodnota; //I prirazeni opet konci strednikem
+ +

+ +L-hodnota je v levo, tj. cíl přiřazení, r-hodnota je v pravo, tj hodnota přiřazení, po úspěšném přiřazení platí, že se l-hodnota rovná r-hodnotě. +Pokud bychom tedy do námi deklarované proměnné moje_cislo chtěli přiřadit hodnotu 5, postupujeme takto: +

+
moje_cislo = 5;
+ +

+ +Pokud je hodnota do proměnné jednou přiřazena, lze ji samozřejmě přepsat jinou (až na vyjímky, o tom později…). +

+ +

+Pokud je to poprvé, co do nově nadeklarované proměnné přiřazujeme hodnotu, takovému přiřazení říkáme také inicializace. +

+ +
+ +

Definice

+
+ +

+Definice je výraz pro inicializaci provedenou zároveň při deklaraci (nebudeme polemizovat o rozdílu slov deklarace a definice z pohledu českého jazyka…). +

+ +

+Zápis definice je tento: +

+
datovy_typ identifikator = nova_hodnota[, dalsi_identifikator = nova_hodnota, ...]; //Samozrejme strednik
+ +

+ +Konkretne napriklad takto: +

+
unsigned char pocet_psu = 10;
+ +

+ +Ovšem zde se naskytuje další možnost udělat chybu a to je redeklarace: +

+
unsigned char pocet_psu = 10;
+unsigned char pocet_psu = 11; //Chybne pridani jednoho psa - pokus o redeklaraci!
+ +

+Spravny zapis je samozřejmě tento: +

+
unsigned char pocet_psu = 10; //Definice
+pocet_psu = 11; //Spravne pridani jednoho psa - pouze prirazeni
+ +
+ +

Funkce printf() podrobněji

+
+ +

+funkce printf nabízí kromě výpisu textu tak, jak je zadán do jejího parametru také možnost výpisu obsahu proměnných. +Pokud bychom například chtěli vypsat proměnné pocet_psu a pocet_kocek, docilime toho timpo zpusobem: + +

+
printf("Pocet psu: %d\nPocet kocek: %d\n", pocet_psu, pocet_kocek); //Ansi-C funkce ze stdio.h - Nezapomeneme na #include <stdio.h>!!!
+ +

+ +Symbol %d bude nahrazen číslem načteným z naší proměnné, s každým podobným operátorem přibyde funkci printf() jeden povinný parametr, tzn., že pokud je v našem řetězi dvakrát “%d“, musíme kromě prvního parametru (tzv. formátovacího řetězce) specifikovat ještě další dva parametry, tj. např. dvě proměnné v požadovaném pořadí. +

+ +

+Tady je seznam všech nejdůležitějších operátorů pro formátovací řetězec funkce printf: +

+ +

+Pro čísla typu int +

+
    +
  • %d - vypíše číslo dekadicky
    +
  • +
  • %u - vypíše číslo dekadicky neznaménkově (unsigned)
    +
  • +
  • %x - vypíše číslo hexadecimálně malými písmenky
    +
  • +
  • %X - vypíše číslo hexadecimálně velkými písmenky
    +
  • +
  • %o - vypíše číslo oktálně
    +
  • +
+ +

+ +Pro ostatní typy +

+
    +
  • %ld - vypíše číslo typu long dekadicky
    +
  • +
  • %f - vypíše číslo typu float dekadicky
    +
  • +
  • %Lf - vypíše číslo typu long double dekadicky
    +
  • +
+ +

+ +Pro pole +

+
    +
  • %s - vypíše řetězec (tomu se budeme věnovat později)
    +
  • +
+ +
+ +

Samostatné cvičení

+
+
    +
  • Co vypíše následující příkaz?:
    +
      +
    • printf("Pocet psu: %d\nPocet kocek: %d\n", 34, 5);
      +
      +
    • +
    +
  • +
  • NapiÅ¡te a zkompilujte program, který na začátku deklaruje jednu proměnnou a druhou definuje libovolným celým číslem, první proměnnou inicializujte také libovolným číslem. Pro obě proměnné si zvolte přísluÅ¡né (a paměťově výhodné) datové typy. Nakonec pomocí příkazu printf() vypiÅ¡te na monitor tato čísla desítkově i Å¡estnáctkově, ve formátovacím řetězci použijte několik přechodů na novou řádku, vtipný text a jeÅ¡tě vypiÅ¡te jedno číslo specifikované konstantou přímo jako argument funkce printf(). Smíte použít pouze jediné volání funkce printf(). Celý zdrojový kód progamu vhodně okomentujte.
    +
  • +
+ +
+ +

Výhody a nevýhody programování textových aplikací

+
+ +

+V našich seminářích se budeme zabívat především psaním aplikací pro CLI (tedy příkazový řádek). +Účelem této hodiny je poskytnout vám objektivní pohled na tyto aplikace ve srovnání s aplikacemi grafickými. +

+ +
+ +

Pokud v C píšeme konzolové aplikace, získáme tyto výhody:

+
+
    +
  • Textové aplikace jsou rychlejší.
    +
  • +
  • Při vzdáleném přístupu k počítači se text (SSH/Telnet) přenáší rychleji než grafika (VNC/MST).
    +
  • +
  • ZkuÅ¡enějším uživatelům usnadňují práci a posouvají pro ně efektivitu úplně jinam, než si BFU (běžný Franta uživatel) dokáže představit.
    +
  • +
  • Bude velmi snadné, aby další aplikace/skripty mohly využívat naší aplikaci (např. je běžnou praxí, že se nejdříve napíše textová aplikace a grafika se píše až jako nástavba na ni - úplně samostatný spustitelný soubor).
    +
  • +
  • VeÅ¡keré výpisy programu i vstupy do něj můžeme ukládat nebo načítat do souboru, případně rovnou zpracovávat výstup jiného programu.
    +
  • +
  • Tyto aplikace mohou být použity jako webové aplikace (buď jako binární CGI aplikace, nebo prostřednictvím interpretovaných skriptů).
    +
  • +
  • Textové aplikace (především ty v čistém Ansi C) jsou snadno přenositelné na vÅ¡echny platformy, pro které jsou dostupné kompilátory (Nejen Windows a Unixy, ale také obrovské množství dalších systémů).
    +
  • +
  • Pokud se naučíte psát textové aplikace, bude pro vás snadné vytvářet grafické aplikace pomocí tzv. GUIBuilderů známých například z vývojového prostředí Visual Basicu implementovaného Microsoftem nebo IBM. Pro více info viz. níže.
    +
  • +
+ +
+ +

Nevýhody textových programů

+
+
    +
  • Pokud píšete aplikace pro běžné uživatele, budou pro ně neefektivní, protože neovládají příkazový řádek na potřebné úrovni.
    +
  • +
  • Tyto uživatelé si samozřejmě budou stěžovat ;D (Dobrým kompromisem pro jednodušší aplikace je napsat si další program, který bude fungovat jako grafická nadstavba).
    +
  • +
+ +
+ +

Výhody grafických aplikací

+
+
    +
  • Spousta tzv. „eye-candy“ → Spokojení uživatelé
    +
  • +
  • Ovládání zvládne i p*blb
    +
  • +
+ +
+ +

Nevýhody grafických aplikací

+
+
    +
  • Je obtížné je ovládat pomocí jiných programů a tedy nemůžeme práci s nimi potřebně automatizovat.
    +
  • +
  • Jsou náročnější na systémové prostředky.
    +
  • +
+ +
+ +

GUIBuildery - prostředí pro jednoduchý návrh grafického rozhraní programů v C/C++

+
+
    +
  • Borland C++ Builder (Windows)
    +
  • +
  • Kylix (Linux - kompatibilní s C++ Builderem a Delphy - zastaralé)
    +
  • +
  • Microsoft Visual Studio (Windows)
    +
  • +
  • wxDev-Cpp (Windows, programy ale možno kompilovat i na Linuxu s potřebnými knihovnami - wxWidgets)
    +
  • +
  • GLade (Linux - GTK+2)
    +
  • +
  • další… (cokoli, s čím se vám dobře pracuje…)
    +
  • +
+ +
+ +

Konstanty, konstantní proměnné

+
+ +

+Konstata je výraz pro jakákoliv data, se kterými program pracuje a píšeme je přímo do zdrojového kódu. +Konstantou může být např. číslo, znak, řetězec, pointer, a další… +Konstanta se chová jako výraz, jako R-Hodnota (lze ji přiřadit, ale nelze přiřadit do ní). +S konstantami jsme se již setkaly v kapitole probírající přiřazení. +

+ +
+ +

Typy konstant s okomentovaným příkladem

+
+
int	32		//cele cislo (Integer)
+long	L940		//cislo typu long
+float	2.345		//cislo s plovouci radovou carkou (teckou)
+float	F940		//Jiny zapis floatu (bez tecky by nebylo jasne, ze jde o float)
+double  3.45		//cislo double
+char	'A'		//znak (pro binarni data pouzivejte unsigned char nebo lepe int)
+char[] "Muj text"	//retezec - pole znaku - viz. znak
+ +
+ +

Možnosti zápisu celých čísel (příklady)

+
+
decimálně	123
+hexadecimálně	0x1A6F
+oktálně	029
+ +
+ +

Možnosti zápisu znaků (literály - platí i pro řetězce)

+
+
decimálně	\0232 ('\0232')
+hexadecimálně	\x0A ('\x0A')
+ +
+ +

Speciální znaky

+
+
\n ('\n')	Přechod na další řádek
+\r ('\r')	Přechod na začátek řádku
+\t ('\t')	Tabelátor
+ +
+ +

Příklady literálů

+
+
char str[] = "\tPole ch\x41ru, neboli retezec,\nje to tak.";
+char str[] = "Preruseny"	" retezec\n";
+char str[] = "Preruseny " "retezec "
+	     "muze pokracovat i na dalsi radce!\n";
+ +
+ +

Konstantní proměnné

+
+ +

+Konstantní proměnná je taková proměnná, která se po inicializaci stává konstantou (nelze ji měnit, je to tedy neproměnná proměnná ;D). +Deklarace konstantní proměnné probíhá pomocí tzv. „typového modifikátoru“, v našem případě „const“. +

+ +

+Příklad: +

+
const int a, b = 32; //Promenna b jiz nepujde zmenit, promenna a pujde zmenit pouze jednou (inicializovat).
+ +
+ +

Základní operátory

+
+ +

+R-hodnota (viz. dříve) se může skládat z více prvků s vlastnostmi r-hodnoty. To uděláme za pomoci nějakých operátorů, se dvěmi hodnotami můžeme provádět různé operace (aritmetické, logické a další). k tomu nám slouží různé operátory. +

+ +
+ +

Příklad

+
+
  int x, a, b = 2;
+  x = (a = (b * 2) - 3);
+ +

+ +Na konci tohoto kódu budou proměnné „x“ a „a“ držet hodnotu 1. +

+ +

+Z toho také vyplívá, že celé přiřazení (l-hodnota = r-hodnota) je zároveň r-hodnotou a lze ho přiřadit do jiné l-hodnoty (např. proměnné). +Také si všimněme, že lze použít závorky () k seskupování výrazů a úpravě jejich priorit (víme, že násobení má přednost před sčítáním), tato základní asociativita funguje stejně jako v matematice, pokud si nejsme jisti, nemusíme experimentovat a prostě se pojistíme závorkou. +

+ +
+ +

Přehled operátorů

+
+ +

+Zde naleznete seznam různých operátorů. Některé z nich budeme používat a vysvětlíme si je, ale většinu z nich zatím potřebovat nebudeme, ale k tomuto seznamu se určitě budete potřebovat vracet. + +

+
+	sčítání
+-	odčítání
+*	násobení
+/	dělení
+
%	dělení modulo (zbytek po dělení)
+
++, --  inkrementace resp. dekrementace hodnoty, prefixový i postfixový zápis
+= *= /= %= += -= <<= >>= &= |= ^= 	jednoduché přiřazení a přiřazení s výpočtem
+
< 	menší než
+> 	větší než
+<= 	menší nebo rovno
+>= 	větší nebo rovno
+== 	rovnost
+!= 	nerovnost
+
&& 	logický součin (and)
+|| 	logický součet (or)
+
!  	logická negace
+~ 	bitová negace
+
<<, >>  bitový posun vlevo resp. vpravo
+& 	bitový součin (and)
+| 	bitový součet (or)
+^ 	bitový vylučovací (exkluzivní) součet (xor)
+
?:  	podmíněné vyhodnocení  	zprava doleva
+
. 	tečka, přímý přístup ke členu struktury
+-> 	nepřímý přístup ke členu struktury
+, 	čárka, oddělení výrazů
+
sizeof	získání velikosti objektu v bytech
+(typ)  	přetypování na typ uvedený v závorkách
+
&  	reference (získání adresy objektu)
+* 	dereference (získání objektu dle adresy)
+ +
+ +

Porovnávání

+
+ +

+V kapitole, kde budeme probírat podmínky a cykly určitě využijeme porovnávací operátory (<,>,⇐,>=,==,!=), logickou negaci (!) a logický součin a součet (&&,||). +Pokud jde o porovnávací operátory, tak vždy vrací hodnotu true (1 nebo jiná nenulová hodnota), nebo false (0), tj. pravda/nepravda. +Logický součin (&&) vrací true pouze pokud jsou obě hodnoty true. Pokud je první hodnota false, tak se druhá nevyhodnocuje (zjednodusene vyhodnocovani). +Logický součet (||) vrací true pokud je alespoň jedna z hodnot true. Pokud je první hodnota true, tak se druhá nevyhodnocuje (zjednodusene vyhodnocovani). +Logická negace vrací opak (!1 je 0, !0 je 1). +

+ +
+ +

Příklady

+
+
int a = 2, b = 3, x = 4, y = 2;
+b = !(b == a); //b bude true
+b = (b != a); //b bude true (jde o prakticky jiny zapis stejneho vypoctu)
+b = (a = 2); //casta chyba - nedojde k porovnani, ale prirazeni 2 do a a nasledne do b
+x = (x <= y); //x bude false
+y = !((1 <= 2)||(b = 7)); //y bude false, prirazeni 7 do b neprobehne (pouzito zjednodusene vyhodnocovani)
+y = 128; //y bude true
+y = 0; //y bude false
+y = !y; //y bude true
+ +
+ +

Inkrementace, dekrementace,...

+
+ +

+Hodnotu proměnné můžeme změnit i jiným způsobem, než je přiřazení: +

+
int a = 31, b;
+a++; //a bude zvětšena o 1 (jiný zápis: a = a+1; )
+a *= 2; //a bude vynásobeno 2 (jiný zápis: a = a*2; )
+b = a++; //a bude přiřazeno do b a následně zvětšeno o 1
+b = --a; //a bude zmenšeno o 1 a nasledne prirazeno do b
+ +
+ +

Operátor sizeof()

+
+ +

+sizeof je makro preprocesoru, které nám vrátí velikost daného datového typu (viz. kapitola jednoduché datové typy) v bytech. Víme, že například celé číslo (int) zabírá v paměti většinou 2 byty, výraz sizeof(int) nám tedy vrátí u většiny kompilátorů číslo 2. +

+ +
+ +

Samostatné cvičení

+
+
    +
  • Vymyslete přiřazení co nejsložitějšího výrazu, jehož výsledkem bude hodnota false.
    +
  • +
  • Jakou hodnotu bude mít následující výraz:
    +
      +
    • (((!(1 > 2 || 2 > 1)) * 2 + 4) / 2) == 7
      +
      +
    • +
    +
  • +
+ +
+ +

Standartní vstup a výstup

+
+ +
+ +

Řádkový výstup

+
+ +

+Již jsme se seznámili s použitím funkce printf(), další užitečnou funkcí je putchar(), která vypíše jeden znak/byte. +

+ +
+ +

Vstup

+
+ +

+Samozřejmě budeme potřebovat také odezvu ze strany uživatele, k tomu nám budou sloužit funkce scanf(), která je opakem printf() a getchar(), která je opakem putchar(). +

+ +

+Funkce getchar() nám vrací ASCII hodnotu jediného načteného znaku. +

+ +

+Funkce scanf() nám oproti tomu zapíše získaná data na danou adresu v paměti, to nebudeme hlouběji rozebírat, důležité ale je, že před identifikátor proměnné musíme napsat operátor ampersand (“&“). Pokud tedy budeme například chtít načíst z klávesnice desítkové číslo, použijeme tento zápis: +

+
  int a;
+  scanf("%d", &a);
+ +
+ +

Převod řetězce na číslo

+
+ +

+Často potřebujeme, aby nám uživatel zadal číslo, z terminálu můžeme číst ale pouze znaky (případně řetězce). Naštěstí pro nás existují v Ansi C funkce, které nám dovolí uskutečnit tento převod, jsou to tyto: + +

+
    +
  • atoi() - ascii to int
    +
  • +
  • atol() - ascii to long
    +
  • +
  • atof() - ascii to float
    +
  • +
+ +
+ +

Souhrnné příklady

+
+
  char text[] = "Toto je nějaký text";
+  int cislo = 5;
+  printf("Toto je text: %s a tohle cislo: %d\n", text); //Vypíše: Toto je text: Toto je nějaký text a tohle cislo: 5(a odřádkuje)
+ 
+  char ascii_cislo[] = "64";
+  cislo = atoi(ascii_cislo); //Priradi do promene cislo cislo urcene retezcem ascii_cislo[], tj.: 64.
+ 
+  char vstup[1024]; //Toto není příliš optimální řešení, protože se v něm skrývá bezpečnostní hrozba, nebo možnost kolapsu našeho programu, pokud uživatel zadá více jak 1024 znaků... My se tímto problémem ale zatím zabývat nebudeme, ovšem nutno poznamenat, že správné řešení by bylo úplně jiné.
+  int vstup_cislo;
+  scanf("%s", &vstup);
+  scanf("%d", &vstup_cislo);
+ +
+ +

Další převody

+
+ +

+Další velice používanou funkcí pro převody (např. čísla na řetězec) je sprintf(). +Tato funkce pracuje obdobně, jako printf() (kterou doufám již všichni známe), s tím rozdílem, že sprintf() přijímá ještě první argument, kterým je identifikátor řetězce, do kterého bude po zformátování výsledný řetězec uložen (printf() by ho jen vypsalo). +

+ +
+ +

Řešený příklad

+
+
+
calc.c
+
/* calc.c
+ * Napište program, který načte z řádky dvě čísla, sečte je a výsledek vypíše formou rovnice.
+ * K získání prvního celého čísla použijte přímo scanf(), druhé převeďte z řetězce získaného ze scanf() pomocí atoi().
+ * Program zkompilujte a otestujte.
+ */
+ 
+#include <stdio.h>
+#include <stdlib.h>
+ 
+int main() {
+	char a[10];
+	int x, y;
+	printf("Prvni scitanec: ");
+	scanf("%d", &x); //Prvni cislo nacteme rovnou jako dekadickou hodnotu
+ 
+	printf("Druhy scitanec: ");
+	scanf("%s", &a); //Do retezce a ulozime ascii zapis cisla (pismenka) z klavesnice
+	y = atoi(a); //Do integeru y ulozime cislo ziskane z retezce a
+ 
+	printf("Vysledek: %d+%d = %d\n", x, y, (x+y)); //Vypiseme vysledek
+}
+
+ +

+Například takto vypadá program za běhu: +

+
harvie@harvie-ntb:~/Desktop/skripta/c$ gcc calc.c -o calc -std=c99 && chmod +x calc #kompilace
+harvie@harvie-ntb:~/Desktop/skripta/c$ ./calc #spusteni
+Prvni scitanec: 2
+Druhy scitanec: 3
+Vysledek: 2+3 = 5
+harvie@harvie-ntb:~/Desktop/skripta/c$
+ +
+ +

Přesměrování vstupu a výstupu

+
+ +

+Zjistěte si, jakým způsobem umí váš operační systém přesměrovávat vstup a výstup do souborů a ze souborů, tak aby se výstup programu nevypsal na obrazovaku, ale do souboru, nebo naopak se vstup načetl ze souboru, nebo byl výstup přesměrován na vstup jiného programu. (většinou k tomu slouží operátory příkazového řádku >,»,<,|). +

+ +

+Kromě použití operátorů příkazové řádky tohoto také můžeme docílit pomocí funkce freopen() aplikované na handly stdin, stdout, nebo stderr, to ale pro nás není zatím nutné umět. +

+ +
+ +

Samostatná cvičení

+
+
    +
  • Upravte program tak, aby fungoval nad desetinými čísly (float)
    +
  • +
  • Předchozí program upravte tak, aby po spuÅ¡tění vypsal 3 očíslované možnosti a podle zadaného čísla buď sčítal, odčítal, nebo násobil.
    +
  • +
+ +
+ +

Podmínky a cykly

+
+ +

+Tyto dvě důležité věci jsou častou součástí většiny programů. +

+ +
+ +

Podmínka

+
+ +

+Podmínka je operátor, který nám umožní vykonat nějaký kód pouze pokud je splněna nějaká podmínka. Podmínka se vyhodnocuje tak, že se vypočítá hodnota výrazu předaného podmínce a pokud tato hodnota odpovídá logické pravdě (to většinou znamená nenulové číslo), vykoná se daný příkaz. +

+ +

+Jednoduchá podmínka může vypadat například takto: +

+
int a = 1, b = 2;
+if(a<b) printf("a je mensi nez b");
+ +

+Jaké operátory máme a jak se vyhodnocují jsme se již dozvěděli z kapitoly operátory, na druhou stranu to nemusí být na první pohled jasné, proto ještě v rychlosti shrnu alespoň srovnávací (komparační) operátory: + +

+
== - je rovno
+!= - není rovno
+>  - větší než
+<  - menší než
+>= - větší nebo rovno
+<= - menší nebo rovno
+!  - logická negace
+&& - logické AND (A)
+|| - logické OR (NEBO)
+ +

+ +Pokud tyto operátory použijeme na dvě čísla (operandy), výslednou hodnotou bude vždy logická hodnota (pravda/nepravda - true/false - 1/0), u většiny kompilátorů je to 0 nebo 1. Pokud tedy vyhodnocujeme podmínku (např. pomocí if()), pokaždé, když ji předáme nenulovou hodnotu, je proveden následující příkaz. Např.: +

+
if(1) if(255) if(!0) printf("tento prikaz bude proveden vzdy\n");
+if(!1) if(0) printf("tento prikaz nebude proveden nikdy\n");
+ +

+S if souvisí ještě jeden operátor a tím je else, tím můžeme určit co se stane, když podmínka splněna nebude. +

+
if(a>b) printf("a je mensi nez b\n"); else printf("a je vetsi nez b\n");
+ +
+ +

Složený příkaz (Blok kódu)

+
+ +

+Pokud několik příkazů uzavřeme do složených závorek, začnou se vůči kódu mimo ně chovat jako jeden příkaz. V podmínkách a cyklech můžeme tedy vykonat více příkazů tam, kde bychom mohli normálně vykonat pouze jeden. např. následující kód vypíše 3x „Nejaky text\n“. +

+
int podminka = 1;
+ 
+if(podminka) printf("Nejaky text\n");
+if(podminka) { printf("Nejaky "); printf("text\n"); }
+if(podminka) {
+	printf("Nejaky ");
+	printf("text\n");
+	}
+ +

+Následující kód pak zmenší hodnotu většího ze dvou čísel. +

+
if(a>b) {
+	a--;
+} else {
+	b--;
+}
+ +
+ +

Cyklus while

+
+ +

+Jde o základní cyklus, jediné, čím se liší od podmínky je to, že se příkaz neustále opakuje, dokud je podmínka splněna. +Příklady: +

+
while(1) printf("#"); //Budeme do nekonečna vypisovat znak '#'
+ 
+int i = 30;
+while(i>10) { //Budeme zmensovat i, dokud bude vetsi nez 10
+	i--;
+}
+ +
+ +

Cyklus for

+
+ +

+Cyklus for je podobný cyklu while, akorát s tím rozdílem, že kromě podmínky obsahuje také příkazy, které se spustí před začátkem cyklu a pak při každé iteraci (opakování). +

+ +

+Následující while cyklus +

+
int i = 30;
+while(i>10) {
+	i--;
+	printf("%d", i);
+}
+ +

+ +tedy můžeme zapsat pomocí for-u i takto: + +

+
int i;
+for(int i=30;i>10;i--) printf("%d", i);
+ +

+Což je mnohem přehlednější. +

+ +
+ +

Vnořené (zahnízděné) cykly

+
+ +

+Dobré je si také uvědomit, že můžeme mít například dva cykly v sobě. +

+ +
+ +

Řešený příklad

+
+ +

+Napište program, který vypíše za sebe čísla od 0 do 10 a zpět oddělené čárkami. +

+
+
loops.c
+
#include <stdio.h>
+#include <stdlib.h>
+ 
+int main() {
+	int x=1, a=0;
+	for(int i=0;i<=20;i++){
+		printf("%d", a);
+		if(i<20) printf(",");
+		if(a>=10) x=(-1);
+		a+=x;
+	}
+	printf("\n");
+}
+ 
+//EOF
+
+ +

+Výstup: +

+
harvie@harvie-ntb:~/Desktop/skripta/c$ ./loops
+0,1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0
+ +
+ +

Samostatná cvičení

+
+
    +
  • Upravte předchozí program tak, aby nepoužíval více než jeden cyklus
    +
  • +
  • NapiÅ¡te program, který 10x pod sebe vypíše číslice od 0 do 9.
    +
  • +
  • Upravte předchozí program tak, aby vykreslil Å¡achovnici (8×8) z 0 a 1.
    +
  • +
+ +
+ +

Pole

+
+ +

+Pole je datový typ skládající se z určitého počtu jiných datových typů. +Zatím jsme se s poli setkali jen jako s řetězci (řetězec je pole jednotlivých znaků, pole končí znakem s ASCII hodnotou \x00). +

+ +

+Nejlepší bude, pokud si to vysvětlíme na jednoduchém příkladu. Například budeme potřebovat uložit 10 čísel int, které budou všechny sloužit k podobnému účelu, ale je možné, že se jejich počet bude v budoucnosti měnit, nebo jsme líní pro je jednotlivě deklarovat (a byli bysme hloupí, kdybychom to tak dělali). +

+ +

+Použijeme tedy např. tuto deklaraci: +

+
int cisla[10];
+ +

+ +Tím jsme poprosili systém o 10*sizeof(int) bytů (neboli paměť potřebnou pro uložení 10 integerů, typicky to bude 20B). +

+ +

+Nyní můžeme s čísli jednoduše pracovat, musíme si však pamatovat, že ačkoli jsme nadeklarovali 10 integerů, k prvnímu přistupujeme pomocí [0] a k desátému pomocí [9], proč tomu tak je si vysvětlíme za chvilku. +

+ +
+ +

Příklad

+
+
int cisla[10], a = 2;
+cisla[0] = 1;
+cisla[1] = 2;
+cisla[a] = cisla[0]*cisla[1]+cisla[2];
+cisla[2]++;
+//promenna cisla[2] drzi nyni hodnotu 5
+ 
+cisla[10] = 18; //Zde by zase pravděpodobně došlo k pádu programu, protože se pokoušíme přistupovat k neexistující 11. položce pole.
+ +
+ +

Uložení pole v paměti

+
+ +

+držme se naší deklarace z předchozího příkladu, tedy: +

+
int cisla[10];
+ +

+V tom případě jsme si říkali, že bude v paměti alokováno 10*sizeof(int) bytů, to bude vypadat následovně: + +

+
 __ __ __ __ __ __ __ __ __ __ 
+|00|00|00|00|00|00|00|00|00|00|
+ -- -- -- -- -- -- -- -- -- --
+^                          ^
+|_ Toto je adresa &cisla   |_  Toto je adresa &cisla+9*sizeof(int) (neboli cisla[9])
+   (neboli cisla[0])
+ +

+ +Pokud si tedy zkusíme vytisknout printf(“%d\n“, &cisla);, získáme adresu v paměti (to dělá operátor &), na které je naše pole uložené, touto adresou je obyčejné číslo, je ale zvykem zapisovat ho šestnáctkově, toto je pro nás ale zatím dostačující. +

+ +

+Tím, že použijeme zápis cisla[0] dojde k tomu, že získáme přístup k sizeof(int) bytům na adrese &cisla, tedy k prvnímu integeru, když chceme přistupovat k druhému integeru v poli použijeme cisla[1], protože tím se dostáváme z adresy &cisla o jeden int dále (tedy: &cisla+1*sizeof(int)), je tedy zřejmé, že pokud se pokusíme pracovat s cisla[10], octneme se již v části paměti, která nepatří našemu programu a náš program bude ukončen, protože v jiném případě by náš program mohl ovlivňovat práci jiného programu. +

+ +
+ +

Zjištění velikosti pole

+
+ +

+Je možné, že neznáme velikost pole, a potřebujeme ho zpracovat (např. v cyklu), k tomu opět použijeme operátor sizeof(). V následujícím příkladu si také můžete všimnout, že při deklaraci pole můžeme jeho velikost určit jinou celočíselnou proměnnou (to je možné až v novějších verzích jazyka C). +Následující kus kódu ukazuje, jak zjistit a vypsat velikost pole. +

+
int i = 30;
+int cisla[i];
+//Nejaky jiny kod
+printf("Pocet cisel: %d\n", sizeof(cisla)/sizeof(int));
+ +

+Příkaz sizeof(cisla) nám vrátí počet bytů, které pole skutečně zabírá v paměti, to může být různé. nás ale zajímá kolik prvků (int) pole má a s kolika můžeme ve skutečnosti pracovat. K tomu musíme ještě toto číslo vydělit hodnotou sizeof(int) (nebo sizeof(jiny_typ_naseho_pole)), ta totiž určuje, kolik každý prvek pole zabírá v paměti. +

+ +

+Když si to shrneme: Víme, kolik místa zabírá pole v RAMce a víme, kolik má zabírat jeden jediný prvek, jednoduše tedy vydělíme (vrátíme se ve vzpomínkách do 2. třídy ZŠ ;) a máme požadované číslo, pokud nás ovšem zajímá nejvyšší „offset“ (to číslo v hranatých závorkách), jaké můžeme použít, nesmíme ještě zapomenout odečíst 1. +

+ +
+ +

N-rozměrná pole

+
+ +

+Můžeme také vytvářet mnohorozměrná pole (např.: dvou-rozměrná, tří-rozměrná, sto-rozměrná, n-rozměrná), takové mnohorozměrné pole je laicky řečeno pole polí, nebo pole polí polí polí polí, typickým příkladem je pole řetězců. +

+ +

+Deklarace takového pole může vypadat takto: +

+
int a[3][40]; //a je pole 40ti polí o 3 integerech
+//Podobná pole si většinou představujeme jako 3x40 čtverečků (40 je výška)
+char c[4][6][8];
+//Takové pole si pro změnu můžeme vizualizovat jako 8mi patrový kvádr, přičemž každé patro se zkládá z 4x6 kostiček (každá kostička drží nějaký znak).
+ +

+U složitějších polí si můžeme představit například několik takových kvádříků uspořádaných do několika polic v několika skříních v několika řadách,… +Prostě jakkoli. +

+ +

+ +Pokud máme například pole int pole[2][3], pak pole[0] je pole 3 integerů jako např. int druhe[3]. +

+ +

+Ostatní práce s poli je naprosto analogická k polím jednorozměrným. +

+ +
+ +

Řešený příklad - zpracování pole v cyklu

+
+ +

+Toto je velmi často používaná věc! Více se dozvíte v kapitole „podmínky a cykly“, tady jen uvádím jednoduchý příklad. +Můžeme si zde všimnout dvou totožných cyklů, přičemž jeden je while() a druhý for(). +

+
+
arrays.c
+
/* arrays.c
+ * Napiste program, ktery naplni pole integeru nahodnymy cisly a potom je vypise.
+ * Pouzijte cykly for i while
+ */
+ 
+#include <stdio.h>
+#include <stdlib.h>
+ 
+int main() {
+	int i, cisla[10];
+ 
+	i=0;
+	while(i<sizeof(cisla)/sizeof(int)) {
+		cisla[i] = rand(); //K generovani nahodnych cisel slouzi funkce rand()
+		i++;
+	}
+ 
+	for(i=0;i<sizeof(cisla)/sizeof(int);i++) printf("%d. cislo je: %d\n", i, cisla[i]);
+}
+ 
+//EOF
+
+ +
+ +

Samostatná cvičení

+
+
    +
  • Pomocí dvou vnořených cyklů naplňte dvojrozměrné pole znaků (char[x][y]) Å¡achovnicí (8×8) z 1 a 0, pomocí dalšího vnořeného cyklu ji pak vytiskněte
    +
      +
    • Velikost Å¡achovnice bude možno libovolně měnit pomocí dvou proměnných (int x = 8, y = 8;).
      +
    • +
    • Očekávaný výsledek:
      01010101
      +10101010
      +01010101
      +10101010
      +01010101
      +10101010
      +01010101
      +10101010
      +
      +
      +
    • +
    +
  • +
  • Upravte program z předchozího cvičení tak, aby byly protilehlé rohy spojeny osmičkami.
    +
  • +
  • Upravte program z předchozího cvičení tak, aby byl čtverec lemován nulami.
    +
      +
    • Očekávaný výsledek:
      00000000
      +08101080
      +01810800
      +00188010
      +01088100
      +00801810
      +08010180
      +00000000
      +
      +
      +
    • +
    +
  • +
+ +
+ +

Argumenty programu

+
+ +

+Další možností, jak můžeme našemu programu předat nějaká data, je to, že mu je zdělíme už při spouštění. To se provádí pomocí tzv. argumentů (můžeme se také setkat s pojmem parametry), ty předáme programu tak, že je napíšeme za jeho název oddělené mezerami. To je přesně to, k čemu dochází pokud např. ve vašem operačním systému otevíráte nějaký textový dokument, video nebo cokoli v jiném programu. V takovém případě grafické prostředí, které pravděpodobně používáte k ovládání počítače vyvolá příkaz podobný těmto: + +

+
    +
  • prehravac_filmu film.avi
    +
  • +
  • cesta/super\ jukebox jedna\ pisnicka.ogg „druha - pisnicka.mp3“
    +
  • +
  • „c:\program files\msoffice\word\word.exe“ dokument.doc
    +
  • +
+ +

+ +Můžeme si všimnout, že všechny parametry jsou odděleny mezerami, pokud je nutné, aby parametr obsahoval mezeru, dáme ho buď do uvozovek, nebo před mezeru dáme zpětné lomítko (to se na windows nepoužívá), pokud ovšem potřebujeme, aby argument obsahoval uvozovku, dáme před ni také zpětné lomítko. +

+ +

+Také by bylo dobré poznamenat, že prvním argumentem (i když se takto neoznačuje) je vždy název programu. +

+ +
+ +

Argumenty z hlediska programátora

+
+ +

+Operační systém předává našemu programu argumenty pomocí dvou proměnných. +První z nich je int argc, která obsahuje počet argumentů, pokud tedy například předáme programu dva argumenty, tak bude platit, že argc == 3, protože kromě těchto dvou souborů bylo programu předáno ještě jméno spustitelného souboru (tedy název programu). +Druhou proměnnou, která už obsahuje data konkrétních argumentů je char *argv[], jde o pole řetězců, to tedy znamená, že např. argv[0] bude první argument (název programu), argv[1] druhý, atd… +

+ +

+Aby náš program mohl od systému parametry převzít, musíme je nadeklarovat v hlavičce funkce main(), tedy např.: +

+
int main(int argc, char *argv[]) {
+	//Telo programu
+}
+ +
+ +

Padám, padáš, padáme!

+
+ +

+V případě, že by se náš program pokusil přistupovat k nezadanému argumentu, dojde k jeho pádu, protože operační systém toto místo (kde náš argument není) již používá k jiným účelům a je nežádoucí, aby k němu náš program získal přístup. Je tedy vhodné pomocí hodnoty argc vždy ověřovat, jestli konkrétní argument existuje. V opačném případě bychom se mohli od operačního systému dočkat ukončení programu a vypsání podobné chybové hlášky: „Neoprávněný přístup do paměti (SIGSEGV)“, nebo známější anglická hláška „Segmentation fault. Core dumped.“. +

+ +

+Takové ošetření by mohlo vypadat například takto: +

+
int main(int argc, char *argv[]) {
+	if(argc > 1) {
+		printf("Byl zadán argument %s\n", argv[1]);
+	} else {
+		printf("Nebyl zadán žádný argument!\n");
+	}
+}
+ +
+ +

Řešený příklad

+
+
+
args.c
+
/* args.c
+ * Napiste program, ktery vypise pocet parametru, prvni parametr a nasledujici dva secte jako cela cisla a vypise ve tvaru rovnice
+ */
+ 
+#include <stdio.h>
+#include <stdlib.h>
+ 
+int main(int argc, char *argv[]) {
+	int x, y;
+	printf("Pocet parametru: %d\n", argc);
+	printf("Jmeno programu: %s\n", argv[0]);
+	x = atoi(argv[1]);
+	y = atoi(argv[2]);
+	printf("Prvni scitanec: %d\n", x);
+	printf("Druhy scitanec: %d\n", y);
+	printf("Vysledek: %d+%d = %d\n", x, y, (x+y));
+}
+
+ +
+ +

Výstup programu:

+
+
harvie@harvie-ntb:~/Desktop/skripta/c$ ./args 2 3
+Pocet parametru: 3
+Jmeno programu: ./args
+Prvni scitanec: 2
+Druhy scitanec: 3
+Vysledek: 2+3 = 5
+
+ +

+ +Nyní se program pokusí přistupovat k neexistujícímu argumentu: + +

+
harvie@harvie-ntb:~/Desktop/skripta/c$ ./args 2
+Pocet parametru: 2
+Jmeno programu: ./args
+Neoprávněný přístup do paměti (SIGSEGV)
+
+ +
+ +

Samostatná cvičení

+
+
    +
  • upravte předchozí příklad tak, aby kontroloval počet parametrů a v případě jejich neexistence použil místo daného sčítance nulu.
    +
  • +
  • NapiÅ¡te program, který pomocí cyklu while vypíše vÅ¡echny argumenty pod sebe.
    +
  • +
  • NapiÅ¡te program, který pomocí cyklu for vypíše vÅ¡echny argumenty pod sebe.
    +
  • +
+ +
+ +

Preprocesor

+
+ +

+Už jsme si nastínili, že než se námi napsaný zdrojový kód dostane do kompilátoru, projde vyčištěním, doplněním a částečnou optimalizací v tzv. preprocesoru. Nyní si ukážeme, jak používat některé jeho direktivy (funkce), předtím je snad jen dobré poznamenat, že direktivy preprocesoru se označují znakem # (hash,mřížka,křížek,sharp). +

+ +
+ +

Inkludování - vkládání jiného souboru

+
+ +

+Preprocesor nám umožňuje vložit do zdrojového kódu veškerý obsah jiného souboru, této direktivy využijeme např. při odděleném překladu, nebo při vkládání hlavičkových souborů různých knihoven. Například inkludováním <stdio.h> si zpřístupníme Ansi C funkce pro práci s textovým vstupem a výstupem (klávesnice, obrazovka, soubory). +

+ +

+Vložení probíhá pomocí direktivy pomocí direktivy #include, např.: +

+
#include <stdio.h> //Se špičatými závorkami se soubor hledá v adresáři, kde má překladač standartní hlavičkové soubory (jako je stdio.h)
+#include "mujprogram.h" //S uvozovkami se soubor hledá ve stejném adresáři, jako je náš zdrojový kód, pokud není nalezen, hledá se ve standartním adresáři
+#include NAZEV_KONSTANTY //Viz. symbolické konstanty
+ +

+Musíme si ale dávat pozor, aby jsme omylem neinkludovali sami sebe, nebo jiný soubor, který inkluduje nás, to by pravděpodobně vedlo k zaseknutí preprocesoru v nekonečné smyčce. Jak tomu předcházet: viz. podmíněný překlad. +

+ +
+ +

Symbolické konstanty

+
+ +

+Rozdílem použití této konstanty (ve srvonání např. s definicí běžné konstanty) je to, že ji nelze po kompilaci měnit, protože preprocesor představuje z tohoto hlediska pouze pomůcku, která vyhledá v kódu identifikátory makra a nahradí je hodnotou tohoto makra (asi jako to dělá váš oblíbený textový editor pomocí funkce „najít a nahradit“). To je výhodné např. pro uchování číselných hodnot (dříve se makra používala k definici velikosti statického pole, dnes již musí Ansi C podle normy umět alokovat pole za běhu, aby bylo možné jeho velikost určit pomocí proměnné), naopak jsou makra nevhodná například pro uchování větších řetězců, které používáme na více místech (rozkopírování několika stejných desítek bytů na několik míst v kódu nikomu ještě nepřidalo). +

+ +

+Použití: +

+ +

+Nahradit všechny výskyty NAZEV_MAKRA textem retezec: +

+
#define NAZEV_KONSTANTY [retezec]
+ +

+ +Zrušit definici makra NAZEV_KONSTANTY: +

+
#undef NAZEV_KONSTANTY
+ +

+ +Jak jste si mohli všimnout, je zvykem psát identifikátory symbolických konstant celé velkými písmeny (opět až na vyjímky), abychom je oddělili od normálních proměnných. +

+ +
+ +

Makra

+
+ +

+Pokud jste ještě nečetli kapitolu Funkce, tak následující odstavec klidně přeskočte. +

+ +

+Také existují ještě zajímavější druhy symbolických konstant a těmi jsou makra, ty se liší tím, že obsahují (podobně jako funkce) argumenty, takové nám mohou nahradit menší funkci, to sice také prodlužuje kód (a velikost výsledného programu), ale nadruhou stranu tím ušetříme čas na volání funkce (což může být někdy poměrně dost), o případných zbytečných automatických přetypování a přiřazování ani nemluvě. +

+ +

+Použití: +

+
#define nasobek(a,b) ((a)*(b))
+ +

+ +zápis: +

+
nasobek(1,2)
+ +

+se potom rozvine na: +

+
((1)*(2))
+ +

+ +Zde musíme dát pozor na závorky, pokud bychom napsali jen: #define nasobek(a,b) a*b, mohlo by se nám potom stát, že makro použijeme (slovo zavoláme by nebylo příliš vhodné) například tímto způsobem: +

+
int i = nasobek(2+3,1+2)*7
+ +

+pak by se makro rozvinulo v: +

+
int i = 2+3*1+2*7
+ +

+a to je úplně jiný výraz než námi předpokládaný +

+
int i = ((2+3)*(1+2))*7
+ +
+ +

Podmíněný překlad (podmínky preprocesoru)

+
+ +

+Podmíněný překlad je možnost preprocesoru vypouštět některé části kódu na základě toho, jestli je definována nějaká symbolická konstanta, typicky jde o potlačení ladících výpisů (které by nám v případě, že je zakážeme pomocí běžné podmínky if() a například čísla, kterým je ovládáme zbytečně okupovali prostor v paměti a výkon procesoru). +

+ +

+Použití: +

+
#define LADIT //Budeme ladit
+ 
+int main() {
+	//nejake prikazy
+	#if defined(LADIT)
+		//ladici prikazy	
+	#endif
+}
+ +

+Dalším využitím podmíněného překladu je například předcházení zacykleným inkludováním, následující soubor se nenainkluduje dvakrát: +

+
#define UZ_INKLUDOVANO
+#ifndef UZ_INKLUDOVANO
+	//Zamysleny obsah souboru
+#endif
+ +
+ +

Předdefinované symbolické konstanty preprocesoru

+
+ +

+Z preprocesoru můžeme také zjišťovat různé informace a zařídit se podle nich, k tomu nám pomůžou předdefinované symbolické konstanty mezi ně patří např.: +

+
    +
  • Datum a čas překladu
    +
  • +
  • Soubor a řádek ve zdrojovém kódu
    +
  • +
  • Operační systém
    +
  • +
  • Verze C / Podpora C++
    +
  • +
  • Další informace o cílovém systému
    +
  • +
+ +
+ +

Funkce - úvod

+
+ +

+Při programování neustále voláme nějaké funkce, funkci, která nám vypíše to, zjistí tamto, vypočítá tohle, ukončí program, otevře soubor, čte ze souboru a takřka cokoli složitějšího děláme pomocí funkcí. +

+ +
+ +

Volání funkce

+
+ +

+Volání funkce (jak už víme) probíhá například zápisem: +

+
int b = 4;
+int y = secti(1, b);
+ +

+Podobný zápis předá jedničku a hodnotu proměnné int b funkci secti() a do proměnné x nám uloží návratovou hodnotu funkce (konkrétně tohoto callu - neboli zavolání). Tuto hodnotu není nutné nikam ukládat. Můžeme ji také např. použít v jiném výrazu, jako argument jiné funkce, nebo dokonce prostě zahodit/nepoužít. +

+ +
+ +

Definice funkce

+
+ +

+Ovšem se nám může stát, že budeme potřebovat použít jeden algoritmus, nebo blok kódu na více místech našeho programu a pokud bychom ho jen rozkopírovali, nebo (dokonce) opsali, byli bysme pro smích všem programátorům (včetně začátečníků). Napíšeme si tedy vlastní funkci, je to jednoduché: +

+
//Definice nasi prvni funkce - nachazi se mimo funkci main()
+int secti(int prvni, int druhe) { //Sem za hlavicku funkce je dobre psat jednoduchy popis funkce (napr. "secte dve cisla int")
+	//Telo funkce secti():
+	int x;
+	x = prvni+druhe; //Secteme prvni a druhe a ulozime do x
+	return x; //Vratime x
+} //Pozor!!! tady jiz neni strednik
+ 
+//A nyni muzeme vyzkouset nas stary dobry ukazkovy kod
+int main(int argc, char *argv[]) { //Volani ale jiz provedeme z funkce main():
+	int b = 4;
+	int y = secti(1, b);
+	printf("%d\n", x);
+}
+ +
+ +

Pravidla

+
+ +

+Při psaní nových funkcí samozřejmě také platí jistá pravidla, například to jsou: + +

+
    +
  • Identifikátor nové funkce nesmí být použit ničím jiným (zdá se to zřejmé, ale pokud bychom například chtěli nadefinovat novou funkci printf(), tak neuspějeme, i když platí jisté vyjímky).
    +
  • +
  • Typ vraceného čísla (return hodnoty) musí být stejný jako typ funkce například funkce int secti() nemůže vracet hodnotu čísla float x, můžeme se také spolehnout na tzv. automatické přetypování tedy např.:
    int secti(int a, int b) { return a+b; } //Tato funkce je hezčejší a rychlejšejší než ta, co jsme si ukázali.
    +
    +
  • +
  • Na konci definice fce nepíšeme (stejně jako například za cykly) středník! (jde o hloupou, ale častou chybu).
    +
  • +
+ +
+ +

Parametry funkce

+
+ +

+Funkci předáváme parametry (tím, jak to ve skutečnosti probíhá v procesoru se zatím zatěžovat nebudeme), jsou to např. nějaká čísla, se kterými můžeme ve funkci dále pracovat. Rozlišujeme dvoje parametry - tzv. skutečné parametry a tzv. formální parametry. + +

+
    +
  • Skutečný parametr je ten, kterým funkci voláme, tedy například při volání secti(2,3); jsou 2 a 3 skutečnými parametry funkce secti().
    +
  • +
  • Formální parametr je ten, se kterým pracujeme v těle funkce, tedy například ve funkci s hlavičkou int secti(int prvni, int druhe); tyto dvě a vÅ¡echny ostatní proměnné, které vytvoříme v těle funkce nijak neovlivňují zbytek programu a mohou se jmenovat stejně (mít stejný identifikátor) jako např. jiná proměnná ve funkci main().
    +
  • +
+ +
+ +

Návratová hodnota

+
+ +

+Návratová hodnota je cokoli, co funkce vrátí (zavoláním funkce return(), nebo dosažením konce funkce), vždy jde o stejný datový typ, jako je typ funkce (návratová hodnota je jakousi hodnotou této funkce). Pokud nezavoláme funkci return(), ale funkce se ukončí dosažením konce svého kódu, je automaticky vrácena 0. +

+ +
+ +

Cvičení

+
+
    +
  • Vysvětlete zjednoduÅ¡eně, co znamená hlavička funkce main(): int main(int argc, char *argv[]) { /*Nejaky kod*/ }
    +
  • +
  • Čím je funkce main() specifická?
    +
  • +
+ +
+ +

Samostatná cvičení

+
+
    +
  • NapiÅ¡te co nejjednodušší funkci, která korektně umocní dvě čísla typu float (jedno druhým).
    +
  • +
  • NapiÅ¡te funkci, která vypíše „hello, world\n“ tolikrát, kolik bude hodnota jediného parametru typu int.
    +
  • +
+ +
+ +

Globální proměnné, přetěžování funkcí, funkční prototypy, rekurzivní funkce

+
+ +

+Minule jsme si ukázali základy práce s funkcemi, dnes si to ještě o něco ztížíme. +

+ +
+ +

Globální proměnná

+
+ +

+Říkali jsme si, že pokud ve funkci pracujeme s proměnnými, tyto neovlivňují zbytek programu, naopak ani nemůžeme pracovat s jinými proměnnými v programu (funkce běží v jiném tzv. kontextu). Pokud bychom ale stejně chtěli nadefinovat proměnnou, která bude použitelná v celém programu (má tzv. Globální viditelnost), můžeme to udělat například její definicí/deklarací mimo funkci main, takový kód by vypadal zhruba takto: +

+
int vypis_x() { printf("x = %d\n", x); } //Vypise globalni promennou x
+int inc_x() { x++; } //Zvetsi globalni promennou x o 1
+ 
+int x = 2; //Globalni prommena x = 2
+ 
+int main(int argc, char *argv[]) { //Hlavni funkce (ta se vetsinou nekomentuje!)
+	vypis_x();
+	x = 4; //x = 4
+	inc_x(); //x = 5
+	vypis_x();
+	x = inc_x(); //x = 0 (funkce inc_x() sice x zvysi na 6, ale nasledne vrati hodnotu 0, ktera je zde do x prirazena)
+	vypis_x();
+}
+ +

+Můžeme si všimnout, že když definujeme novou funkci, děláme to také raději mimo fci main(), tato naše funkce je pak „viditelná“ (dostupná) kdekoli. +

+ +
+ +

Přetěžování funkcí

+
+ +

+Psal jsem, že identifikátor funkce nesmí s ničím kolidovat. To není tak úplně pravda. Můžeme mít několik funkcí se stejným jménem, ale jiným počtem neby typem parametrů, nejlépe to je vidět na následujícím příkladu: +

+
int secti(int a, int b) { return a+b; }
+int secti(int a, int b, int c) { return a+b+c; }
+int secti(char c) { putc c; }
+ +

+Pak pomocí volání secti() můžeme sečíst dvě, nebo tři čísla (a nemusíme tedy přemýšlet, jak se jmenuje funkce na sečtení tří čísel), pokud zavoláme secti() s jedním parametrem typu char, tak dokonce tato funkce udělá něco úplně jiného a to je vypsání znaku (což je stejně nečekané, jako sčítání s jedním číslem ;). +

+ +
+ +

Funkční prototypy

+
+ +

+Zatím jsme vždy funkci definovali jen před místem, kde jsme ji použili (to je logické, protože proměnnou také musíme vždy nejdříve nadefinovat, než s ní začneme pracovat). Mohlo by se ale stát, že otevřeme soubor se zdrojovým kódem našeho programu, a než se dostaneme k funkci main(), která obsahuje hlavní logiku našeho programu, budeme se muset prokousat spoustou pomocných funkcí, které pro nás nemají tak velký význam. +

+ +

+Můžeme tedy funkci nad main() jen „nadeklarovat“ (toto označení není úplně na místě, ale přesto je takřka pravdivé) a napsat (nadefinovat) ji níže. Tomu se říká použití funkčního prototypu. Funkční prototyp je vlastně pouze hlavička dané funkce zakončená středníkem. Funkční prototyp také nemusí obsahovat seznam parametrů (a jejich datových typů), v tom případě ale funkci nelze přetěžovat a kompilátor neví jaké parametry má očekávat (jede odzhora dolů) a proto nemůže opravit chyby jako volání s nesprávným počtem, nebo typem parametrů, které takřka vždy musí skončit s oblíbenou hláškou „Segmentation fault“, neboli neoprávněný přístup do paměti. +

+ +

+V případě, že používáme funkční prototypy, tak stručný komentář píšeme k prototypu, nikoli k tělu funkce. +

+ +

+Bývá také zvykem, že se funkční prototypy dávají do hlavičkového souboru (viz. kapitola Preprocesor), který se jmenuje stejně jako náš zdrojový kód, s tím rozdílem, že místo přípony .c má příponu .h, to je užitečné, pokud chceme tyto funkce používat i v jiných souborech našeho projektu (tomu se říká tzv. oddělená kompilace). Tento hlavičkový soubor se pak includuje nejen do našeho zdrojového kódu, ale do všech dalších souborů, které chtějí mít k těmto funkcím přístup. +

+
int tisk(int x); //Funkce vypise prvni parametr jako int a vrati jeho dvojnasobek (pozor, tady strednik pro zmenu je!)
+//int tisk(); //Toto je druha moznost zapisu funkcniho prototypu, tedy bez parametru...
+ 
+int main(int argc, char *argv[]) {
+	tisk(4);
+}
+ 
+int tisk(int x) {
+	printf("%d\n", x);
+}
+ +
+ +

Rekurzivní funkce

+
+ +

+Rekurzivní funkce je funkce, které volá sama sebe, musíme ale pamatovat na to, že pokud nebude počet rekurzivních volání konečný, tak bude nekonečný, to v praxi znamená, že takový program se logicky zasekne v nekonečné smyčce, což vyústí v jednu ze tří věcí. Buď dojde paměť, nebo jiné prostředky, program začne velmi špatně hospodařit s časem CPU a „vycucne“ výkon, který potřebují jiné programy, nebo zůstane stát na místě a dokola opakovat nějakou jednoduchou akci. +

+ +

+Možná není na první pohled zřejmé, k čemu jsou takové funkce dobré, uvedu vám tedy příklad z praxe, který jsem sám několikrát použil a je používaný ve spoustě programů. Představte si, že potřebujete vypsat, nebo prohledat obsah adresáře včetně podadresářů a jejich podadresářů, atd… Jak to tedy uděláme? Jednoduše si napíšeme funkci, která otevře zvolený kořenový adresář (jeho jméno se předává jako parametr) a projíždí si ho položku po položce, když narazí na soubor, tak ho zpracuje (např. vypíše jeho název), pokud ale narazí na adresář, tak ho nejen vypíše, ale potom ještě rekurzivně zavolá sama sebe a předá si cestu k tomuto adresáři tak, že k názvu kořenového adresáře připojí jméno adresáře k prohledání, aby vznikla celá cesta. Dovedete si tedy představit, že ve finále si tímto postupem projedeme všechny složky a podsložky a jejich podsložky ve zvoleném adresáři. +

+ +

+Takže rekurzivní funkce jsou velmi výhodné, je-li třeba operovat například nad nějakými stromovými strukturami, na druhou stranu se ale dají použít i jinak než ke zkoumání nebo vytváření (např. kreslení) stromů. +

+ +

+Tady je příklad jednoduché rekurzivní fce: +

+
int rekurze(int x, int y, int z) {
+	if(x>z) return(rekurze(x-y, y, z));
+	return(x);
+}
+ +

+Pokud tuto funkci zavoláme (např.: rekurze(10, 1, 0);), bude volat sama sebe a postupně odečítat od zadaného parametru x parametr y, dokud nebude platit, že x⇐z, pak vrátí x, v našem případě bude návratem hodnota 0. +

+ +
+ +

Samostatná cvičení

+
+
    +
  • NapiÅ¡te rekurzivní funkci, která vypíše „hello, world\n“ tolikrát, kolik bude hodnota jediného parametru typu int.
    +
  • +
  • Nadefinujte globální proměnnou typu int a napiÅ¡te funkci, která zvětší její hodnotu o číslo zadané jako parametr.
    +
  • +
  • Tuto funkci přetěžte a udělejte druhou, která sečte nejdřív dva parametry dohromady a pak toto číslo teprve přičte k vaší globální proměnné.
    +
  • +
  • Pro tyto dvě funkce vytvořte funkční prototypy a přesuňte jejich kód pod funkci main(), ve které je odzkouÅ¡ejte.
    +
  • +
  • Zkuste vypočítat, kolikrát se zavolá fce rekurze() z výkladu (výše) při volání rekurze(10, 1, 0);, potom to vyzkouÅ¡ejte, použijte k tomu globální proměnnou int a.
    +
  • +
  • Co funkce vratí pro hodnoty 4 a 3?:
    int ff1(x, y) {
    +	if (x>0) return ff1(x-1, y)+1;
    +	return y;
    +}
    +
    +
  • +
  • Co funkce vratí pro hodnoty 2 a 7?:
    int ff2(x, y) {
    +	if (x < y) return ff2(x+1,y);
    +	return x;
    +}
    +
    +
  • +
  • Co funkce vratí pro hodnoty 2 a 4?:
    int ff3(x, y) {
    +	if (x == 0) return 0;
    +	return ff3(x-1,y)+y;
    +}
    + +

    +====== Pointery (ukazatele) ====== +

    +
    +
  • +
+ +

+Doteď platilo, že když jsme potřebovali pracovat s nějakým kusem paměti (proměnnou), jednoduše jsme ji nadeklarovali (nebo nadefinovali) a kompilátor se za nás postaral o to, aby se po spuštění programu nalézala v paměti a my s ní mohli pracovat. +

+ +
+ +

Referencování

+
+ +

+Základní operací kterou musíme znát je použití referenčního (& - Ampersand) a dereferenčního (* - Hvězdička) operátoru. +

+ +

+Pokud aplikujeme referenční operátor na některou z proměnných (nebo cokoli jiného, co je fyzicky uložené v paměti), dostaneme adresu v paměti, na které je tento objekt umístěn. Např. následující kód, který by normálně měl vytisknout hexadecimální (šestnáctkovou) interpretaci hodnoty proměnné cislo nám díky operátoru “&“ před identifikátorem proměnné vytiskne adresu v paměti (na které je samozřejmě uložen obsah naší proměnné). +

+
int cislo = 2;
+printf("0x%X\n", &cislo);
+ +

+Nutno ještě podotknout, že bývá zvykem, že se šestnáctkové číslo (to, které vypíšeme pomocí “%x“ nebo “%X“) pro rozlišení od čísel v jiných číselných soustavách (desítkové, dvojkové, osmičkové) zapisuje s „0x“ na začátku, formátovací řetězec pro 'slušné' vypsání čísla v šestnáctkovém tvaru pomocí standartní funkce printf() (adresy v paměti a adresy vůbec nebývá zvykem udávat jinak než šestnáctkově) by tedy vypadal například takto: „0x%X“, s odřádkováním pak takto: „0x%X\n“. +

+ +

+A proč se operátoru “&“ říká „referenční“? Je to jednoduše proto, že nám vrací referenci (neboli odkaz) na proměnnou a sice v podobě její adresy. +

+ +
+ +

Dereferencování

+
+ +

+Ještě užitečnější možností, než je referencování je možnost tzv. dereference. Dereferencování nám umožňuje naopak pracovat s pamětí, pokud známe její adresu. Dereferencování probíhá pomocí operátoru „*“. To můžete vidět na následujícím příkladu: +

+
int data, adresa;
+ 
+data = 32; //Inicializace promenne
+adresa = &data; //Do promenne adresa ulozime adresu promenne data (pomoci referencovani)
+printf("0x%X\n", adresa); //Vytiskneme si adresu
+printf("%d\n", *adresa); //Na promennou adresa pouzijeme dereferencni operator a vytiskneme tedy hodnotu promenne data
+ 
+*adresa = 23; //Zapiseme 23 do pameti urcene adresou ulozenou v promenne adresa
+printf("%d\n", data); //Tim, ze jsme zapisovali na adresu ziskanou referenci romenne data, jsme zmenili i hodnotu promene data
+ 
+//Nyni lze tedy tvrdit, ze hodnoty data a *adresa jsou to same.
+//Stejne jsou i hodnoty &data a adresa.
+ +

+Pokud používáme proměnnou pouze na uložení jiné adresy a pomocí dereference přes ní přistupujeme k datům na této adrese, takové proměnné říkáme pointer. Toto označení není špatné ani v případě, že jím titulujeme přímo tuto adresu. +

+ +

+Dalším pěkným příkladem může být také toto: +

+
int data;
+*(&(*(&data))) = 32; //To je to same jako: data = 32;
+ +
+ +

Neoprávněný přístup do paměti

+
+ +

+Neoprávněný přístup do paměti je zatím asi jediná chyba, která nás při programování potkala, pokud tedy mluvíme o chybách, které neodchytí kompilátor (nebo preprocesor), ale nastanou až za běhu programu. V podstatě jde o to, že pokud se program pokusí číst nebo zapisovat do paměti, kterou si nealokoval (tudíž je buď volná, nebo patří někomu jinému), systém ho zarazí a z bezpečnostních důvodů ukončí (takový přístup může signalizovat, že se někdo pokouší program nabourat, nebo sám o sobě způsobit jiné škody). +

+ +

+Jak si takový neoprávněný přístup nasimulovat? +

+
int *a, b;
+a = 31337; //Toto je vymyslena adresa, ktera pravdepodobne nepatri nasemu programu (teoreticky by mohla, ale pravdepodobnost je celkem miziva)
+*a = 32; //Pokusime se zapsat na neplatnou adresu -> Pad programu
+b = *a; //Pokusime se cist z neplatne adresy -> Taktez Segmentation fault (sem se uz program nedostane, protoze havaroval)
+ +
+ +

Správná deklarace pointerů

+
+ +

+Všiměte si, že jsem v nadpisu použil slovo deklarace pointerů, nikoli definice. To proto, že adresa uchovávaná v pointeru by měla být zjištěna až za běhu programu. Pokud jí zapíšeme přímo do kódu, tak program buď spadne, nebo bude-li fungovat, tak jenom někde a někdy, podle toho, co na dané adrese je. +

+ +

+Chceme li tedy vytvořit pointer například na integer, uděláme to takto: +

+
int *cislo, a;
+cislo = &a; //inicializace
+ +

+S tím jsme se již setkali v předchozích příkladech, ale já jsem to záměrně nechal až na konec. +Proč je u pointeru nutné určit, na jaký datový typ bude ukazovat si povíme později. Pro nás je ale důleřité, že pointer nezabírá tolik místa, jako může být nutné pro uložení dat, která budou na cílové adrese. To si jednak musíme uvědomit při deklaraci a za druhé nám to může urychlit program tak, že nějaké funkci předáme pouze pointer (ta ho musí očekávat) a funkce tak pracuje skrze tento pointer (adresu) přímo nad našimi daty, aniž by se vytvářela jejich kopie v kontextu funkce. Této možnosti se říká předání odkazem a dalo by se to přirovnat k situaci ze skutečného života, kdy potřebujete vykonat nějakou stavební úpravu a můžete (s nadsázkou) buď odnést celý dům k zedníkovi, nebo můžete zedníkovi donést jen papírek s adresou tohoto domu (tedy pointer). +

+ +
+ +

Dynamická alokace paměti

+
+ +

+Než začneme s dynamickou alokací paměti, je ještě je dobré vědět, že je slušné, dobré, praktické, důležité a nevím jaké ještě to, že pokud máme pointer na neexistující objekt (v C znamená pojem objekt něco jiného, než v oběktových, nebo objektově orientovaných jazycích), tak bysme měli tento pointer nastavit na hodnotu NULL (my se spokojíme s přiřazením 0), takovému pointeru se pak říká nulový pointer, nebo pointer na NULL. Například takto: +

+
int a, b;
+a = &b;
+*a = 32;
+a = NULL; //Zrusime pointer
+ +
+ +

Funkce pro dynamické přidělování paměti

+
+ +

+Abychom mohli využívat tyto funkce, musíme nainkludovat hlavičku stdlib.h (tedy: #include <stdlib.h>). Je pravděpodobné, že na některých kompilátorech (především těch z GNU rodiny) by se vám program zkompiloval i bez vložení tohoto hlavičkového souboru, protože jde o jeden z nejzákladnějších, tak je možné, že již je nainkludován, ale to není dobře, protože pokud se takový program pokusíte zkompilovat jinde, tak se vám to nepodaří, to také vyčtete z varovných hlášek, kterými vás gcc poučí, pokud soubor nenainkludujete. Jde především o funkce malloc() a free(). První z nich nám umožní za běhu programu alokovat potřebné množství paměti, ta druhá ji potom zase dokáže uvolnit (tedy navrátit operačnímu systému a umožnit tak její využití k jiným účelům). +

+ +
+ +

Funkce malloc()

+
+ +

+Tato funkce přijímá jediný parametr, kterým je počet bytů, které si má od OS vyžádat, potom vrátí pointer na alokované místo (jeho první byte). Pokud se z nějakého důvodu nepodaří tuto paměť získat, malloc() vrací nulový pointer. Když potřebujeme alokovat např. integer, musíme si zjistit, jakou velikost má int na našem kompilátoru. Již víme, že se to provádí pomocí operátoru sizeof(), tedy sizeof(int). Následující příklad ukazuje správnou alokaci a inicializaci dvou integerů, jeden staticky, druhý za běhu programu: +

+
+
dynamic.c
+
#include <stdlib.h>
+ 
+int main() {
+	int a, *b;
+	b = NULL; //Pro jistotu a ze zvyku priradime do b nulu (abychom se omylem nepokusili pracovat s cizi pameti)
+ 
+	a = 2600;
+ 
+	b = malloc(sizeof(int)); //Pokusime se alokovat pamet o velikosti integeru
+	if(!b) { //Pokud se nam nepodari alokovat pamet
+		printf("Chyba pri malloc()!\n"); //Vypiseme chyb. hlasku
+		exit(1); //A skoncime s chybovym kodem 1
+	}
+ 
+	*b = 1337;
+}
+
+ +

+Možná je dobré vědět, že operačnímu systému se nemusí vždy hodit množství paměti, jaké vyžadujete a přidělí vám trochu víc (nebo samozřejmně nic, tedy NULL). +

+ +
+ +

Funkce free()

+
+ +

+Funkci předáme jako parametr pointer/adresu již předem alokované paměti, funkce se postará o to, aby byla tato paměť uvolněna a navrácena OS k dalšímu použití. Věřím, že na demonstraci postačí jednoduchý příklad: +

+
int *a;
+a = NULL;
+a = malloc(sizeof(int));
+if(!a) {
+	printf("Chyba pri malloc()!\n");
+	exit(1);
+}
+*a = 31337;
+ 
+free(a); //Uvolnime pamet
+a = NULL; //Pointer, ktery ukazuje na "cizi pudu" nastavime na NULL
+ +

+Takže si musíme pamatovat, že takový pointer, který nám zůstal po uvolnění funkcí free() musíme co možná nejdříve nastavit na NULL. Nebývá žádnou zvláštností, když se tyto dvě neoddělitelné operace zapisují na jeden řádek (kompaktnější vzhled a logika kódu): + +

+
free(a); a = NULL;
+ +
+ +

Kam se starým smetím?

+
+ +

+Může se nám také díky nějaké chybě v logice programu, nebo nějaké jiné nepozornosti stát, že budeme alokovat a alokovat paměť, ale už ji zapomeneme uvolňovat. A protože C (ani C++) nemá tzv. Garbage collector (Sběrač smetí), musíme uvolnit paměť, než pointer na ní zahodíme. Z následujícího příkladu by to mělo být jasné: +

+
int *data;
+data = malloc(sizeof(int));
+data = malloc(sizeof(int)); //Alokujeme podruhe, tim prijdeme o adresu prvniho alokovaneho prostoru, a uz nikdy se nam ho nepodari uvolnit
+ +

+Většinou se samozřejmě paměť uvolní při ukončení programu (OS by měl uvolnit vše, co po programu v paměti zbylo), ale určitě nelze 100% věřit tomu, že například M$ Windows někde sem tam něco nezapomenou. Zkuste si například tento kód: + +

+
while(1) malloc(1024);
+ +

+ +Otevřete si správce procesů (htop, top, tasklist, taskmgr) a zjistěte, kolik paměti náš proces zabírá (virtuální, fyzické i celkové). Pošlete procesu signál pro ukončení (nebo ukočete program, jak jste na vašem OS zvyklí) a sledujte, jak se paměť pomalu uvolňuje. +

+ +
+ +

Opakovací ukázka pointerů a dynamické alokace paměti

+
+
    +
  • Ujistěte se, že chápete celý následující kód, v opačném případě se okamžitě obraÅ¥te na nejbližšího profesora (nebo rychle utečte).
    +
  • +
  • Předpovězte, co program zhruba vypíše a svoje doměnky si vyvraÅ¥te jeho kompilací a spuÅ¡těním:
    +
  • +
+
+
hadanka.c
+
#include <stdio.h>
+#include <stdlib.h>
+ 
+int main() {
+ 
+        int prvni; //Staticky (za prekladu) alokovana promenna typu int
+ 
+        int *druha; //Staticky alokovany pointer na promennou typu int
+        druha = malloc(sizeof(int)); //Dynamicky (za behu) alokovana promenna typu int
+        if(!druha) {
+                printf("Chyba!\nNepodarilo se alokovat promennou *druha\n");
+                exit(1);
+        }
+ 
+        prvni = 11;
+        prvni = 22;
+        prvni = *(&prvni)+1;
+        //druha = 22; //Ukazkova chyba -> SIGSEGV
+        *druha = 22;
+ 
+        //Hodnoty promennych
+        printf("Hodnoty promennych:\n");
+        printf("prvni == %d\n", prvni);
+        printf("druha == %d\n\n", *druha);
+ 
+        //Vypis adres, na kterych jsou promenne ulozeny
+        //Desitkove a pak hexadecimalne (s prefixem 0x)
+        printf("Adresy v promennych pameti:\n\n");
+        printf("prvni je na %d = 0x%X\n", &prvni, &prvni);
+        printf("druha je na %d = 0x%X\n\n", druha, druha);
+ 
+        free(druha); //Uvolnime alokovanou pamet
+ 
+        exit(0); //Na konci programu se samozrejme teoreticky uvolni vse
+ 
+}
+
+ +
+ +

Dynamická pole

+
+ +

+V této kapitole si představíme způsob, kterým můžeme pracovat s polem alokovaným až za běhu programu. +

+ +
+ +

Alokace

+
+ +

+Na následujícím příkladu si ukážeme, jak je to doopravdy s definicí (nebo deklarací) polí. +

+
unsigned char static[10];
+unsigned char *dynamic;
+ +

+V obou případech vytvoříme pointer na char (případně pole), jediný rozdíl je v tom, že static je konstanta, kterou nelze měnit a obsahuje pointer na již alokované místo v paměti (to se alokovalo při definici), ale dynamic neobsahuje nic (resp. není inicializovaný) a nealokuje žádné místo (alokuje pouze místo pro sebe). +

+ +

+Takže když chceme dynamic začít používat stejně jako static, stačí nám použít tento zápis: +

+
unsigned char static[10];
+unsigned char *dynamic; //Deklarace pointeru na char (případně pole charů)
+ 
+dynamic = malloc(10); //Alokujeme 10 bytů a pointer na ně přiřadíme do pole
+if(!dynamic) {
+	printf("Nelze alokovat paměť!\n");
+	exit(1);
+}
+ +

+Nyní můžeme k oběma polím přistupovat následujícím způsobem: +

+
static[3] = 'a';
+dynamic[3] = 'a';
+ 
+*(static + 3 * sizeof(char)) = 'a';
+*(dynamic + 3 * sizeof(char)) = 'a';
+ +

+Jak vidíte, k oběma polím (jak statickému tak dynamickému) můžeme přistupovat naprosto totožným způsobem, tedy pomocí operátoru [], který (jak jsme nyní zjistili) také zahrnuje dereferenci, nebo pomocí čistě dereferenčního operátoru a pointerové aritmetiky. +

+ +
+ +

Pokročilé postupy

+
+ +

+Pokud potřebujeme pole o proměnné velikosti, tak jediným možným způsobem zůstává vždy alokovat nové pole (o jiné velikosti) a stará data do něj v cyklu přetáhnout. Je samozřejmě vhodné staré pole uvolnit (pomocí free()). +

+ +
+ +

Přetečení bufferu

+
+ +

+Dobré je také vědět, že pokud načítáme jakákoli data od uživatele (např. z argumentů, klávesnice, sítě nebo souboru) a chceme je uložit do pole (např. řetězce), musíme pohlídat, aby data nepřetekla nad velikost pole, v takovém případě by mohlo dojít k pádu programu pokud by programu byl předán příliš dlouhý řetězec, nebo dokonce zápisu nebezpečného kódu na významná místa v paměti, pokud by se někdo pokusil program napadnout záměrně. Je tedy nutné si hlídat, jestli nepřekračujeme maximální offsety pole. +

+ +
+ +

Samostatná cvičení

+
+
    +
  • NapiÅ¡te program, který dokáže do statického pole načíst z klávesnice libovolný řetězec tak, aby nebyla přesažena velikost pole. Nezapomeňte na to, že poslední znak pole musí být nulový.
    +
  • +
  • Vytvořte obdobu předchozího programu, s tím, že se pole alokuje dynamicky.
    +
  • +
  • Zkuste napsat program tak, aby zvládl načíst libovolně dlouhý řetězec do pole o proměnné velikosti.
    +
  • +
+ +
+ +

Spouštění externích programů

+
+ +

+Tato kapitola by měla nastínit, jakým způsobem je možné zavolat externí program (příkaz), stejně, jako byste ho třeba napsali do příkazové řádky. +

+ +
+ +

Funkce system()

+
+ +

+Funkce system() dokáže spustit příkaz a to dokonce s využitím operátorl příkazového interpretu (např.: <,>,»,|), ten jí předáme jako obyčejný řetězec, tedy například system(„ls“);, s tím, že výstup tohoto příkazu bude vypsán na obrazovku. +

+ +

+Samozřejmě si musíme uvědomit, že ve chvíli, kdy použijeme podobné volání externího programu, se náš (relativně přenositelný) program stává závislý na existenci daného příkazu na cílové platformě. Tedy například pokud budeme chtít uživateli zobrazit seznam souborů voláním příkazu „ls“, program nám bude bezproblémově fungovat na většině UNIXových systémů naopak na Windows bychom museli tento příkaz změnit na „dir“. +

+ +

+V případě, že je nezbytně nutné volat externí programy, je dobré na začátku programu nadefinovat symbolické konstanty s cestou k tomuto programu, nebo příkazy například načítat z nějakého konfiguračního souboru, který se bude pro každou platformu lišit, také je možné aby náš program nějakým způsobem automaticky ověřoval, jestli program existuje, nebo třeba od někud zjistil, na jaké běží platformě a podle toho se zařídil. +

+ +
+ +

Další funkce pro práci s externími programy

+
+ +

+Existuje spousta dalších funkcí, které vám umožní pokročilejší práci se spustitelnými soubory, jako je například nahrazení našeho programu v paměti jiným, spuštění na pozadí, otevření procesu jako souboru a čtení a zápis dat na jeho I/O. +

+ +
+ +

Práce s proměnnými prostředí

+
+ +

+Proměnné prostředí jsou proměnné, které nám poskytuje program, který náš program spouští (většinou příkazový řádek, nebo grafické prostředí). Tyto proměnné jsou nahrány do paměti našeho programu spolu s jeho kódem. +

+ +

+Typickou proměnnou prostředí je „PATH“, proměnná, ve které jsou uložené cesty k adresářům, ve kterých se hledá program, který se pokoušíme spustit, pokud není nalezen v aktuálním adresáři. Pokud vás zajímá, jaké další proměnné váš OS běžně poskytuje, zkuste si příkazy export na UNIXech, nebo set na Windows, pomocí těchto příkazů lze také nastavit nové proměnné, nebo změnit stávající. Existuje funkce getenv(), která nám vrátí pointer na danou proměnnou. Následující příklad ukazuje, jak vytisknout námi zvolenou proměnnou prostředí: +

+
+
getenv-path.c
+
#include <stdio.h>
+#include <stdlib.h>
+ 
+int main ()
+{
+  char *p;
+  p = getenv( "PATH" );
+  if (p != NULL) printf ("PATH: %s", p);
+}
+
+ +
+ +

Větvení procesu, paralelní zpracování programu

+
+ +
+ +

Funkce fork()

+
+ +

+Pokud potřebujeme v našem programu opustit lineární řízení, jinak řečeno - dělat dvě (a více) věcí najednou. Můžeme pomocí systémového volání fork() vytvořit dokonalou kopii procesu našeho programu, která se bude lišit pouze tím, že návratová hodnota fork() v ní bude 0 a samozřejmě bude mít jiné PID (identifikační číslo procesu). Volání fork() (neboli větvení) je výsadou pouze UNIXových (a samozřejmě UNIX-Like) systémů a na MS Windows bychom podobnou věc museli řešit jinak a daleko složitěji. +

+ +

+Abych vás nenapínal, tady je první příklad: +

+
int main() {
+	if(fork()) return;
+	/* Tento kod se bude jiz provadet na pozadi... */
+	sleep(10);
+	printf("BAF!\n");
+}
+ +

+V našem případě jsem zavolali fork() hned na začátku programu, tím se vytvořili kopii našeho procesu, v originále se návratová hodnota volání fork() rovnala 1, to jsme ověřili podmínkou, takže v prvním procesu se nám vykonal return() a tím pádem se první proces zavřel. Máme tedy nový proces, který ovšem není tak pevně svázán s naší příkazovou řádkou a ta se tedy uvolní (a budeme moci normálně dále pracovat a spouštět další programy). Protože se nám ale v procesu nakopírovalo číslo file deskriptoru (ukazatele na soubor), pomocí kterého se dá vypisovat do konzole (na STDOUT), může náš tak trochu záškodnický program na pozadí za 10 sekund vypsat nic netušícímu uživateli „BAF!“ a to klidně doprostřed výpisu jiného programu (podobně, jako se vám třeba v BASHi můžou vypisovat oznámení o nových mailech). +

+ +

+Spuštění programu na pozadí je ale pouze začátkem toho, co fork() doopravdy umí. Podívejme se na následující kód.: +

+
	/* nejaky kod */
+	if(!fork()) {
+		udelej_neco();
+		return;
+	}
+	/* dalsi kod */
+ +

+V tomto případě se zavolá na pozadí pouze funkce udelej_neco() a program bude ihned pokračovat dále. Typickým příkladem může být stahování nějakého velkého souboru (nebo více souborů) z webového serveru (pro zjednodušení jsem použil externí program wget volaný pomocí system()): +

+
+
fork.c
+
#include <stdio.h>
+ 
+int main() {
+	if(!fork()) { system("wget http://server/soubor1"); return; }
+	if(!fork()) { system("wget http://server/soubor2"); return; }
+	if(!fork()) { system("wget http://server/soubor3"); return; }
+	if(!fork()) { system("wget http://server/soubor4"); return; }
+	return;
+}
+
+ +

+Tím docílíme toho, že se budou všechny 4 soubory stahovat najednou a ne jeden podruhém, jako kdybychom pouze 4x pod sebou zavolali system(). Díky tomu, že jsem do podmínky přidal vikřičník jsem si zajistil to, že se soubor bude stahovat v kopii a nikoli v originálním procesu. Původnímu procesu se říká parrent (rodič) a kopie se označuje jako child (dítě) i když v případě fork() jsou oba procesy spíše bratry či sestřičkami. Důležité je také to, že po stažení souboru zavoláme return(), protože kdybychom to neudělali, tak by se každý soubor mohl stáhnout vícekrát, protože se náš program v paměti zkopíroval i s tím, co má dělat potom. +

+ +

+Stinnou stránkou celé věci je to, že jednotlivé procesy se nemohou vzájemně příliš dorozumívat, musíme pak přistoupit k použití prostředků jako jsou soubory, pojmenované pajpy (fifo roury), unix domain sockety a nebo dokonce síťové sockety. +

+ +

+Další věcí je, že náš program bude velmi těžkopádný, pokud budeme používat fork() ve větším měřítku, například pokud bychom psali webový (nebo jiný) server, tak musíme obsluhovat více uživatelů najednou. Pokud bychom ale na každého uživatele vytvořili jednu kopii procesu, může se nám stát, že nám brzo začnou docházet systémové prostředky (mluvíme o serverech s ~100 requesty najednou), pokud nám nedojdou hardwarové prostředky, tak se nám zaplní process table (vyčerpáme maximální počet procesů povolený operačním systémem), proto je lepší počet 'forků' omezit a ještě lépe používat thready (viz. dále). +

+ +

+Pro zájemce: Existuje lokální DoS útok pojmenovaný ForkBomb, který způsobí zaplnění tabulky procesů a vede neodvratně k zamrznutí systému, protože nelze vytvořit žádný nový proces, nemůžeme ani spustit program, který by útok ukončil. Uvádím to proto, že k podobné věci může dojít pokud někde voláme fork() v cyklu (např. potřebujeme n podprocesů) a omylem vytvoříme nekonečnou smyčku. +

+ +

+Např. takto: + +

+
while(1) fork();
+ +

+ +Na UNIXových systémech se dá proti nečekané chybě bránit tím, že nastavíme limit počtu procesů pro každého uživatele, v případě podobného výmrzu můžeme jako jiný uživatel (typicky root) procesy pozabíjet. Na Windows proti této chybě takřka není ochrana. A ačkoli v jádře systému Windows nic jako fork() neexistuje, může nastat podobný problém, pokud se nám omylem podaří to, že jeden program neustále spouští sám sebe. +

+ +
+ +

Thready

+
+ +

+Další možností jak může náš program dělat více věcí najednou jsou takzvané thready (vlákna) ty se od forku liší v tom, že nejde o kopii procesu, ale jeho součást. Thread je tím pádem jakýsi podřadný proces. Narozdíl od forku existují thready i na Windows. Další výhodou je, že thready mohou dále komunikovat se zbytkem procesu, například pomocí globálních proměnných (například proměnné deklarované mimo funkci main()), potom je ale třeba hlídat, aby se dva thready nepokusily zapisovat do stejné proměnné (== stejného místa v paměti), potom by mohlo dojít k poškození těchto společných dat. K tomu se používá tzv. synchronizace threadů. Práce s thready už je ale složitější a proto si ji zde nebudeme ukazovat… +

+ +
+ +

Samostatná cvičení

+
+
    +
  • NapiÅ¡te program, který vypíše, na jakém místě se v paměti nachází proměnná prostředí, jejíž název byl zadán jako parametr.
    +
  • +
  • NapiÅ¡te program, který vezme vÅ¡echny argumenty (kromě prvního), spojí je do jednoho řetězce (oddělené mezerami) a výslednou větu vytiskne orámovanou znakem (případně prvním znakem řetězce), který je udaný prvním argumentem (vlevo a vpravo bude jeden znak mezera). Výsledný výstup pak mže vypadat napříkad takto:
    +
  • +
+
./ramecek * "Ahoj lidi," jak\ se máte?
+***************************
+* Ahoj lidi, jak se máte? *
+***************************
+ +
+ +

Práce se soubory

+
+ +

+Doteď jsme naše data ukládali jen do paměti RAM. O všechna data uložená v paměti RAM přijdeme v okamžiku ukončení programu, nebo vypnutí počítače. To nemusí bý vždy postačující a můžeme chtít svoje data uložit nějakým trvanlivějším způsobem, ideálním řešením bude jejich zapsání na pevný disk, konkrétně do souboru. +

+ +

+Klasickým příkladem práce se soubory je jednoduchý tetový editor (nano, gedit, SciTE, notepad, atd…). Takový editor při svém spuštění načte zvolený soubor do paměti, kde s ním může uživatel pracovat a před svým ukončením tato data z paměti uloží i s úpravami zpět do souboru na příslušném paměťovém médiu. +

+ +

+Ovšem si pamatujte, že problematika základní práce se soubory je mnohem komplikovanější, než jak je zde popsána a pokud máte zájem, doporučuji si projít odkazy na konci této publikace. +

+ +
+ +

Otevření souboru

+
+ +

+Abychom mohli pracovat se souborem, musíme ho nejdříve otevřít. Se soubory se dá pracovat například pomocí tzv. file deskriptorů, neo také ukazatelů (je to podobné, jako nám již známé pointery, s tím rozdílem, že neukazují na disk, ale obsahují číslo, které operační systém tomuto souboru přiřadil a podle kterého ho dále rozlišuje). Funkce na práci se soubory opět zpřístupníme vložením hlavičkového souboru <stdio.h>. +

+ +

+Jak tedy takové otevření a čtení ze souboru funguje, to pochopíte z následujícího kusu kódu: +

+
FILE *fp; //Nadeklarujeme deskriptor fp
+fp = fopen("soubor.txt", "r"); //Otevíráme "soubor.txt" v režimu "r", tedy "pro čtení"
+if(fp == NULL) { //Osetrime chyby (napr. soubor neexistuje, nebo nemame prava pro cteni)
+	printf("Nepodarilo se otevrit soubor!\n");
+	exit(1);
+}
+ 
+char retezec[101];
+fgets(retezec , 100, fp); //Nacteme 100 bytů (znaků) z fp do retezce retezec
+puts(retezec); //Vytiskneme tento retezec na obrazovku
+ 
+fclose(fp); //Zavreme soubor
+ +

+A tady je například správný postup, jak vypsat celý soubor znak po znaku na obrazovku, všimněte si, že každý znak po celou dobu porovnávám s konstantou EOF, v případě, že jí odpovídá, znamená to, že je soubor na konci (EOF znamená End Of File): +

+
int c;
+while((c = fgetc(fp)) != EOF) putc(c);
+ +
+ +

Režimy fopen()

+
+ +

+Když pomocí fopen() otevíráme soubor, můžeme ho otevřít celkem asi v 9ti režimech. Toto jsou 3 základní: + +

+
    +
  • „r“ - read - čtení
    +
  • +
  • „w“ - write - zápis
    +
  • +
  • „a“ - append - zápis (přidání) na konec
    +
  • +
+ +

+ +Ke každému režimu můžeme ještě připojit „b“, tedy: „rb“, „wb“, „ab“, to znamená, že se soubory bude zacházeno čistě po binární stránce, tedy že to, co do souboru zapíšete v něm určitě bude a naopak, že přečtete to, co v něm skutečně je. Bez písmenka b dochází k automatické konverzi tzv. line-end kódování, já nechci zabíhat příliš do podrobností, ale v zásadě jde o to, že každá skupina operačních systémů (UNIX + UNIX-like, Windows a staré MAC OSy) ukládají znak odřádkování (Enteru) jinak. Na linuxu je to jen LF, na Windows CR+LF a na starších MAC OSech je to LF+CR, pokud ale v C pracujeme se soubory v textovém režimu (bez „b“), tak s těmito odlišnostmi můžeme pracovat naprosto transparentně (tj. Enter je pokaždé „\n“ nezávisle na systému). Pokud bychom ale například pracovali s nějakým binárním (např. spustitelný soubor, hudba, video), mohlo by takřka náhodné změnění některých bytů na jiné způsobit poměrně velké potíže, proto vždy pracujeme s binárními soubory jinak. U binárních souborů je také špatně, pokud je byte po bytu načítáme do charu, protože ačkoli char je datový typ o velikosti 1B, stejně nemohou být všechny hodnoty korektně interpretovány, proto k načítání bytů z bin. soubori použijeme integer. +

+ +
+ +

Funkce na čtení ze souboru ("r")

+
+
    +
  • fgetc(deskriptor);
    +
      +
    • Vrati jeden byte (znak) ze souboru
      +
    • +
    +
  • +
  • fgets(retezec, delka, deskriptor);
    +
      +
    • Precte delka znaku do retezec
      +
    • +
    +
  • +
  • fscanf(deskriptor, “%s“, retezec);
    +
      +
    • Precete radek do retezec
      +
    • +
    +
  • +
+ +
+ +

Funkce na zápis do souboru ("w", "a")

+
+
    +
  • fputc(byte, deskriptor);
    +
      +
    • Zapise byte do souboru
      +
    • +
    +
  • +
  • fputs(retezec, deskriptor);
    +
      +
    • Zapise retezec do souboru
      +
    • +
    +
  • +
  • fprintf(deskriptor, format_retezec, dalsi argumenty);
    +
      +
    • Jako printf(), ale zapisuje do souboru
      +
    • +
    +
  • +
+ +
+ +

Předotevřené soubory

+
+ +

+Je dobré vědět, že v C jsou otevřené následující soubory, se kterými pracují funkce jako printf() a pod, když tisknou na obrazovku, nebo načítají z klávesnice, vy toho můžete využít tak, že je zpracujete pomocí funkcí na práci s normálními soubory, nebo je třeba zavřete pro potlačení výstupu. Pak je můžete dokonce opět otevřít a způsobit tak, že všechen výstup vašeho programu, který se normálně provádí na obrazovku bude místo toho uložen do vámi zvoleného souboru. Na druhou stranu nesmíme zapomenout na to, že už nelze zaručit, že znovu půjde otevřít tyto soubory do původního stavu, aby například opět vypisovali na obrazovku. Např. v Linuxu to možné je, v ostatních UNIX-like systémech asi také, ale s jinými takové zkušenost nemám. Na Windows to pravděpodobně možné nebude. + +

+
    +
  • stdout - „w“ - stanartní výstup
    +
  • +
  • stderr - „w“ - standartní chybový výstup
    +
  • +
  • stdin - „r“ - standartní vstup
    +
  • +
+ +
+ +

Samostatná cvičení

+
+
    +
  • NapiÅ¡te program, který vypíše celý soubor (určený 1. argumentem) otevřený v textovém módu.
    +
  • +
  • NapiÅ¡te program, který binárně zapíše obsah souboru určeného 1. argumentem do souboru určeného druhým argumentem. Půjde o alternativu programu na kopírování souborů (cp, copy, atd…), tento program vyzkouÅ¡ejte zkopírováním jiného spustitelného souboru, zvukového záznamu a videa, nebo jiného binárního souboru. Tyto kopie musí mít stejnou velikost a být funkční stejně jako jejich originály.
    +
  • +
  • NapiÅ¡te program, který znak po znaku přečte celý binární soubor a vypíše číselnou hodnotu každého znaku na nový řádek hexadecimálně, desítkově a binárně.
    +
  • +
  • NapiÅ¡te program, který na střídačku binárně čte byte po bytu ze dvou souborů a zapisuje do jednoho souboru. Pokud tedy 1. soubor bude obsahovat byty „AAAAA“ a druhý „BBBBB“, pak bude výsledný soubor obsahovat „ABABABABAB“, potom napiÅ¡te program, který zvládne za byty správně rozdělit tak, aby byly soubory opět použitelné (stejně jako u kopírování).====== Napojení C na další systémy ======
    +
  • +
+ +
+ +

Napojení na webové aplikace (CGI a PHP)

+
+ +

+V někerých případech se může stát, že budete potřebovat, aby váš program napsaný v C spolupracoval s vaší webovou aplikací, dnes si představíme dva nejjednodušší způsoby, jak toho docílit. První se bude zabívat CGI rozhraním (Common Gateway Interface) a druhý nám ukáže, jak napojit program na webovou aplikaci pomocí wrapperu napsaného v PHP. +

+ +
+ +

Common Gateway Interface (CGI)

+
+ +

+CGI je rozhraní, které nám umožní, aby webserver předával požadavek přímo našemu programu. Jaké jsou výhody a nevýhody C proti jiným webovým server-side jazykům (jako PHP, JSP, nebo ASP) je celkem průhledné. C je sice rychlejší, ale musí být zkompilováno pro danou platformu. Nemůžete tedy jednoduše vzít vaší aplikaci, kterou jste do teď provozovali na Linuxu (na procesoru řady x86) a všechny soubory jednoduše uploadnout na HPBSD server (s procesorem PA-RISC), ale budete muset všechny binární soubory ze zdrojových kódů překompilovat pro tuto platformu. +

+ +

+Když napíšete a zkompilujete CGI aplikaci, potřebujete ještě webserver, který CGI podporuje a musíte ho nastavit podle instrukcí dle konkrétního serveru, potom nahrajete spustitelné soubory do příslušného adresáře. Nastavení serveru tady rozebírat nebudu. +

+ +

+Jaký je tedy rozdíl mezi normálním programem a CGI programem? Jde o obyčejný textový program pro příkazový řádek, s tím rozdílem, že výstup (například text vypsaný pomocí printf()) se nevypisuje na obrazovku, ale do obsahu vrácené webové stránky, nejdříve, ale musíme poslat alespoň minimální HTTP hlavičku (pro více informací si přečtěte něco o HTTP protokolu), pokud tedy chceme například vygenerovat HTML dokument s nadpisem první úrovně, kód bude vypadat takto: +

+
+
cgi-hello.c
+
#include <stdio.h>
+ 
+int main() {
+	printf("Content-type: text/html\n"); //HTTP hlavicka udavajici typ obsahu
+	printf("\n"); //Po posledni hlavicce se posila prazdny radek.
+	//Nyni uz muzeme zahajit vystup:
+	printf("<h1>Hello world!</h1>\n");
+}
+
+ +

+Ještě bychom měli vědět, jak se dostaneme k datům předávaným metodami GET nebo POST. Oba dva typy parametrů jsou předávány jako řetězec ve formátu, v jakém je server dostane od klienta, většinou takový řetězec vypadá například takto (běžný URL query string): + +

+
prvnipromena=224&druha=Zapis%20data&treti&ctvrta=posledni
+ +

+ +Pokud jsou data předávána v GETu, nahdete je v proměnné prostředí pojmenované „QUERY_STRING“, pokud tedy například chceme získat a vytisknout celý GET požadavek, uděláme to pomocí funkce getenv() zhruba takto: +

+
+
cgi-get.c
+
#include <stdio.h>
+#include <stdlib.h>
+ 
+int main () {
+	char *get;
+	get = getenv("QUERY_STRING"); //Získáme pointer na QUERY_STRING
+ 
+	printf("Content-type: text/html\n\n");
+	if (p != NULL) printf("<h1>CGI - GET</h1>\n<textarea>%s</textarea>", get); //Vytiskneme QUERY_STRING
+	return 0;
+}
+
+ +

+Pokud ale chceme získat data z POSTu, budou v přesně stejném tvaru, jako v případě GETu, s tím rozdílem, že budou čekat na standartním vstupu, jinými slovy to znamená, že je můžeme načítat například pomocí funkcí scanf(), nebo getc(), to tady dále rozebírat nebudu, protože to je poměrně základní znalost. +

+ +
+ +

Wrapper v PHP

+
+ +

+PHP (Portable Hypertext Preprocesor) je interpretovaný programovací jazyk (podobně, jako PERL, nebo Python), který se dá provozovat například i na webovém serveru. Pro nás je důležité, že obsahuje některé funkce, pomocí kterých se lze odvolávat i na binární spustitelné soubory, požadavky na spustitelný soubor jsou víceméně stejné, jako u CGI, ale s tím rozdílem, že tento soubor nemusí být primárně určen jako webová aplikace, nebo se nacházet ve speciálním adresáři, úplně postačí, když bude mít dobře nastavená práva pro spouštění. +

+ +

+Jak toto propojení v PHP vytvoříme? Poslouží nám k tomu funkce jako system(), nebo popen() (které se mimochodem chovají stejně, jako jejich jmenovci v Ansi C), shell_exec() a nebo proc_open(). Z následující tabulky pochopíte, co jednotlivé funkce umožňují: + +

+
    +
  • system() - spustí program se zadanými parametry a vypíše výstup (stdout)
    +
  • +
  • shell_exec() - spustí program se zadanými parametry a vrátí výstup (stdout)
    +
  • +
  • popen() - otevře program podobně jako například soubor, buď pro čtení stdoutu nebo zápis na stdin programu
    +
  • +
  • proc_open() - dovoluje otevřít program tak, aby bylo možné zároveň pracovat se vÅ¡emi jeho výstupy i vstupem (stdout, stderr, stdin)
    +
  • +
+ +

+ +Jednoduchý PHP skript, který nám spustí náš smyšlený program napsaný v C, který může obsluhovat smyšlený teploměr by vypadal například takto: +

+
+
c.php
+
<h1>Teploty</h1>
+<?php
+	echo("<h2>Vevnitř</h2>\n");
+	echo(htmlspecialchars(shell_exec('./thermo -in'))."\n");
+	echo("<h2>Venku</h2>\n");
+	echo(htmlspecialchars(shell_exec('./thermo -out'))."\n");
+?>
+
+ +

+Všiměte si, že jsem použil ještě funkci PHP nazvanou htmlspecialchars(), která zajistí, že například špičaté závorky budou převedeny na příslušné HTML entity, místo toho, aby způsobily nekorektní zobrazení dokumentu. Sám podobný skript používám, abych si mohl přes webové rozhraní vypisovat aktuální informace o serveru (teplota procesoru, disků, volné místo na disku, přihlášení uživatelé, spuštěné procesy, atd…). To je tedy vše, co si o spolupráci programů napsaných v C s vebovými aplikacemi můžeme říct, aniž bychom přesáhli rámec naší hodiny. +

+ +
+ +

Jiné systémy

+
+ +

+Podobně, jako z PHP voláme program napsaný v C, můžeme z C také volat jiný program, nebo můžeme například pomocí socketů vytvořit spojení například s naslouchajícím serverem. Propojení dvou programů může také probíhat pomocí roury, nebo pojmenované FIFO (first in, first out) roury. +

+ +
+ +

Freestyle Coding Contest

+
+ +

+Pozn.: Tato lekce může být použita suplujícím v případě absence vyučujícího, je ale nutné slevit z nároků a říct studentům, aby aplikace upravili tak, aby nemuseli používat znalosti, které ještě nemají, nebo si vymysleli jednodušší zadání, jehož správnost (a především správnost vypracování programu) bude ověřena při první možné příležitosti vyučujícím lektorem. +

+ +

+V poslední lekci jsem si pro vás připravil zadání různých malých (a do jisté míry užitečných) prográmků, které byste se svými znalostmi měli být schopni vytvořit. Protože ale nemusí být úplně průhledné, jak takový program napsat (ačkoli teoretické znalosti byste na to mít měli), v případě nejasností požádejte profesora o pomocnou berličku v místech, která vám nejsou úplně jasná (samozřejmě až po chvilce namáhání hlavy ;). Pokud nemáte žádný vlastní nápad, můžete si vybrat jeden (nebo několik) z následujících projektů: +

+ +
+ +

Kalkulátor

+
+ +

+Pokuste se napsat co nejkomplexnější a nejpřívětivější program na provádění různých druhů výpočtů. Program můžete například doplit i o pokročilé funkce, jako vykreslení grafu (pomocí písmenek) průběhu různých funkcí při různých vstupních hodnotách (stačí například sin()), nebo libovolnou jinou funkci dle zájmu (výpočet obvodu kruhu, nebo cokoli, co ve své kalkulačce chcete mít). +

+ +
+ +

Interpreter jednoduchého jazyka

+
+ +

+Vymyslete si jednoduchý interpretovaný programovací jazyk a napište pro něj interpreter. Stačí například 3-5 příkazů, pro zjednodušení může mít každý příkaz délku 1 znak, nebo řádek. V jednodušší obdobě nemusí jazyk být schopný dělat nic smysluplného, například pokud první písmenko řádku určuje akci a zbytek jsou data, která se mají zpracovat a „P“ znamená vytisknout a „M“ vynásobit dvěmi a vytisknout, může náledující program: + +

+
PTento text bude vypsan
+CToto je komentar
+M23 //toto cislo bude vynasobeno dvěmi a vypsáno
+ +

+ +Po zpracování vaším interpreterem například vytvořit následující výpis: + +

+
Tento text bude vypsan
+46
+ +

+ +Co bude jazyk dělat je čistě na vás, může také například do dvojrozměrného pole kreslit čáru (L,P,N,D,T = vlevo, vpravo, nahoru, dolu, tisk) a když narazí na příkaz pro tisk, tak toto „plátno“ vytiskne (vypíše). +

+ +

+Tedy program DDDPPPNNLLDT vypíše například toto: + +

+
#
+####
+## #
+####
+ +

+ +Můžete si samozřejmě doplnit další příkazy (změna písmenka/barvy), nebo napsat něco úplně jiného. +

+ +
+ +

Shell

+
+ +

+Napište jednoduchý příkazový řádek (podobný například BASHi, nebo CMD) implementujte do něj funkci pro spouštění zadaných příkazů. Na internetu zjistěte, jakým způsobem lze zjistit aktuální adresář a vypisujte ho jako součást výzvy (na začátek řádky). Můžete implementovat i další virtuální příkazy na mazání, přesouvání a kopírování souborů, apod… Záleží opět jen na vaší fantazii. +

+ +
+ +

Mnohojazyčná aplikace

+
+ +

+Napište program, který obsahuje několik jednoduchých textových menu a libovolnou funkčnost (můžete se inspirovat jinými příklady). Veškeré texty v programu se budou načítat ze souboru specifikovaného v jiném (konfiguračním souboru). Vytvořte najméně dva datové soubory s lokalizacemi programu do vašeho mateřského jazyka a libovolného jiného. Soubor s jazykem nastavený v konfiguračním souboru by měl jít dočasně změnit pomocí argumentu programu. +

+ +
+ +

Engine textové hry

+
+ +

+Napište engine a alespoň jeden datový soubor pro textovou hru (elektronický gamebook), uživatel bude o pohybu mezi místnostmi této adventury (načtené ze souboru, jehož jméno zadá v parametru) rozhodovat zadáním čísla místnosti, číslo místnosti může odpovídat jedné konkrétní řádce v textovém souboru. Do enginu můžete dodělat možnosti soubojů (pomocí náhodných čísel), nebo kontrolu, jestli hráč dostal skutečně na výběr číslo místnosti, které zadal. +

+ +
+ +

Primitivní textový editor

+
+ +

+Program pro CLI (příkazový řádek) přijme jako argumenty režim (R - přečíst (vypsat na obrazovku), W - přečíst a zapsat, nebo A - přečíst a přídat) a jméno souboru, bude ho vypisovat po 15 řádkách (pokaždé počká na enter), až se dostane na konec souboru, tak pokud je pomocí prvního argumentu aktivován režim, který umožňuje zápis do souboru, vypíše řetězec „\n—– NEJAKY TEXT —–\n“ (NEJAKY TEXT budou informace o souboru) a vše, co od té chvíle uživatel napíše na klávesnici zaznamená do souboru (přepíše celý soubor). Uživatel svůj vstup ukončí pomocí programátorem zvolené klávesy stlačené současně s Control (CTRL), nesmí ale jít o kombinace CTRL+C nebo CTRL+D. Pokud uživatel zadá volbu R, program místo toho rovnou skončí. +

+ +

+Pokud program argument s názvem souboru neobdrží, automaticky vypíše seznam souborů (pomocí volání system() a příslušného programu - tj. ls, dir,…) a na jméno souboru se dotáže. Pokud soubor neexistuje, nabídne jeho vytvoření. Pokud je zadán první argument, tento soubor zpracuje v daném režimu, v jiném případě se uživatele taktéž zeptá. +

+ +
+ +

Ascii Grafika

+
+ +

+Tento program by měl dokázat vykreslovat (alespoň) 3 libovolné různé obrazce, prvním parametrem je určen tvar, druhým znak (barva) a dalšími potřebné parametry (rozměry). Způsob, jakým bude tvar vykreslován a jakým bude prováděn výpočet nechám na vás, důležité je ale, aby se tvar zobrazoval korektně nezávisle na zadaném rozměru. Výstup (u těch opravdu nejjednodušších obrazců) může vypadat například takto: +

+
Čtverec (c):
+./grafika c # 4 4
+####
+#  #
+#  #
+####
+
+Kruh (k):
+./grafika k o 3
+ o  o
+o    o
+ o  o
+
+Trojúhelník (t):
+./grafika t A 5
+  A
+ A A
+AAAAA
+
+ +
+ +

Další nápady

+
+ +

+Můžete samozřejmě vymyslet a zrealizovat svůj ještě zajímavější nápad, nebo libovolná zadání libovolně modafakovat. +

+ +

+Nejlepší programátor (čistota kódu*nápaditost) bude odměněn diplomem „Fr335ty13 C0din9 C0nt35+ - Zlatý byte“ (nebo taky ne ;)… +

+ +
+ +

Vysvětlivky

+
+
Akronym - Zkratka vzniklá spojením počátečních písmen slov ve slovním spojení, nebo větě.
+BFU - Běžný Franta Uživatel - slangové ozn. pro uživatele bez hlubších znalostí, pravděpodobně to jednou bude váš typický uživatel. Aplikace je nutno přizpůsobovat těmto uživatelům.
+CLI - Command Line Interface - Akronym pro příkazový řádek.
+IDE - Integrated developing environment - Integrované vývojové prostředí - Zkládá se především z editoru a kompilátoru (případně může obsahovat debugger nebo GUIBuilder).
+UI - User Interface - Uživatelské rozhraní - rozhraní, pomocí kterého uživatel komunikuje s aplikací.
+GUI - Graphical User Interface - Specifický druh UI využívající grafiku (většinou tzv. okenní aplikace).
+C - Programovací jazyk.
+Ansi C - Americká norma popisující konvence, které musí dodržet kompilátor. Používá se zároveň i jako označení současné verze jazyka C.
+C++ - Programovací jazyk vycházející z jazyka C. Byl rozšířen především o podporu objektů.
+Decimální - Desítkový
+HexaDecimální - Šestnáctkový
+Binární - Dvojkový
+Oktální - Osmičkový
+Preprocesor kompilátoru - Program, který připravuje zdrojový kód pro kompilátor (maže nepotřebné mezery, komentáře, atd...).
+Kompilátor - Program, který převádí zdrojový kód na binární objektový kód.
+Assembler - Jazyk symbolických adres. Programovací jazyk využívající přímo instrukce procesoru (jen zapsané čitelnější formou).
+Linker - Program vytvářející spustitelný soubor z objektového kódu vytvořeného při kompilaci.
+
+ +
+ +

Prameny

+
+ +

+Tady naleznete seznam zdrojů, které sem (kromě svých vlastních znalostí) použil k napsání těchto skript a které vám důrazně doporučuji si pročíst, nebo je prohledávat při nejasnostech ohledně Ansi C, nebo C jako takového. +

+ +

+Povinná četba každého Céčkaře +

+
    +
  • Pavel Herout - Učebnice Jazyka C (Kopp) - I. a II. díl
    +
  • +
  • Jon Erickson - Hacking: umění exploitace (Zoner press)
    +
  • +
+ +

+ +Knihovní funkce Ansi C +

+ + +

+ +Všeobecné informace +

+
    +
  • cs.wikipedia.org
    +
  • +
  • en.wikipedia.org
    +
  • +
+ +

+ +Všechno ostatní + * google.com +

+
    +
  • Existují pokročilé techniky googlování, které vám pomohou snázeji najít to, co skutečně hledáte
    +
  • +
+ +
+
+ + + \ No newline at end of file diff --git a/c/skripta/compilation/jazyk_c compilation_files/css(1).php b/c/skripta/compilation/jazyk_c compilation_files/css(1).php new file mode 100755 index 0000000..00e5340 --- /dev/null +++ b/c/skripta/compilation/jazyk_c compilation_files/css(1).php @@ -0,0 +1 @@ +a.interwiki{background:transparent url(/doku/lib/images/interwiki.png) 0px 1px no-repeat;padding-left:16px;}a.iw_wp{background-image:url(/doku/lib/images/interwiki/wp.gif)}a.iw_wpfr{background-image:url(/doku/lib/images/interwiki/wpfr.gif)}a.iw_wpde{background-image:url(/doku/lib/images/interwiki/wpde.gif)}a.iw_wpes{background-image:url(/doku/lib/images/interwiki/wpes.gif)}a.iw_wppl{background-image:url(/doku/lib/images/interwiki/wppl.gif)}a.iw_wpjp{background-image:url(/doku/lib/images/interwiki/wpjp.gif)}a.iw_wpmeta{background-image:url(/doku/lib/images/interwiki/wpmeta.gif)}a.iw_doku{background-image:url(/doku/lib/images/interwiki/doku.gif)}a.iw_dokubug{background-image:url(/doku/lib/images/interwiki/dokubug.gif)}a.iw_amazon{background-image:url(/doku/lib/images/interwiki/amazon.gif)}a.iw_amazon_de{background-image:url(/doku/lib/images/interwiki/amazon.de.gif)}a.iw_amazon_uk{background-image:url(/doku/lib/images/interwiki/amazon.uk.gif)}a.iw_phpfn{background-image:url(/doku/lib/images/interwiki/phpfn.gif)}a.iw_coral{background-image:url(/doku/lib/images/interwiki/coral.gif)}a.iw_sb{background-image:url(/doku/lib/images/interwiki/sb.gif)}a.iw_google{background-image:url(/doku/lib/images/interwiki/google.gif)}a.iw_meatball{background-image:url(/doku/lib/images/interwiki/meatball.gif)}a.iw_wiki{background-image:url(/doku/lib/images/interwiki/wiki.gif)}a.mediafile{background:transparent url(/doku/lib/images/fileicons/file.png) 0px 1px no-repeat;padding-left:18px;padding-bottom:1px;}a.mf_sxd{background-image:url(/doku/lib/images/fileicons/sxd.png)}a.mf_js{background-image:url(/doku/lib/images/fileicons/js.png)}a.mf_pl{background-image:url(/doku/lib/images/fileicons/pl.png)}a.mf_jpg{background-image:url(/doku/lib/images/fileicons/jpg.png)}a.mf_jpeg{background-image:url(/doku/lib/images/fileicons/jpeg.png)}a.mf_sxi{background-image:url(/doku/lib/images/fileicons/sxi.png)}a.mf_png{background-image:url(/doku/lib/images/fileicons/png.png)}a.mf_pdf{background-image:url(/doku/lib/images/fileicons/pdf.png)}a.mf_rtf{background-image:url(/doku/lib/images/fileicons/rtf.png)}a.mf_cs{background-image:url(/doku/lib/images/fileicons/cs.png)}a.mf_ods{background-image:url(/doku/lib/images/fileicons/ods.png)}a.mf_cpp{background-image:url(/doku/lib/images/fileicons/cpp.png)}a.mf_php{background-image:url(/doku/lib/images/fileicons/php.png)}a.mf_odg{background-image:url(/doku/lib/images/fileicons/odg.png)}a.mf_htm{background-image:url(/doku/lib/images/fileicons/htm.png)}a.mf_rb{background-image:url(/doku/lib/images/fileicons/rb.png)}a.mf_odi{background-image:url(/doku/lib/images/fileicons/odi.png)}a.mf_ps{background-image:url(/doku/lib/images/fileicons/ps.png)}a.mf_c{background-image:url(/doku/lib/images/fileicons/c.png)}a.mf_odf{background-image:url(/doku/lib/images/fileicons/odf.png)}a.mf_java{background-image:url(/doku/lib/images/fileicons/java.png)}a.mf_html{background-image:url(/doku/lib/images/fileicons/html.png)}a.mf_bz2{background-image:url(/doku/lib/images/fileicons/bz2.png)}a.mf_xls{background-image:url(/doku/lib/images/fileicons/xls.png)}a.mf_py{background-image:url(/doku/lib/images/fileicons/py.png)}a.mf_odp{background-image:url(/doku/lib/images/fileicons/odp.png)}a.mf_doc{background-image:url(/doku/lib/images/fileicons/doc.png)}a.mf_txt{background-image:url(/doku/lib/images/fileicons/txt.png)}a.mf_rar{background-image:url(/doku/lib/images/fileicons/rar.png)}a.mf_odc{background-image:url(/doku/lib/images/fileicons/odc.png)}a.mf_odt{background-image:url(/doku/lib/images/fileicons/odt.png)}a.mf_zip{background-image:url(/doku/lib/images/fileicons/zip.png)}a.mf_sxw{background-image:url(/doku/lib/images/fileicons/sxw.png)}a.mf_gz{background-image:url(/doku/lib/images/fileicons/gz.png)}a.mf_xml{background-image:url(/doku/lib/images/fileicons/xml.png)}a.mf_lua{background-image:url(/doku/lib/images/fileicons/lua.png)}a.mf_tar{background-image:url(/doku/lib/images/fileicons/tar.png)}a.mf_tgz{background-image:url(/doku/lib/images/fileicons/tgz.png)}a.mf_swf{background-image:url(/doku/lib/images/fileicons/swf.png)}a.mf_css{background-image:url(/doku/lib/images/fileicons/css.png)}a.mf_ppt{background-image:url(/doku/lib/images/fileicons/ppt.png)}a.mf_conf{background-image:url(/doku/lib/images/fileicons/conf.png)}a.mf_rpm{background-image:url(/doku/lib/images/fileicons/rpm.png)}a.mf_deb{background-image:url(/doku/lib/images/fileicons/deb.png)}a.mf_sxc{background-image:url(/doku/lib/images/fileicons/sxc.png)}a.mf_gif{background-image:url(/doku/lib/images/fileicons/gif.png)}div.clearer{clear:both;line-height:0;height:0;overflow:hidden;}div.no{display:inline;margin:0;padding:0;}.hidden{display:none;}div.error{background:#fcc url(/doku/lib/styles/../images/error.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #faa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;}div.info{background:#ccf url(/doku/lib/styles/../images/info.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #aaf;font-size:90%;margin:0;padding-left:3em;overflow:hidden;}div.success{background:#cfc url(/doku/lib/styles/../images/success.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #afa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;}div.notify{background:#ffc url(/doku/lib/styles/../images/notify.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #ffa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;}.medialeft{float:left;}.mediaright{float:right;}.mediacenter{display:block;margin-left:auto;margin-right:auto;}.leftalign{text-align:left;}.centeralign{text-align:center;}.rightalign{text-align:right;}em.u{font-style:normal;text-decoration:underline;}em em.u{font-style:italic;}.code .br0{color:#6c6;}.code .co0{color:#808080;font-style:italic;}.code .co1{color:#808080;font-style:italic;}.code .co2{color:#808080;font-style:italic;}.code .co3{color:#808080;}.code .coMULTI{color:#808080;font-style:italic;}.code .es0{color:#009;font-weight:bold;}.code .kw1{color:#b1b100;}.code .kw2{color:#000;font-weight:bold;}.code .kw3{color:#006;}.code .kw4{color:#933;}.code .kw5{color:#00f;}.code .me1{color:#060;}.code .me2{color:#060;}.code .nu0{color:#c6c;}.code .re0{color:#00f;}.code .re1{color:#00f;}.code .re2{color:#00f;}.code .re3{color:#f33;font-weight:bold;}.code .re4{color:#099;}.code .st0{color:#f00;}.code .sy0{color:#6c6;}#user__manager tr.disabled{color:#6f6f6f;background:#e4e4e4;}#user__manager tr.user_info{vertical-align:top;}#user__manager div.edit_user{width:46%;float:left;}#user__manager table{margin-bottom:1em;}#user__manager input.button[disabled]{color:#ccc!important;border-color:#ccc!important;}#config__manager div.success,#config__manager div.error,#config__manager div.info{background-position:0.5em;padding:0.5em;text-align:center;}#config__manager fieldset{margin:1em;width:auto;margin-bottom:2em;background-color:#dee7ec;color:#000;padding:0 1em;}#config__manager legend{font-size:1.25em;}#config__manager form{}#config__manager table{margin:1em 0;width:100%;}#config__manager fieldset td{text-align:left;}#config__manager fieldset td.value{width:31em;}#config__manager td.label{padding:0.8em 0 0.6em 1em;vertical-align:top;}#config__manager td.label label{clear:left;display:block;}#config__manager td.label img{padding:0 10px;vertical-align:middle;float:right;}#config__manager td.label span.outkey{font-size:70%;margin-top:-1.7em;margin-left:-1em;display:block;background-color:#fff;color:#000;float:left;padding:0 0.1em;position:relative;z-index:1;}#config__manager td input.edit{width:30em;}#config__manager td .input{width:30.8em;}#config__manager td select.edit{}#config__manager td textarea.edit{width:27.5em;height:4em;}#config__manager tr .input,#config__manager tr input,#config__manager tr textarea,#config__manager tr select{background-color:#fff;color:#000;}#config__manager tr.default .input,#config__manager tr.default input,#config__manager tr.default textarea,#config__manager tr.default select,#config__manager .selectiondefault{background-color:#cdf;color:#000;}#config__manager tr.protected .input,#config__manager tr.protected input,#config__manager tr.protected textarea,#config__manager tr.protected select,#config__manager tr.protected .selection{background-color:#fcc!important;color:#000 !important;}#config__manager td.error{background-color:red;color:#000;}#config__manager .selection{width:14.8em;float:left;margin:0 0.3em 2px 0;}#config__manager .selection label{float:right;width:14em;font-size:90%;}* html #config__manager .selection label{padding-top:2px;}#config__manager .selection input.checkbox{padding-left:0.7em;}#config__manager .other{clear:both;padding-top:0.5em;}#config__manager .other label{padding-left:2px;font-size:90%;}div.dokuwiki div.include div.secedit{float:right;margin-left:1em;margin-top:-18px;}div.dokuwiki div.inclmeta{border-top:1px dotted #8cacbb;padding-top:0.2em;color:#000;font-size:80%;line-height:1.25;margin-top:0.5em;margin-bottom:2em;}div.dokuwiki div.inclmeta a.permalink{background:transparent url(/doku/lib/plugins/include/images/link.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;}div.dokuwiki div.inclmeta abbr.published{background:transparent url(/doku/lib/plugins/include/images/date.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;border-bottom:0;}div.dokuwiki div.inclmeta span.author{background:transparent url(/doku/lib/plugins/include/images/user.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;}div.dokuwiki div.inclmeta span.comment{background:transparent url(/doku/lib/plugins/include/images/comment.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;}div.dokuwiki div.inclmeta div.tags{border-top:0;font-size:100%;float:right;clear:none;}#plugin__manager{}#plugin__manager h2{margin-left:0;}#plugin__manager form{display:block;margin:0;padding:0;}#plugin__manager legend{display:none;}#plugin__manager fieldset{width:auto;}#plugin__manager .button{margin:0;}#plugin__manager p,#plugin__manager label{text-align:left;}#plugin__manager .hidden{display:none;}#plugin__manager .new{background:#dee7ec;}#plugin__manager input[disabled]{color:#ccc;border-color:#ccc;}#plugin__manager .pm_menu,#plugin__manager .pm_info{margin-left:0;text-align:left;}#plugin__manager .pm_menu{float:left;width:48%;}#plugin__manager .pm_info{float:right;width:50%;}#plugin__manager .common{}#plugin__manager .common form{}#plugin__manager .common fieldset{margin:0;padding:0 0 1.0em 0;text-align:left;border:none;}#plugin__manager .common label{padding:0 0 0.5em 0;}#plugin__manager .common input{}#plugin__manager .common input.edit{width:24em;margin:0.5em;}#plugin__manager .common .button{}#plugin__manager form.plugins{}#plugin__manager .plugins fieldset{color:#000;background:#fff;text-align:right;border-top:none;border-right:none;border-left:none;}#plugin__manager .plugins fieldset.protected{background:#fdd;color:#000;}#plugin__manager .plugins fieldset.disabled{background:#e0e0e0;color:#a8a8a8;}#plugin__manager .plugins .legend{color:#000;background:inherit;display:block;margin:0;padding:0;font-size:1em;line-height:1.4em;font-weight:normal;text-align:left;float:left;padding:0;clear:none;}#plugin__manager .plugins .button{font-size:95%;}#plugin__manager .plugins fieldset.buttons{border:none;}#plugin__manager .plugins fieldset.buttons .button{float:left;}#plugin__manager .pm_info h3{margin-left:0;}#plugin__manager .pm_info dl{margin:1em 0;padding:0;}#plugin__manager .pm_info dt{width:6em;float:left;clear:left;margin:0;padding:0;}#plugin__manager .pm_info dd{margin:0 0 0 7em;padding:0;background:none;}#plugin__manager .plugins .enable{float:left;width:auto;margin-right:0.5em;}div#acl_manager div#acl__tree{font-size:90%;width:25%;height:300px;float:left;overflow:auto;border:1px solid #8cacbb;text-align:left;}div#acl_manager div#acl__tree a.cur{background-color:#ff9;font-weight:bold;}div#acl_manager div#acl__tree ul{list-style-type:none;margin:0;padding:0;}div#acl_manager div#acl__tree li{padding-left:1em;}div#acl_manager div#acl__tree ul img{margin-right:0.25em;cursor:pointer;}div#acl_manager div#acl__detail{width:73%;height:300px;float:right;overflow:auto;}div#acl_manager div#acl__detail fieldset{width:90%;}div#acl_manager div#acl__detail div#acl__user{border:1px solid #8cacbb;padding:0.5em;margin-bottom:0.6em;}div#acl_manager table.inline{width:100%;margin:0;}div#acl_manager .aclgroup{background:transparent url(/doku/lib/plugins/acl/pix/group.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;}div#acl_manager .acluser{background:transparent url(/doku/lib/plugins/acl/pix/user.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;}div#acl_manager .aclpage{background:transparent url(/doku/lib/plugins/acl/pix/page.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;}div#acl_manager .aclns{background:transparent url(/doku/lib/plugins/acl/pix/ns.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;}div#acl_manager label.disabled{color:#000!important;}#acl_manager label{text-align:left;font-weight:normal;display:inline;}#acl_manager table{margin-left:10%;width:80%;}#acl_manager table tr{background-color:inherit;}#acl_manager table tr:hover{background-color:#dee7ec;}#column-content{width:100%;float:right;margin:0 0 .6em -12.2em;padding:0;}#content{margin:2.8em 0 0 12.2em;padding:0 1em 1.5em 1em;background:white;color:black;border:1px solid #aaa;border-right:none;line-height:1.5em;position:relative;z-index:2;}#column-one{padding-top:160px;}body{font:x-small sans-serif;background:#f9f9f9 url(/doku/lib/tpl/monobook/static/3rd/monobook/headbg.jpg) 0 0 no-repeat;color:black;margin:0;padding:0;}#globalWrapper{font-size:127%;width:100%;margin:0;padding:0;}.visualClear{clear:both;}table{background:white;font-size:100%;color:black;}a{text-decoration:none;color:#002bb8;background:none no-repeat;}a:visited{color:#5a3696;}a:active{color:#faa700;}a:hover{text-decoration:underline;}a.stub{color:#723;}a.new,#p-personal a.new{color:#ba0000;}a.new:visited,#p-personal a.new:visited{color:#a55858;}img{border:none;vertical-align:middle;}p{margin:.4em 0 .5em 0;line-height:1.5em;}p img{margin:0;}hr{height:1px;color:#aaa;background-color:#aaa;border:0;margin:.2em 0 .2em 0;}h1,h2,h3,h4,h5,h6{color:black;background:none;font-weight:normal;margin:0;padding-top:.5em;padding-bottom:.17em;border-bottom:1px solid #aaa;}h1{font-size:188%;}h2{font-size:150%;}h3,h4,h5,h6{border-bottom:none;font-weight:bold;}h3{font-size:132%;}h4{font-size:116%;}h5{font-size:100%;}h6{font-size:80%;}ul{line-height:1.5em;list-style-type:square;margin:.3em 0 0 1.5em;padding:0;list-style-image:url(/doku/lib/tpl/monobook/static/3rd/monobook/bullet.gif);}ol{line-height:1.5em;margin:.3em 0 0 3.2em;padding:0;list-style-image:none;}li{margin-bottom:.1em;}dt{font-weight:bold;margin-bottom:.1em;}dl{margin-top:.2em;margin-bottom:.5em;}dd{line-height:1.5em;margin-left:2em;margin-bottom:.1em;}fieldset{border:1px solid #2f6fab;margin:1em 0 1em 0;padding:0 1em 1em;line-height:1.5em;}legend{background:white;padding:.5em;font-size:95%;}form{border:none;margin:0;}textarea{width:100%;padding:.1em;}input.historysubmit{padding:0 .3em .3em .3em !important;font-size:94%;cursor:pointer;height:1.7em !important;margin-left:1.6em;}select{vertical-align:top;}abbr,acronym,.explain{border-bottom:1px dotted black;color:black;background:none;cursor:help;}q{font-family:Times,"Times New Roman",serif;font-style:italic;}code{background-color:#f9f9f9;}pre{padding:1em;border:1px dashed #2f6fab;color:black;background-color:#f9f9f9;line-height:1.1em;}#siteSub{display:none;}#jump-to-nav{display:none;}#contentSub,#contentSub2{font-size:84%;line-height:1.2em;margin:0 0 1.4em 1em;color:#7d7d7d;width:auto;}span.subpages{display:block;}#bodyContent h1,#bodyContent h2{margin-bottom:.6em;}#bodyContent h3,#bodyContent h4,#bodyContent h5{margin-bottom:.3em;}.firstHeading{margin-bottom:.1em;}.usermessage{background-color:#ffce7b;border:1px solid #ffa500;color:black;font-weight:bold;margin:2em 0 1em;padding:.5em 1em;vertical-align:middle;}#siteNotice{text-align:center;font-size:95%;padding:0 .9em;}#siteNotice p{margin:0;padding:0;}.error{color:red;font-size:larger;}.errorbox,.successbox{font-size:larger;border:2px solid;padding:.5em 1em;float:left;margin-bottom:2em;color:#000;}.errorbox{border-color:red;background-color:#fff2f2;}.successbox{border-color:green;background-color:#dfd;}.errorbox h2,.successbox h2{font-size:1em;font-weight:bold;display:inline;margin:0 .5em 0 0;border:none;}#catlinks{border:1px solid #aaa;background-color:#f9f9f9;padding:5px;margin-top:1em;clear:both;}.documentDescription{font-weight:bold;display:block;margin:1em 0;line-height:1.5em;}.documentByLine{text-align:right;font-size:90%;clear:both;font-weight:normal;color:#76797c;}.center{width:100%;text-align:center;}*.center *{margin-left:auto;margin-right:auto;}.small,.small *{font-size:94%;}table.small{font-size:100%;}.mw-warning{margin-left:50px;margin-right:50px;text-align:center;}div.floatright,table.floatright{clear:right;float:right;position:relative;margin:0 0 .5em .5em;border:0;}div.floatright p{font-style:italic;}div.floatleft,table.floatleft{float:left;position:relative;margin:0 .5em .5em 0;border:0;}div.floatleft p{font-style:italic;}div.thumb{margin-bottom:.5em;border-style:solid;border-color:white;width:auto;}div.thumb div{border:1px solid #ccc;padding:3px !important;background-color:#f9f9f9;font-size:94%;text-align:center;overflow:hidden;}div.thumb div a img{border:1px solid #ccc;}div.thumb div div.thumbcaption{border:none;text-align:left;line-height:1.4em;padding:.3em 0 .1em 0;}div.magnify{float:right;border:none !important;background:none !important;}div.magnify a,div.magnify img{display:block;border:none !important;background:none !important;}div.tright{clear:right;float:right;border-width:.5em 0 .8em 1.4em;}div.tleft{float:left;margin-right:.5em;border-width:.5em 1.4em .8em 0;}.hiddenStructure{display:none;speak:none;}img.tex{vertical-align:middle;}span.texhtml{font-family:serif;}table.rimage{float:right;position:relative;margin-left:1em;margin-bottom:1em;text-align:center;}.toccolours{border:1px solid #aaa;background-color:#f9f9f9;padding:5px;font-size:95%;}div.townBox{position:relative;float:right;background:white;margin-left:1em;border:1px solid gray;padding:.3em;width:200px;overflow:hidden;clear:right;}div.townBox dl{padding:0;margin:0 0 .3em;font-size:96%;}div.townBox dl dt{background:none;margin:.4em 0 0;}div.townBox dl dd{margin:.1em 0 0 1.1em;background-color:#f3f3f3;}.special li{line-height:1.4em;margin:0;padding:0;}.autocomment{color:gray;}#pagehistory span.user{margin-left:1.4em;margin-right:.4em;}#pagehistory span.minor{font-weight:bold;}#pagehistory li{border:1px solid white;}#pagehistory li.selected{background-color:#f9f9f9;border:1px dashed #aaa;}table.diff,td.diff-otitle,td.diff-ntitle{background-color:white;}td.diff-addedline{background:#cfc;font-size:smaller;}td.diff-deletedline{background:#ffa;font-size:smaller;}td.diff-context{background:#eee;font-size:smaller;}span.diffchange{color:red;font-weight:bold;}#bodyContent a.extiw,#bodyContent a.extiw:active{color:#36b;background:none;padding:0;}#bodyContent a.external{color:#36b;}.portlet{border:none;margin:0 0 .5em;padding:0;float:none;width:11.6em;overflow:hidden;}.portlet h4{font-size:95%;font-weight:normal;white-space:nowrap;}.portlet h5{background:transparent;padding:0 1em 0 .5em;display:inline;height:1em;text-transform:lowercase;font-size:91%;font-weight:normal;white-space:nowrap;}.portlet h6{background:#ffae2e;border:1px solid #2f6fab;border-style:solid solid none solid;padding:0 1em 0 1em;text-transform:lowercase;display:block;font-size:1em;height:1.2em;font-weight:normal;white-space:nowrap;}.pBody{font-size:95%;background-color:white;color:black;border-collapse:collapse;border:1px solid #aaa;padding:0 .8em .3em .5em;}.portlet h1,.portlet h2,.portlet h3,.portlet h4{margin:0;padding:0;}.portlet ul{line-height:1.5em;list-style-type:square;list-style-image:url(/doku/lib/tpl/monobook/static/3rd/monobook/bullet.gif);font-size:95%;}.portlet li{padding:0;margin:0;}#p-logo{z-index:3;position:absolute;top:0;left:0;height:155px;width:12em;overflow:visible;}#p-logo h5{display:none;}#p-logo a,#p-logo a:hover{display:block;height:155px;width:12.2em;background-repeat:no-repeat;background-position:35% 50% !important;text-decoration:none;}#p-navigation{position:relative;z-index:3;}#p-navigation .pBody{padding-right:0;}#p-navigation a{display:block;}#p-navigation li.active a,#p-navigation li.active a:hover{text-decoration:none;display:inline;font-weight:bold;}#p-search{position:relative;z-index:3;}input.searchButton{margin-top:1px;font-size:95%;}#searchGoButton{padding-left:.5em;padding-right:.5em;font-weight:bold;}#searchInput{width:10.9em;margin:0;font-size:95%;}#p-search .pBody{padding:.5em .4em .4em .4em;text-align:center;}#p-personal{width:100%;white-space:nowrap;padding:0;margin:0;position:absolute;left:0;top:0;z-index:0;border:none;background:none;overflow:visible;line-height:1.2em;}#p-personal h5{display:none;}#p-personal .portlet,#p-personal .pBody{padding:0;margin:0;border:none;z-index:0;overflow:visible;background:none;}#p-personal ul{border:none;line-height:1.4em;color:#2f6fab;padding:0 2em 0 3em;margin:0;text-align:right;text-transform:lowercase;list-style:none;z-index:0;background:none;cursor:default;}#p-personal li{z-index:0;border:none;padding:0;display:inline;color:#2f6fab;margin-left:1em;line-height:1.2em;background:none;}#p-personal li.active{font-weight:bold;}#p-personal li a{text-decoration:none;color:#005896;padding-bottom:.2em;background:none;}#p-personal li a:hover{background-color:white;padding-bottom:.2em;text-decoration:none;}#p-personal li.active a:hover{background-color:transparent;}li#pt-userpage,li#pt-anonuserpage,li#pt-login{background:url(/doku/lib/tpl/monobook/static/3rd/monobook/user.gif) top left no-repeat;padding-left:20px;text-transform:none;}#p-cactions{position:absolute;top:1.3em;left:11.5em;margin:0;white-space:nowrap;width:76%;line-height:1.1em;overflow:visible;background:none;border-collapse:collapse;padding-left:1em;list-style:none;font-size:95%;font-weight:normal;}#p-cactions .hiddenStructure{display:none;}#p-cactions ul{list-style:none;}#p-cactions li{display:inline;border:1px solid #aaa;border-bottom:none;padding:0 0 .1em 0;margin:0 .3em 0 0;overflow:visible;background:white;}#p-cactions li.selected{border-color:#fabd23;padding:0 0 .2em 0;font-weight:bold;}#p-cactions li a{background-color:#fbfbfb;color:#002bb8;border:none;padding:0 .8em .3em;text-decoration:none;text-transform:lowercase;position:relative;z-index:0;margin:0;}#p-cactions li.selected a{z-index:3;background-color:#fff;padding:0 1em .2em!important;}#p-cactions .new a{color:#ba0000;}#p-cactions li a:hover{z-index:3;text-decoration:none;background-color:#fff;}#p-cactions h5{display:none;}#p-cactions li.istalk{margin-right:0;}#p-cactions li.istalk a{padding-right:.5em;}#p-cactions #ca-addsection a{padding-left:.4em;padding-right:.4em;}li#ca-talk{margin-right:1.6em;}li#ca-watch,li#ca-unwatch,li#ca-varlang-0,li#ca-print{margin-left:1.6em;}#p-tbx,#p-lang{position:relative;z-index:3;}#t-ispermalink,#t-iscite{color:#999;}#footer{background-color:white;border-top:1px solid #fabd23;border-bottom:1px solid #fabd23;margin:.6em 0 1em 0;padding:.4em 0 1.2em 0;text-align:center;font-size:90%;}#footer li{display:inline;margin:0 1.3em;}head:first-child+body #footer li{white-space:nowrap;}#f-poweredbyico,#f-copyrightico{margin:0 8px;position:relative;top:-2px;}#f-poweredbyico{float:right;height:1%;}#f-copyrightico{float:left;height:1%;}#preftoc{margin:0;padding:0;width:100%;clear:both;}#preftoc li{margin:1px -2px 1px 2px;float:left;padding:2px 0 3px 0;background-color:#f0f0f0;color:#000;border:1px solid #fff;border-right-color:#716f64;border-bottom:0;position:relative;white-space:nowrap;list-style-type:none;list-style-image:none;z-index:3;}#preftoc li.selected{font-weight:bold;background-color:#f9f9f9;border:1px solid #aaa;border-bottom:none;cursor:default;top:1px;padding-top:2px;margin-right:-3px;}#preftoc > li.selected{top:2px;}#preftoc a,#preftoc a:active{display:block;color:#000;padding:0 .7em;position:relative;text-decoration:none;}#preftoc li.selected a{cursor:default;text-decoration:none;}#prefcontrol{padding-top:2em;clear:both;}#preferences{margin:0;border:1px solid #aaa;clear:both;padding:1.5em;background-color:#F9F9F9;}.prefsection{border:none;padding:0;margin:0;}.prefsection fieldset{border:1px solid #aaa;float:left;margin-right:2em;}.prefsection legend{font-weight:bold;}.prefsection table,.prefsection legend{background-color:#F9F9F9;}.mainLegend{display:none;}div.prefsectiontip{font-size:95%;margin-top:0;background-color:#FFC1C1;padding:.2em .7em;clear:both;}.btnSavePrefs{font-weight:bold;padding-left:.3em;padding-right:.3em;}.preferences-login{clear:both;margin-bottom:1.5em;}.prefcache{font-size:90%;margin-top:2em;}div#userloginForm form,div#userlogin form#userlogin2{margin:0 3em 1em 0;border:1px solid #aaa;clear:both;padding:1.5em 2em;background-color:#f9f9f9;float:left;}div#userloginForm table,div#userlogin form#userlogin2 table{background-color:#f9f9f9;}div#userloginForm h2,div#userlogin form#userlogin2 h2{padding-top:0;}div#userlogin .captcha{border:1px solid #bbb;padding:1.5em 2em;width:400px;background-color:white;}#userloginprompt,#languagelinks{font-size:85%;}#login-sectiontip{font-size:85%;line-height:1.2;padding-top:2em;}#userlogin .loginText,#userlogin .loginPassword{width:12em;}#userloginlink a,#wpLoginattempt,#wpCreateaccount{font-weight:bold;}* > html #p-cactions li{border:none;}* > html #p-cactions li a{border:1px solid #aaa;border-bottom:none;}* > html #p-cactions li.selected a{border-color:#fabd23;}* > html #f-poweredbyico,* > html #f-copyrightico{width:88px;}* > html #bodyContent,* > html #bodyContent pre{overflow-x:auto;width:100%;padding-bottom:25px;}* html #footer{margin-top:0;}* html #column-content{display:inline;margin-bottom:0;}* html div.editsection{font-size:smaller;}#pagehistory li.selected{position:relative;}* > html #column-content{float:none;}* > html #column-one{position:absolute;left:0;top:0;}* > html #footer{margin-left:13.2em;}.redirectText{font-size:150%;margin:5px;}.printfooter{display:none;}.not-patrolled{background-color:#ffa;}div.patrollink{font-size:75%;text-align:right;}span.newpage,span.minor,span.searchmatch,span.bot{font-weight:bold;}span.unpatrolled{font-weight:bold;color:red;}span.searchmatch{color:red;}.sharedUploadNotice{font-style:italic;}span.updatedmarker{color:black;background-color:#0f0;}span.newpageletter{font-weight:bold;color:black;background-color:yellow;}span.minoreditletter{color:black;background-color:#c5ffe6;}table.gallery{border:1px solid #ccc;margin:2px;padding:2px;background-color:white;}table.gallery tr{vertical-align:top;}table.gallery td{vertical-align:top;background-color:#f9f9f9;border:solid 2px white;}table.gallery td.galleryheader{text-align:center;font-weight:bold;}div.gallerybox{margin:2px;width:150px;}div.gallerybox div.thumb{text-align:center;border:1px solid #ccc;margin:2px;}div.gallerytext{font-size:94%;padding:2px 4px;}span.comment{font-style:italic;}span.changedby{font-size:95%;}.previewnote{text-indent:3em;color:#c00;border-bottom:1px solid #aaa;padding-bottom:1em;margin-bottom:1em;}.previewnote p{margin:0;padding:0;}.editExternally{border:1px solid gray;background-color:#fff;padding:3px;margin-top:0.5em;float:left;font-size:small;text-align:center;}.editExternallyHelp{font-style:italic;color:gray;}li span.deleted,span.history-deleted{text-decoration:line-through;color:#888;font-style:italic;}.toggle{margin-left:2em;text-indent:-2em;}table.mw_metadata{font-size:0.8em;margin-left:0.5em;margin-bottom:0.5em;width:300px;}table.mw_metadata caption{font-weight:bold;}table.mw_metadata th{font-weight:normal;}table.mw_metadata td{padding:0.1em;}table.mw_metadata{border:none;border-collapse:collapse;}table.mw_metadata td,table.mw_metadata th{text-align:center;border:1px solid #aaa;padding-left:0.1em;padding-right:0.1em;}table.mw_metadata th{background-color:#f9f9f9;}table.mw_metadata td{background-color:#fcfcfc;}table.collapsed tr.collapsable{display:none;}ul#filetoc{text-align:center;border:1px solid #aaa;background-color:#f9f9f9;padding:5px;font-size:95%;margin-bottom:0.5em;margin-left:0;margin-right:0;}#filetoc li{display:inline;list-style-type:none;padding-right:2em;}input#wpSave,input#wpDiff{margin-right:0.33em;}#editform .editOptions{display:inline;}#wpSave{font-weight:bold;}table.revisionform_default{border:1px solid #000;}table.revisionform_focus{border:1px solid #000;background-color:#0BF;}tr.revision_tr_default{background-color:#EEE;}tr.revision_tr_first{background-color:#DDD;}p.revision_saved{color:green;font-weight:bold;}#mw_trackbacks{border:solid 1px #bbf;background-color:#eef;padding:0.2em;}#allmessagestable th{background-color:#b2b2ff;}#allmessagestable tr.orig{background-color:#ffe2e2;}#allmessagestable tr.new{background-color:#e2ffe2;}#allmessagestable tr.def{background-color:#f0f0ff;}div.noarticletext{border:1px solid #ccc;background:#fff;padding:.2em 1em;color:#000;}div#searchTargetContainer{left:10px;top:10px;width:90%;background:white;}div#searchTarget{padding:3px;margin:5px;background:#F0F0F0;border:solid 1px blue;}div#searchTarget ul li{list-style:none;}div#searchTarget ul li:before{color:orange;content:"\00BB \0020";}.ns-1 #content,.ns-1 #p-cactions li,.ns-1 #p-cactions li a{background:#f8fcff;}.ns-2 #content,.ns-2 #p-cactions li,.ns-2 #p-cactions li a,.ns-2 #media__manager_table{background:#f3f3ff;}#p-cactions .selected,#ca-edit{font-weight:bold;}#p-cactions .selected,#p-cactions .selected a,#p-cactions .selected span{z-index:3;padding-bottom:0.17em;}a.wikilink2:link,a.wikilink2:visited,a.wikilink2:hover{color:#ba0000;}#p-cactions li a.wikilink2{color:#ba0000;}div.dokuwiki dl.file pre{margin-top:0;}#media__left{width:30%;}#globalWrapper #column-one.mmanagernotembedded,#globalWrapper #footer.mmanagernotembedded{display:none !important;}#globalWrapper #content.mmanagernotembedded{margin:0 !important;}div.plugin_translation{float:right;text-align:right;display:inline;margin:4px 0;padding:0 !important;}.dokuwiki div.plugin_translation ul{display:inline;float:right;}.dokuwiki div.plugin_translation ul li{list-style-type:none;list-style-image:none !important;display:inline;}.dokuwiki div.plugin_translation form,.dokuwiki div.plugin_translation select{float:right;display:inline;}div.picker,button.pickerbutton{z-index:3;}.editButtons{float:left;padding:0 1em 0.7em 0;}.summary{float:left;}#size__ctl{float:right;}form#dw__editform div.license{clear:left;}div.dokuwiki input.missing{background-color:#fcc;}div.dokuwiki a:link,div.dokuwiki a:visited{color:#436976;text-decoration:none;}div.dokuwiki a:hover,div.dokuwiki a:active{color:#000;text-decoration:underline;}div.dokuwiki h1 a,div.dokuwiki h2 a,div.dokuwiki h3 a,div.dokuwiki h4 a,div.dokuwiki h5 a,div.dokuwiki a.nolink{color:#000 !important;text-decoration:none !important;}div.dokuwiki a.urlextern{background:transparent url(/doku/lib/tpl/monobook/static/3rd/monobook/external.png) center right no-repeat;padding:1px 13px 1px 0px;color:#436976;text-decoration:none;}div.dokuwiki a.windows{background:transparent url(/doku/lib/tpl/monobook/static/3rd/dokuwiki/windows.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;}div.dokuwiki a.interwiki{}div.dokuwiki a.media{}div.dokuwiki a.urlextern:link,div.dokuwiki a.windows:link,div.dokuwiki a.interwiki:link{color:#436976;}div.dokuwiki a.urlextern:visited,div.dokuwiki a.windows:visited,div.dokuwiki a.interwiki:visited{color:purple;}div.dokuwiki a.urlextern:hover,div.dokuwiki a.urlextern:active,div.dokuwiki a.windows:hover,div.dokuwiki a.windows:active,div.dokuwiki a.interwiki:hover,div.dokuwiki a.interwiki:active{color:#000;}div.dokuwiki a.mail{background:transparent url(/doku/lib/tpl/monobook/static/3rd/dokuwiki/mail_icon.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;}div.dokuwiki a.wikilink1{color:#002bb8 !important;}div.dokuwiki a.wikilink2{color:#ba0000 !important;text-decoration:none !important;border-bottom:dashed 1px #ba0000 !important;}div.dokuwiki img.media{margin:3px;}div.dokuwiki img.medialeft{border:0;float:left;margin:0 1.5em 0 0;}div.dokuwiki img.mediaright{border:0;float:right;margin:0 0 0 1.5em;}div.dokuwiki img.mediacenter{border:0;display:block;margin:0 auto;}div.dokuwiki img.middle{vertical-align:middle;}div.dokuwiki acronym{cursor:help;border-bottom:1px dotted #000;}div.dokuwiki blockquote{border-left:2px solid #8cacbb;padding-left:3px;}div.dokuwiki pre{font-size:120%;padding:0.5em;border:1px dashed #8cacbb;color:#000;overflow:auto;}div.dokuwiki pre.pre{background-color:#f9f9f9;}div.dokuwiki pre.code{background-color:#f9f9f9;}div.dokuwiki pre.file{background-color:#dee7ec;}div.dokuwiki dl.file,div.dokuwiki dl.code{margin-top:2em;margin-bottom:2.5em;}div.dokuwiki dl.file dt,div.dokuwiki dl.code dt{border:1px dashed #8cacbb;display:inline;padding:0.1em 1em;margin-left:2em;}div.dokuwiki dl.code dt a,div.dokuwiki dl.file dt a{color:#000;}div.dokuwiki dl.code dt{background-color:#f9f9f9;border-bottom:1px solid #f9f9f9;}div.dokuwiki dl.file dt{background-color:#dee7ec;border-bottom:1px solid #dee7ec;}div.dokuwiki table.inline{background-color:#fff;border-spacing:0px;border-collapse:collapse;}div.dokuwiki table.inline th{padding:3px;border:1px solid #8cacbb;background-color:#dee7ec;}div.dokuwiki table.inline td{padding:3px;border:1px solid #8cacbb;}div.dokuwiki div.toc{margin:1.2em 0 0 2em;float:right;width:200px;font-size:80%;clear:both;}div.dokuwiki div.tocheader{border:1px solid #8cacbb;background-color:#dee7ec;text-align:left;font-weight:bold;padding:3px;margin-bottom:2px;}div.dokuwiki span.toc_open,div.dokuwiki span.toc_close{border:0.4em solid #dee7ec;float:right;display:block;margin:0.4em 3px 0 0;}div.dokuwiki span.toc_open span,div.dokuwiki span.toc_close span{display:none;}div.dokuwiki span.toc_open{margin-top:0.4em;border-top:0.4em solid #000;}div.dokuwiki span.toc_close{margin-top:0;border-bottom:0.4em solid #000;}div.dokuwiki #toc__inside{border:1px solid #8cacbb;background-color:#fff;text-align:left;padding:0.5em 0 0.7em 0;}div.dokuwiki ul.toc{list-style-type:none;list-style-image:none;line-height:1.2em;padding-left:1em;margin:0;}div.dokuwiki ul.toc li{background:transparent url(/doku/lib/tpl/monobook/static/3rd/dokuwiki/tocdot2.gif) 0 0.6em no-repeat;padding-left:0.4em;}div.dokuwiki ul.toc li.clear{background-image:none;padding-left:0.4em;}div.dokuwiki a.toc:link,div.dokuwiki a.toc:visited{color:#436976;}div.dokuwiki a.toc:hover,div.dokuwiki a.toc:active{color:#000;}div.dokuwiki table.diff{background-color:#fff;width:100%;}div.dokuwiki td.diff-blockheader{font-weight:bold;}div.dokuwiki table.diff th{border-bottom:1px solid #8cacbb;font-size:110%;width:50%;font-weight:normal;text-align:left;}div.dokuwiki table.diff th a{font-weight:bold;}div.dokuwiki table.diff th span.user{color:#000;font-size:80%;}div.dokuwiki table.diff th span.sum{font-size:80%;font-weight:bold;}div.dokuwiki table.diff th.minor{font-style:italic;}div.dokuwiki table.diff td{font-family:monospace;font-size:100%;}div.dokuwiki td.diff-addedline{background-color:#dfd;}div.dokuwiki td.diff-deletedline{background-color:#ffb;}div.dokuwiki td.diff-context{background-color:#fff;}div.dokuwiki table.diff td.diff-addedline strong,div.dokuwiki table.diff td.diff-deletedline strong{color:red;}div.dokuwiki div.footnotes{clear:both;border-top:1px solid #8cacbb;padding-left:1em;margin-top:1em;}div.dokuwiki div.fn{font-size:90%;}div.dokuwiki a.fn_bot{font-weight:bold;}div.insitu-footnote{line-height:1.2em;border:1px solid #8cacbb;background-color:#f9f9f9;text-align:left;padding:4px;max-width:40%;z-index:3;}* html .insitu-footnote pre.code,* html .insitu-footnote pre.file{padding-bottom:18px;}div.dokuwiki .search_result{margin-bottom:6px;padding:0 10px 0 30px;}div.dokuwiki .search_snippet{color:#ccc;font-size:12px;margin-left:20px;}div.dokuwiki .search_sep{color:#000;}div.dokuwiki .search_hit{color:#000;background-color:#ff9;}div.dokuwiki strong.search_hit{font-weight:normal;}div.dokuwiki div.search_quickresult{margin:0 0 15px 30px;padding:0 10px 10px 0;border-bottom:1px dashed #8cacbb;}div.dokuwiki div.search_quickresult h3{margin:0 0 1.0em 0;font-size:1em;font-weight:bold;}div.dokuwiki ul.search_quickhits{margin:0 0 0.5em 1.0em;}div.dokuwiki ul.search_quickhits li{margin:0 1.0em 0 1.0em;float:left;width:30%;}div.dokuwiki div.section_highlight{background-color:#dee7ec;}button.toolbutton{background-color:#fff;padding:0px;margin:0 1px 0 0;border:1px solid #8cacbb;cursor:pointer;}html>body button.toolbutton{background:#fff url(/doku/lib/tpl/monobook/static/3rd/dokuwiki/images/buttonshadow.png) repeat-x bottom;}div.picker{width:250px;border:1px solid #8cacbb;background-color:#dee7ec;}div.pk_hl{width:125px;}button.pickerbutton{padding:0px;margin:0 1px 1px 0;border:0;background-color:transparent;font-size:80%;cursor:pointer;}#p-cactions #ca-addsection a{padding-left:.4em;padding-right:.4em;}#qsearch__in{width:10.9em;margin:0;font-size:95%;}#qsearch__out{background-color:#f9f9f9;border:1px solid #8cacbb;display:none;font-size:80%;line-height:1.2em;opacity:0.9;padding:4px;text-align:left;position:absolute;left:150px;z-index:30000;}div.dokuwiki div.ajax_qsearch{position:absolute;width:200px;opacity:0.9;display:none;font-size:80%;line-height:1.2em;border:1px solid #8cacbb;background-color:#f7f9fa;text-align:left;padding:4px;}li#ca-talk{margin-right:1.6em;}li#ca-watch,li#ca-unwatch,li#ca-varlang-0,li#ca-print{margin-left:1.6em;}div.secedit input.button{border:0px;text-transform:lowercase;color:blue;background-color:transparent;vertical-align:middle;text-decoration:none;margin:0px;padding:0px;font-size:10px;cursor:pointer;height:15px !important;max-height:15px !important;min-height:15px !important;float:right;display:inline;}div.secedit2{text-align:right;}div.secedit2 a{border:0px;text-transform:lowercase;color:blue;background-color:transparent;vertical-align:middle;text-decoration:none;font-size:10px;cursor:pointer;}a.spell__error{color:#f00;text-decoration:underline;}div#spell__suggest{position:absolute;left:0;top:0;display:none;z-index:2;background-color:#fff;padding:2px;border:1px solid #000;font-size:80%;}div#spell__result{display:none;font-family:monospace;overflow:auto;z-index:1;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;border:1px solid #8cacbb;color:Black;font-size:14px;padding:3px;background-color:#f7f9fa;}span.spell__noerr{color:#093;}span.spell__wait{color:#06c;}.leftalign{text-align:left;}.centeralign{text-align:center;}.rightalign{text-align:right;}#media__tree img{float:left;padding:0.5em 0.3em 0 0;}#media__tree ul{list-style-type:none;list-style-image:none;margin-left:1.5em;}#media__tree li{clear:left;list-style-type:none;list-style-image:none;}*+html #media__tree li,* html #media__tree li{border:1px solid #fff;}#media__opts{padding-left:1em;margin-bottom:0.5em;}#media__opts input{float:left;display:block;margin-top:4px;position:absolute;}*+html #media__opts input,* html #media__opts input{position:static;}#media__opts label{display:block;float:left;margin-left:20px;margin-bottom:4px;}*+html #media__opts label,* html #media__opts label{margin-left:10px;}#media__opts br{clear:left;}#media__content img.load{margin:1em auto;}#media__content #scroll__here{border:1px dashed #8cacbb;}#media__content .odd{background-color:#f9f9f9;padding:0.4em;}#media__content .even{padding:0.4em;}#media__content a.mediafile{margin-right:1.5em;font-weight:bold;}#media__content div.detail{padding:0.3em 0 0.3em 2em;}#media__content div.detail div.thumb{float:left;width:130px;text-align:center;margin-right:0.4em;}#media__content img.btn{vertical-align:text-bottom;}#media__content div.example{color:#000;margin-left:1em;}#media__content div.upload{font-size:90%;padding:0 0.5em 0.5em 0.5em;}#media__content form#dw__upload,#media__content div#dw__flashupload{display:block;border-bottom:solid 1px #8cacbb;padding:0 0.5em 1em 0.5em;}#media__content form#dw__upload fieldset{padding:0;margin:0;border:none;width:auto;}#media__content form#dw__upload p{text-align:left;padding:0.25em 0;margin:0;line-height:1.0em;}#media__content form#dw__upload label.check{float:none;width:auto;margin-left:11.5em;}#media__content form.meta{display:block;padding:0 0 1em 0;}#media__content form.meta label{display:block;width:25%;float:left;font-weight:bold;margin-left:1em;clear:left;}#media__content form.meta .edit{font:100% "Lucida Grande",Verdana,Lucida,Helvetica,Arial,sans-serif;float:left;width:70%;padding-right:0;padding-left:0.2em;margin:2px;}#media__content form.meta textarea.edit{height:8em;}#media__content form.meta div.metafield{clear:left;}#media__content form.meta div.buttons{clear:left;margin-left:20%;padding-left:1em;}.dokuwiki ul.admin_tasks{font-size:115%;float:left;width:40%;list-style-type:none;}.dokuwiki ul.admin_tasks li{line-height:22px;padding-left:35px;margin:1em 0;background:transparent none no-repeat scroll 0 0;text-align:left;list-style-type:none;list-style-image:none;}.dokuwiki ul.admin_tasks li div.li{font-weight:bold;border-left:1px dashed #fff;}.dokuwiki ul.admin_tasks li.admin_acl{background-image:url(/doku/lib/tpl/monobook/../../images/admin/acl.png);}.dokuwiki ul.admin_tasks li.admin_usermanager{background-image:url(/doku/lib/tpl/monobook/../../images/admin/usermanager.png);}.dokuwiki ul.admin_tasks li.admin_plugin{background-image:url(/doku/lib/tpl/monobook/../../images/admin/plugin.png);}.dokuwiki ul.admin_tasks li.admin_config{background-image:url(/doku/lib/tpl/monobook/../../images/admin/config.png);}.dokuwiki ul.admin_tasks li.admin_revert{background-image:url(/doku/lib/tpl/monobook/../../images/admin/revert.png);}.dokuwiki ul.admin_tasks li.admin_popularity{background-image:url(/doku/lib/tpl/monobook/../../images/admin/popularity.png);}#link__wiz{position:absolute;display:block;z-index:99;width:300px;height:250px;padding:0;margin:0;overflow:hidden;border:1px solid #8cacbb;background-color:#fff;text-align:center;}#link__wiz_header{background-color:#dee7ec;height:16px;margin-bottom:5px;}#link__wiz_close{cursor:pointer;margin:0;}#link__wiz_result{background-color:#fff;width:293px;height:193px;overflow:auto;border:1px solid #8cacbb;margin:3px auto;text-align:left;}#link__wiz_result div.type_u{padding:3px 3px 3px 22px;background:transparent url(/doku/lib/tpl/monobook/../../images/up.png) 3px 3px no-repeat;}#link__wiz_result div.type_f{padding:3px 3px 3px 22px;background:transparent url(/doku/lib/tpl/monobook/../../images/page.png) 3px 3px no-repeat;}#link__wiz_result div.type_d{padding:3px 3px 3px 22px;background:transparent url(/doku/lib/tpl/monobook/../../images/ns.png) 3px 3px no-repeat;}#link__wiz_result div.even{background-color:#fff;}#link__wiz_result div.selected{background-color:#dee7ec;}#link__wiz_result span{display:block;color:#000;}.ondrag{cursor:move;opacity:0.8;} \ No newline at end of file diff --git a/c/skripta/compilation/jazyk_c compilation_files/css(2).php b/c/skripta/compilation/jazyk_c compilation_files/css(2).php new file mode 100755 index 0000000..7a1d64e --- /dev/null +++ b/c/skripta/compilation/jazyk_c compilation_files/css(2).php @@ -0,0 +1 @@ +a.interwiki{background:transparent url(/doku/lib/images/interwiki.png) 0px 1px no-repeat;padding-left:16px;}a.iw_wp{background-image:url(/doku/lib/images/interwiki/wp.gif)}a.iw_wpfr{background-image:url(/doku/lib/images/interwiki/wpfr.gif)}a.iw_wpde{background-image:url(/doku/lib/images/interwiki/wpde.gif)}a.iw_wpes{background-image:url(/doku/lib/images/interwiki/wpes.gif)}a.iw_wppl{background-image:url(/doku/lib/images/interwiki/wppl.gif)}a.iw_wpjp{background-image:url(/doku/lib/images/interwiki/wpjp.gif)}a.iw_wpmeta{background-image:url(/doku/lib/images/interwiki/wpmeta.gif)}a.iw_doku{background-image:url(/doku/lib/images/interwiki/doku.gif)}a.iw_dokubug{background-image:url(/doku/lib/images/interwiki/dokubug.gif)}a.iw_amazon{background-image:url(/doku/lib/images/interwiki/amazon.gif)}a.iw_amazon_de{background-image:url(/doku/lib/images/interwiki/amazon.de.gif)}a.iw_amazon_uk{background-image:url(/doku/lib/images/interwiki/amazon.uk.gif)}a.iw_phpfn{background-image:url(/doku/lib/images/interwiki/phpfn.gif)}a.iw_coral{background-image:url(/doku/lib/images/interwiki/coral.gif)}a.iw_sb{background-image:url(/doku/lib/images/interwiki/sb.gif)}a.iw_google{background-image:url(/doku/lib/images/interwiki/google.gif)}a.iw_meatball{background-image:url(/doku/lib/images/interwiki/meatball.gif)}a.iw_wiki{background-image:url(/doku/lib/images/interwiki/wiki.gif)}a.mediafile{background:transparent url(/doku/lib/images/fileicons/file.png) 0px 1px no-repeat;padding-left:18px;padding-bottom:1px;}a.mf_sxd{background-image:url(/doku/lib/images/fileicons/sxd.png)}a.mf_js{background-image:url(/doku/lib/images/fileicons/js.png)}a.mf_pl{background-image:url(/doku/lib/images/fileicons/pl.png)}a.mf_jpg{background-image:url(/doku/lib/images/fileicons/jpg.png)}a.mf_jpeg{background-image:url(/doku/lib/images/fileicons/jpeg.png)}a.mf_sxi{background-image:url(/doku/lib/images/fileicons/sxi.png)}a.mf_png{background-image:url(/doku/lib/images/fileicons/png.png)}a.mf_pdf{background-image:url(/doku/lib/images/fileicons/pdf.png)}a.mf_rtf{background-image:url(/doku/lib/images/fileicons/rtf.png)}a.mf_cs{background-image:url(/doku/lib/images/fileicons/cs.png)}a.mf_ods{background-image:url(/doku/lib/images/fileicons/ods.png)}a.mf_cpp{background-image:url(/doku/lib/images/fileicons/cpp.png)}a.mf_php{background-image:url(/doku/lib/images/fileicons/php.png)}a.mf_odg{background-image:url(/doku/lib/images/fileicons/odg.png)}a.mf_htm{background-image:url(/doku/lib/images/fileicons/htm.png)}a.mf_rb{background-image:url(/doku/lib/images/fileicons/rb.png)}a.mf_odi{background-image:url(/doku/lib/images/fileicons/odi.png)}a.mf_ps{background-image:url(/doku/lib/images/fileicons/ps.png)}a.mf_c{background-image:url(/doku/lib/images/fileicons/c.png)}a.mf_odf{background-image:url(/doku/lib/images/fileicons/odf.png)}a.mf_java{background-image:url(/doku/lib/images/fileicons/java.png)}a.mf_html{background-image:url(/doku/lib/images/fileicons/html.png)}a.mf_bz2{background-image:url(/doku/lib/images/fileicons/bz2.png)}a.mf_xls{background-image:url(/doku/lib/images/fileicons/xls.png)}a.mf_py{background-image:url(/doku/lib/images/fileicons/py.png)}a.mf_odp{background-image:url(/doku/lib/images/fileicons/odp.png)}a.mf_doc{background-image:url(/doku/lib/images/fileicons/doc.png)}a.mf_txt{background-image:url(/doku/lib/images/fileicons/txt.png)}a.mf_rar{background-image:url(/doku/lib/images/fileicons/rar.png)}a.mf_odc{background-image:url(/doku/lib/images/fileicons/odc.png)}a.mf_odt{background-image:url(/doku/lib/images/fileicons/odt.png)}a.mf_zip{background-image:url(/doku/lib/images/fileicons/zip.png)}a.mf_sxw{background-image:url(/doku/lib/images/fileicons/sxw.png)}a.mf_gz{background-image:url(/doku/lib/images/fileicons/gz.png)}a.mf_xml{background-image:url(/doku/lib/images/fileicons/xml.png)}a.mf_lua{background-image:url(/doku/lib/images/fileicons/lua.png)}a.mf_tar{background-image:url(/doku/lib/images/fileicons/tar.png)}a.mf_tgz{background-image:url(/doku/lib/images/fileicons/tgz.png)}a.mf_swf{background-image:url(/doku/lib/images/fileicons/swf.png)}a.mf_css{background-image:url(/doku/lib/images/fileicons/css.png)}a.mf_ppt{background-image:url(/doku/lib/images/fileicons/ppt.png)}a.mf_conf{background-image:url(/doku/lib/images/fileicons/conf.png)}a.mf_rpm{background-image:url(/doku/lib/images/fileicons/rpm.png)}a.mf_deb{background-image:url(/doku/lib/images/fileicons/deb.png)}a.mf_sxc{background-image:url(/doku/lib/images/fileicons/sxc.png)}a.mf_gif{background-image:url(/doku/lib/images/fileicons/gif.png)}.toc,div#footer-buttons,input.button,.dokuwiki div.plugin_translation,li#usermod,div#catlinks,.bchead{display:none;}.urlextern.text:after,.urlextern:after,a.urlextern.text:after,a.urlextern:after,a.interwiki.text:after,a.interwiki:after{content:" (" attr(href) ") ";}a.stub,a.new{color:#ba0000;text-decoration:none;}#toc{border:1px solid #aaa;background-color:#f9f9f9;padding:5px;}.tocindent{margin-left:2em;}.tocline{margin-bottom:0px;}div.floatright{float:right;clear:right;margin:0;position:relative;border:0.5em solid White;border-width:0.5em 0 0.8em 1.4em;}div.floatright p{font-style:italic;}div.floatleft{float:left;margin:0.3em 0.5em 0.5em 0;position:relative;border:0.5em solid White;border-width:0.5em 1.4em 0.8em 0;}div.floatleft p{font-style:italic;}div.thumb{margin-bottom:0.5em;border-style:solid;border-color:White;width:auto;overflow:hidden;}div.thumb div{border:1px solid #ccc;padding:3px !important;background-color:#f9f9f9;font-size:94%;text-align:center;}div.thumb div a img{border:1px solid #ccc;}div.thumb div div.thumbcaption{border:none;padding:0.3em 0 0.1em 0;}div.magnify{display:none;}div.tright{float:right;clear:right;border-width:0.5em 0 0.8em 1.4em;}div.tleft{float:left;margin-right:0.5em;border-width:0.5em 1.4em 0.8em 0;}img.thumbborder{border:1px solid #ddd;}table.rimage{float:right;width:1pt;position:relative;margin-left:1em;margin-bottom:1em;text-align:center;}body{background:White;color:Black;margin:0;padding:0;}.noprint,div#jump-to-nav,div.top,div#column-one,#colophon,.editsection,.toctoggle,.tochidden,div#f-poweredbyico,div#f-copyrightico,li#viewcount,li#about,li#disclaimer,li#privacy,#mw-hidden-catlinks{display:none;}ul{list-style-type:square;}#content{background:none;border:none ! important;padding:0 ! important;margin:0 ! important;}#footer{background:white;color:black;border-top:1px solid black;}h1,h2,h3,h4,h5,h6{font-weight:bold;}p,.documentDescription{margin:1em 0 ! important;line-height:1.2em;}.tocindent p{margin:0 0 0 0 ! important;}pre{border:1pt dashed black;white-space:pre;font-size:8pt;overflow:auto;padding:1em 0;background:white;color:black;}table.listing,table.listing td{border:1pt solid black;border-collapse:collapse;}a{color:Black !important;background:none !important;padding:0 !important;}a:link,a:visited{color:#520;background:transparent;text-decoration:underline;}#content a.external.text:after,#content a.external.autonumber:after{content:" (" attr(href) ") ";}#globalWrapper{width:100% !important;min-width:0 !important;}#content{background:white;color:black;}#column-content{margin:0 !important;}#column-content #content{padding:1em;margin:0 !important;}a,a.external,a.new,a.stub{color:black ! important;text-decoration:none ! important;}a,a.external,a.new,a.stub{color:inherit ! important;text-decoration:inherit ! important;}img{border:none;}img.tex{vertical-align:middle;}span.texhtml{font-family:serif;}#siteNotice{display:none;}div.gallerybox{border:1px solid #ccc;background-color:#f9f9f9;width:150px;}div.gallerytext{overflow:visible;}table.diff{background:white;}td.diff-otitle{background:#fff;}td.diff-ntitle{background:#fff;}td.diff-addedline{background:#cfc;font-size:smaller;border:solid 2px black;}td.diff-deletedline{background:#ffa;font-size:smaller;border:dotted 2px black;}td.diff-context{background:#eee;font-size:smaller;}.diffchange{color:silver;font-weight:bold;text-decoration:underline;} \ No newline at end of file diff --git a/c/skripta/compilation/jazyk_c compilation_files/css.php b/c/skripta/compilation/jazyk_c compilation_files/css.php new file mode 100755 index 0000000..f54b38b --- /dev/null +++ b/c/skripta/compilation/jazyk_c compilation_files/css.php @@ -0,0 +1 @@ +a.interwiki{background:transparent url(/doku/lib/images/interwiki.png) 0px 1px no-repeat;padding-left:16px;}a.iw_wp{background-image:url(/doku/lib/images/interwiki/wp.gif)}a.iw_wpfr{background-image:url(/doku/lib/images/interwiki/wpfr.gif)}a.iw_wpde{background-image:url(/doku/lib/images/interwiki/wpde.gif)}a.iw_wpes{background-image:url(/doku/lib/images/interwiki/wpes.gif)}a.iw_wppl{background-image:url(/doku/lib/images/interwiki/wppl.gif)}a.iw_wpjp{background-image:url(/doku/lib/images/interwiki/wpjp.gif)}a.iw_wpmeta{background-image:url(/doku/lib/images/interwiki/wpmeta.gif)}a.iw_doku{background-image:url(/doku/lib/images/interwiki/doku.gif)}a.iw_dokubug{background-image:url(/doku/lib/images/interwiki/dokubug.gif)}a.iw_amazon{background-image:url(/doku/lib/images/interwiki/amazon.gif)}a.iw_amazon_de{background-image:url(/doku/lib/images/interwiki/amazon.de.gif)}a.iw_amazon_uk{background-image:url(/doku/lib/images/interwiki/amazon.uk.gif)}a.iw_phpfn{background-image:url(/doku/lib/images/interwiki/phpfn.gif)}a.iw_coral{background-image:url(/doku/lib/images/interwiki/coral.gif)}a.iw_sb{background-image:url(/doku/lib/images/interwiki/sb.gif)}a.iw_google{background-image:url(/doku/lib/images/interwiki/google.gif)}a.iw_meatball{background-image:url(/doku/lib/images/interwiki/meatball.gif)}a.iw_wiki{background-image:url(/doku/lib/images/interwiki/wiki.gif)}a.mediafile{background:transparent url(/doku/lib/images/fileicons/file.png) 0px 1px no-repeat;padding-left:18px;padding-bottom:1px;}a.mf_sxd{background-image:url(/doku/lib/images/fileicons/sxd.png)}a.mf_js{background-image:url(/doku/lib/images/fileicons/js.png)}a.mf_pl{background-image:url(/doku/lib/images/fileicons/pl.png)}a.mf_jpg{background-image:url(/doku/lib/images/fileicons/jpg.png)}a.mf_jpeg{background-image:url(/doku/lib/images/fileicons/jpeg.png)}a.mf_sxi{background-image:url(/doku/lib/images/fileicons/sxi.png)}a.mf_png{background-image:url(/doku/lib/images/fileicons/png.png)}a.mf_pdf{background-image:url(/doku/lib/images/fileicons/pdf.png)}a.mf_rtf{background-image:url(/doku/lib/images/fileicons/rtf.png)}a.mf_cs{background-image:url(/doku/lib/images/fileicons/cs.png)}a.mf_ods{background-image:url(/doku/lib/images/fileicons/ods.png)}a.mf_cpp{background-image:url(/doku/lib/images/fileicons/cpp.png)}a.mf_php{background-image:url(/doku/lib/images/fileicons/php.png)}a.mf_odg{background-image:url(/doku/lib/images/fileicons/odg.png)}a.mf_htm{background-image:url(/doku/lib/images/fileicons/htm.png)}a.mf_rb{background-image:url(/doku/lib/images/fileicons/rb.png)}a.mf_odi{background-image:url(/doku/lib/images/fileicons/odi.png)}a.mf_ps{background-image:url(/doku/lib/images/fileicons/ps.png)}a.mf_c{background-image:url(/doku/lib/images/fileicons/c.png)}a.mf_odf{background-image:url(/doku/lib/images/fileicons/odf.png)}a.mf_java{background-image:url(/doku/lib/images/fileicons/java.png)}a.mf_html{background-image:url(/doku/lib/images/fileicons/html.png)}a.mf_bz2{background-image:url(/doku/lib/images/fileicons/bz2.png)}a.mf_xls{background-image:url(/doku/lib/images/fileicons/xls.png)}a.mf_py{background-image:url(/doku/lib/images/fileicons/py.png)}a.mf_odp{background-image:url(/doku/lib/images/fileicons/odp.png)}a.mf_doc{background-image:url(/doku/lib/images/fileicons/doc.png)}a.mf_txt{background-image:url(/doku/lib/images/fileicons/txt.png)}a.mf_rar{background-image:url(/doku/lib/images/fileicons/rar.png)}a.mf_odc{background-image:url(/doku/lib/images/fileicons/odc.png)}a.mf_odt{background-image:url(/doku/lib/images/fileicons/odt.png)}a.mf_zip{background-image:url(/doku/lib/images/fileicons/zip.png)}a.mf_sxw{background-image:url(/doku/lib/images/fileicons/sxw.png)}a.mf_gz{background-image:url(/doku/lib/images/fileicons/gz.png)}a.mf_xml{background-image:url(/doku/lib/images/fileicons/xml.png)}a.mf_lua{background-image:url(/doku/lib/images/fileicons/lua.png)}a.mf_tar{background-image:url(/doku/lib/images/fileicons/tar.png)}a.mf_tgz{background-image:url(/doku/lib/images/fileicons/tgz.png)}a.mf_swf{background-image:url(/doku/lib/images/fileicons/swf.png)}a.mf_css{background-image:url(/doku/lib/images/fileicons/css.png)}a.mf_ppt{background-image:url(/doku/lib/images/fileicons/ppt.png)}a.mf_conf{background-image:url(/doku/lib/images/fileicons/conf.png)}a.mf_rpm{background-image:url(/doku/lib/images/fileicons/rpm.png)}a.mf_deb{background-image:url(/doku/lib/images/fileicons/deb.png)}a.mf_sxc{background-image:url(/doku/lib/images/fileicons/sxc.png)}a.mf_gif{background-image:url(/doku/lib/images/fileicons/gif.png)} \ No newline at end of file diff --git a/c/skripta/compilation/jazyk_c compilation_files/icon_smile.gif b/c/skripta/compilation/jazyk_c compilation_files/icon_smile.gif new file mode 100755 index 0000000000000000000000000000000000000000..7b1f6d30449c976f49a4ff4f55558156a7084732 GIT binary patch literal 174 zcmZ?wbhEHb3F2nzSlmGt}{tp7jjg5`} z|9}1eDNqRrDE?$&WMJT9&;fBkW-zcsU+|R7ntLO3**QsZu>uaJIn9DTj_MrhAC|2y zn^DM@#l<(@zDcWq`B+oyDaGR~0+SdoFXD`_(PqAxy<2o0Q>0^(jhH~$tb+>(~Mkip?iSJVU!i155M;PsyygH$s=4lN1*#;9#25Ea>CN&heak$?CEh zA7(bsN;","close":"<\/del>"},{"type":"autohead","title":"Nadpis stejn\u00e9 \u00farovn\u011b","icon":"hequal.png","key":"8","text":"Nadpis","mod":0},{"type":"autohead","title":"Nadpis ni\u017e\u0161\u00ed \u00farovn\u011b","icon":"hminus.png","key":"9","text":"Nadpis","mod":1},{"type":"autohead","title":"Nadpis vy\u0161\u0161\u00ed \u00farovn\u011b","icon":"hplus.png","key":"0","text":"Nadpis","mod":-1},{"type":"picker","title":"Vybrat nadpis","icon":"h.png","class":"pk_hl","list":[{"type":"format","title":"Nadpis 1. \u00farovn\u011b","icon":"h1.png","key":"1","open":"====== ","close":" ======\\n"},{"type":"format","title":"Nadpis 2. \u00farovn\u011b","icon":"h2.png","key":"2","open":"===== ","close":" =====\\n"},{"type":"format","title":"Nadpis 3. \u00farovn\u011b","icon":"h3.png","key":"3","open":"==== ","close":" ====\\n"},{"type":"format","title":"Nadpis 4. \u00farovn\u011b","icon":"h4.png","key":"4","open":"=== ","close":" ===\\n"},{"type":"format","title":"Nadpis 5. \u00farovn\u011b","icon":"h5.png","key":"5","open":"== ","close":" ==\\n"}]},{"type":"linkwiz","title":"Intern\u00ed odkaz","icon":"link.png","key":"l","open":"[[","close":"]]"},{"type":"format","title":"Extern\u00ed odkaz","icon":"linkextern.png","open":"[[","close":"]]","sample":"http:\/\/example.com|Extern\u00ed odkaz"},{"type":"formatln","title":"\u010c\u00edslovan\u00fd seznam","icon":"ol.png","open":" - ","close":"","key":"-"},{"type":"formatln","title":"Ne\u010d\u00edslovan\u00fd seznam","icon":"ul.png","open":" * ","close":"","key":"."},{"type":"insert","title":"Vodorovn\u00e1 \u010d\u00e1ra","icon":"hr.png","insert":"\\n----\\n"},{"type":"mediapopup","title":"Vlo\u017eit obr\u00e1zky nebo jin\u00e9 soubory","icon":"image.png","url":"lib\/exe\/mediamanager.php?ns=","name":"mediaselect","options":"width=750,height=500,left=20,top=20,scrollbars=yes,resizable=yes"},{"type":"picker","title":"Emotikony","icon":"smiley.png","list":{"8-)":"icon_cool.gif","8-O":"icon_eek.gif","8-o":"icon_eek.gif",":-(":"icon_sad.gif",":-)":"icon_smile.gif","=)":"icon_smile2.gif",":-\/":"icon_doubt.gif",":-\\":"icon_doubt2.gif",":-?":"icon_confused.gif",":-D":"icon_biggrin.gif",":-P":"icon_razz.gif",":-o":"icon_surprised.gif",":-O":"icon_surprised.gif",":-x":"icon_silenced.gif",":-X":"icon_silenced.gif",":-|":"icon_neutral.gif",";-)":"icon_wink.gif","^_^":"icon_fun.gif",":?:":"icon_question.gif",":!:":"icon_exclaim.gif","LOL":"icon_lol.gif","FIXME":"fixme.gif","README":"readme.gif","TODO":"todo.gif","DELETEME":"delete.gif","DUPLICATE":"duplicate.gif","DONE":"done.gif"},"icobase":"smileys"},{"type":"picker","title":"Speci\u00e1ln\u00ed znaky","icon":"chars.png","list":["\u00c0","\u00e0","\u00c1","\u00e1","\u00c2","\u00e2","\u00c3","\u00e3","\u00c4","\u00e4","\u01cd","\u01ce","\u0102","\u0103","\u00c5","\u00e5","\u0100","\u0101","\u0104","\u0105","\u00c6","\u00e6","\u0106","\u0107","\u00c7","\u00e7","\u010c","\u010d","\u0108","\u0109","\u010a","\u010b","\u00d0","\u0111","\u00f0","\u010e","\u010f","\u00c8","\u00e8","\u00c9","\u00e9","\u00ca","\u00ea","\u00cb","\u00eb","\u011a","\u011b","\u0112","\u0113","\u0116","\u0117","\u0118","\u0119","\u0122","\u0123","\u011c","\u011d","\u011e","\u011f","\u0120","\u0121","\u0124","\u0125","\u00cc","\u00ec","\u00cd","\u00ed","\u00ce","\u00ee","\u00cf","\u00ef","\u01cf","\u01d0","\u012a","\u012b","\u0130","\u0131","\u012e","\u012f","\u0134","\u0135","\u0136","\u0137","\u0139","\u013a","\u013b","\u013c","\u013d","\u013e","\u0141","\u0142","\u013f","\u0140","\u0143","\u0144","\u00d1","\u00f1","\u0145","\u0146","\u0147","\u0148","\u00d2","\u00f2","\u00d3","\u00f3","\u00d4","\u00f4","\u00d5","\u00f5","\u00d6","\u00f6","\u01d1","\u01d2","\u014c","\u014d","\u0150","\u0151","\u0152","\u0153","\u00d8","\u00f8","\u0154","\u0155","\u0156","\u0157","\u0158","\u0159","\u015a","\u015b","\u015e","\u015f","\u0160","\u0161","\u015c","\u015d","\u0162","\u0163","\u0164","\u0165","\u00d9","\u00f9","\u00da","\u00fa","\u00db","\u00fb","\u00dc","\u00fc","\u01d3","\u01d4","\u016c","\u016d","\u016a","\u016b","\u016e","\u016f","\u01d6","\u01d8","\u01da","\u01dc","\u0172","\u0173","\u0170","\u0171","\u0174","\u0175","\u00dd","\u00fd","\u0178","\u00ff","\u0176","\u0177","\u0179","\u017a","\u017d","\u017e","\u017b","\u017c","\u00de","\u00fe","\u00df","\u0126","\u0127","\u00bf","\u00a1","\u00a2","\u00a3","\u00a4","\u00a5","\u20ac","\u00a6","\u00a7","\u00aa","\u00ac","\u00af","\u00b0","\u00b1","\u00f7","\u2030","\u00bc","\u00bd","\u00be","\u00b9","\u00b2","\u00b3","\u00b5","\u00b6","\u2020","\u2021","\u00b7","\u2022","\u00ba","\u2200","\u2202","\u2203","\u018f","\u0259","\u2205","\u2207","\u2208","\u2209","\u220b","\u220f","\u2211","\u203e","\u2212","\u2217","\u221a","\u221d","\u221e","\u2220","\u2227","\u2228","\u2229","\u222a","\u222b","\u2234","\u223c","\u2245","\u2248","\u2260","\u2261","\u2264","\u2265","\u2282","\u2283","\u2284","\u2286","\u2287","\u2295","\u2297","\u22a5","\u22c5","\u25ca","\u2118","\u2111","\u211c","\u2135","\u2660","\u2663","\u2665","\u2666","\u03b1","\u03b2","\u0393","\u03b3","\u0394","\u03b4","\u03b5","\u03b6","\u03b7","\u0398","\u03b8","\u03b9","\u03ba","\u039b","\u03bb","\u03bc","\u039e","\u03be","\u03a0","\u03c0","\u03c1","\u03a3","\u03c3","\u03a4","\u03c4","\u03c5","\u03a6","\u03c6","\u03c7","\u03a8","\u03c8","\u03a9","\u03c9","\u2605","\u2606","\u260e","\u261a","\u261b","\u261c","\u261d","\u261e","\u261f","\u2639","\u263a","\u2714","\u2718","\u00d7","\u201e","\u201c","\u201d","\u201a","\u2018","\u2019","\u00ab","\u00bb","\u2039","\u203a","\u2014","\u2013","\u2026","\u2190","\u2191","\u2192","\u2193","\u2194","\u21d0","\u21d1","\u21d2","\u21d3","\u21d4","\u00a9","\u2122","\u00ae","\u2032","\u2033","[","]","{","}","~","(",")","%","\u00a7","$","#","|","@"]},{"type":"signature","title":"Vlo\u017eit podpis","icon":"sig.png","key":"y"}];function isUndefined(prop){return(typeof prop=='undefined');}function isFunction(prop){return(typeof prop=='function');}function isString(prop){return(typeof prop=='string');}function isNumber(prop){return(typeof prop=='number');}function isNumeric(prop){return isNumber(prop)&&!isNaN(prop)&&isFinite(prop);}function isArray(prop){return(prop instanceof Array);}function isRegExp(prop){return(prop instanceof RegExp);}function isBoolean(prop){return('boolean'==typeof prop);}function isScalar(prop){return isNumeric(prop)||isString(prop);}function isEmpty(prop){if(isBoolean(prop))return false;if(isRegExp(prop)&&new RegExp("").toString()==prop.toString())return true;if(isString(prop)||isNumber(prop))return!prop;if(Boolean(prop)&&false!=prop){for(var i in prop)if(prop.hasOwnProperty(i))return false}return true;}if('undefined'==typeof Object.hasOwnProperty){Object.prototype.hasOwnProperty=function(prop){return!('undefined'==typeof this[prop]||this.constructor&&this.constructor.prototype[prop]&&this[prop]===this.constructor.prototype[prop]);}}function hasFlash(version){var ver=0;try{if(navigator.plugins!=null&&navigator.plugins.length>0){ver=navigator.plugins["Shockwave Flash"].description.split(' ')[2].split('.')[0];}else{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");ver=axo.GetVariable("$version").split(' ')[1].split(',')[0];}}catch(e){}if(ver>=version)return true;return false;}function addEvent(element,type,handler){if(!handler.$$guid)handler.$$guid=addEvent.guid++;if(!element.events)element.events={};var handlers=element.events[type];if(!handlers){handlers=element.events[type]={};if(element["on"+type]){handlers[0]=element["on"+type];}}handlers[handler.$$guid]=handler;element["on"+type]=handleEvent;};addEvent.guid=1;function removeEvent(element,type,handler){if(element.events&&element.events[type]){delete element.events[type][handler.$$guid];}};function handleEvent(event){var returnValue=true;event=event||fixEvent(window.event);var handlers=this.events[event.type];for(var i in handlers){if(!handlers.hasOwnProperty(i))continue;this.$$handleEvent=handlers[i];if(this.$$handleEvent(event)===false){returnValue=false;}}return returnValue;};function fixEvent(event){event.preventDefault=fixEvent.preventDefault;event.stopPropagation=fixEvent.stopPropagation;event.target=event.srcElement;return event;};fixEvent.preventDefault=function(){this.returnValue=false;};fixEvent.stopPropagation=function(){this.cancelBubble=true;};window.fireoninit=function(){if(arguments.callee.done)return;arguments.callee.done=true;if(_timer){clearInterval(_timer);_timer=null;}if(typeof window.oninit=='function'){window.oninit();}};if(document.addEventListener){document.addEventListener("DOMContentLoaded",window.fireoninit,null);}/*@cc_on @*//*@if(@_win32)document.write("<\/script>");var script=document.getElementById("__ie_init");script.onreadystatechange=function(){if(this.readyState=="complete"){window.fireoninit();}};/*@end @*/if(/WebKit/i.test(navigator.userAgent)){var _timer=setInterval(function(){if(/loaded|complete/.test(document.readyState)){window.fireoninit();}},10);}window.onload=window.fireoninit;window.oninit=function(){};function addInitEvent(func){var oldoninit=window.oninit;if(typeof window.oninit!='function'){window.oninit=func;}else{window.oninit=function(){oldoninit();func();};}}function bind(fnc){var args=Array.prototype.slice.call(arguments,1);return function(){return fnc.apply(this,args);}}DokuCookie={data:Array(),name:'DOKU_PREFS',setValue:function(key,val){DokuCookie.init();DokuCookie.data[key]=val;var now=new Date();DokuCookie.fixDate(now);now.setTime(now.getTime()+365*24*60*60*1000);var text='';for(var key in DokuCookie.data){if(!DokuCookie.data.hasOwnProperty(key))continue;text+='#'+escape(key)+'#'+DokuCookie.data[key];}DokuCookie.setCookie(DokuCookie.name,text.substr(1),now,DOKU_BASE);},getValue:function(key){DokuCookie.init();return DokuCookie.data[key];},init:function(){if(DokuCookie.data.length)return;var text=DokuCookie.getCookie(DokuCookie.name);if(text){var parts=text.split('#');for(var i=0;i0){date.setTime(date.getTime()-skew);}}};var clientPC=navigator.userAgent.toLowerCase();var is_macos=navigator.appVersion.indexOf('Mac')!=-1;var is_gecko=((clientPC.indexOf('gecko')!=-1)&&(clientPC.indexOf('spoofer')==-1)&&(clientPC.indexOf('khtml')==-1)&&(clientPC.indexOf('netscape/7.0')==-1));var is_safari=((clientPC.indexOf('AppleWebKit')!=-1)&&(clientPC.indexOf('spoofer')==-1));var is_khtml=(navigator.vendor=='KDE'||(document.childNodes&&!document.all&&!navigator.taintEnabled));if(clientPC.indexOf('opera')!=-1){var is_opera=true;var is_opera_preseven=(window.opera&&!document.childNodes);var is_opera_seven=(window.opera&&document.childNodes);}function $(){var elements=new Array();for(var i=0;i');}function hideLoadBar(id){obj=$(id);if(obj)obj.style.display="none";}function addTocToggle(){if(!document.getElementById)return;var header=$('toc__header');if(!header)return;var toc=$('toc__inside');var obj=document.createElement('span');obj.id='toc__toggle';obj.style.cursor='pointer';if(toc&&toc.style.display=='none'){obj.innerHTML='+';obj.className='toc_open';}else{obj.innerHTML='';obj.className='toc_close';}prependChild(header,obj);obj.parentNode.onclick=toggleToc;try{obj.parentNode.style.cursor='pointer';obj.parentNode.style.cursor='hand';}catch(e){}}function toggleToc(){var toc=$('toc__inside');var obj=$('toc__toggle');if(toc.style.display=='none'){toc.style.display='';obj.innerHTML='';obj.className='toc_close';}else{toc.style.display='none';obj.innerHTML='+';obj.className='toc_open';}}function footnote(e){var obj=e.target;var id=obj.id.substr(5);var fndiv=$('insitu__fn');if(!fndiv){fndiv=document.createElement('div');fndiv.id='insitu__fn';fndiv.className='insitu-footnote JSpopup dokuwiki';addEvent(fndiv,'mouseout',function(e){if(e.target!=fndiv){e.stopPropagation();return;}if(e.pageX){var bx1=findPosX(fndiv);var bx2=bx1+fndiv.offsetWidth;var by1=findPosY(fndiv);var by2=by1+fndiv.offsetHeight;var x=e.pageX;var y=e.pageY;if(x>bx1&&xby1&&y0&&e.offsetX0&&e.offsetY.*<\/sup>/gi,'');content=content.replace(/^\s+(,\s+)+/,'');content=content.replace(/\bid=\"(.*?)\"/gi,'id="insitu__$1');fndiv.innerHTML=content;var x;var y;if(e.pageX){x=e.pageX;y=e.pageY;}else{x=e.offsetX;y=e.offsetY;}fndiv.style.position='absolute';fndiv.style.left=(x+2)+'px';fndiv.style.top=(y+2)+'px';fndiv.style.display='';}addInitEvent(function(){var elems=getElementsByClass('fn_top',null,'a');for(var i=0;i=2)input2.disabled=(input2.type=='checkbox'&&!input2.checked);else input2.disabled=(input2.type!='checkbox');}});input1.checked=false;}else if(input1.type=='submit'){input1.disabled=true;}}});addInitEvent(function(){var selector=$('action__selector');if(!selector)return;addEvent(selector,'change',function(e){this.form.submit();});$('action__selectorbtn').style.display='none';});function checkWindowsShares(){if(!LANG['nosmblinks'])return true;var elems=getElementsByClass('windows',document,'a');if(elems){for(var i=0;iloading...';listitem.appendChild(ul);listitem.className='open';}},this.throbber_delay);ajax.elementObj=ul;ajax.afterCompletion=function(){window.clearTimeout(timeout);index.treeattach(ul);if(listitem.className!='open'){if(!listitem.open){ul.style.display='none';}listitem.appendChild(ul);if(listitem.open){listitem.className='open';}}};ajax.runAJAX(clicky.search.substr(1)+'&call=index');e.preventDefault();return false;}};addInitEvent(function(){index.treeattach($('index__tree'));});var drag={obj:null,handle:null,oX:0,oY:0,eX:0,eY:0,attach:function(obj,handle){if(handle){handle.dragobject=obj;addEvent($(handle),'mousedown',drag.start);}else{addEvent($(obj),'mousedown',drag.start);}},start:function(e){drag.handle=e.target;if(drag.handle.dragobject){drag.obj=drag.handle.dragobject;}else{drag.obj=drag.handle;}drag.handle.className+=' ondrag';drag.obj.className+=' ondrag';drag.oX=parseInt(drag.obj.style.left);drag.oY=parseInt(drag.obj.style.top);drag.eX=drag.evX(e);drag.eY=drag.evY(e);addEvent(document,'mousemove',drag.drag);addEvent(document,'mouseup',drag.stop);e.preventDefault();e.stopPropagation();return false;},stop:function(){drag.handle.className=drag.handle.className.replace(/ ?ondrag/,'');drag.obj.className=drag.obj.className.replace(/ ?ondrag/,'');removeEvent(document,'mousemove',drag.drag);removeEvent(document,'mouseup',drag.stop);drag.obj=null;drag.handle=null;},drag:function(e){if(drag.obj){drag.obj.style.top=(drag.evY(e)+drag.oY-drag.eY+'px');drag.obj.style.left=(drag.evX(e)+drag.oX-drag.eX+'px');}},evX:function(e){return(e.pageX)?e.pageX:e.clientX+document.body.scrollTop;},evY:function(e){return(e.pageY)?e.pageY:e.clientY+document.body.scrollTop;}};function selection_class(){this.start=0;this.end=0;this.obj=null;this.rangeCopy=null;this.scroll=0;this.fix=0;this.getLength=function(){return this.end-this.start;};this.getText=function(){if(!this.obj)return'';return this.obj.value.substring(this.start,this.end);}}function getSelection(textArea){var sel=new selection_class();sel.obj=textArea;sel.start=textArea.value.length;sel.end=textArea.value.length;textArea.focus();if(document.getSelection){sel.start=textArea.selectionStart;sel.end=textArea.selectionEnd;sel.scroll=textArea.scrollTop;}else if(document.selection){sel.rangeCopy=document.selection.createRange().duplicate();var before_range=document.body.createTextRange();before_range.moveToElementText(textArea);before_range.setEndPoint("EndToStart",sel.rangeCopy);var before_finished=false,selection_finished=false;var before_text,selection_text;before_text=before_range.text;selection_text=sel.rangeCopy.text;sel.start=before_text.length;sel.end=sel.start+selection_text.length;do{if(!before_finished){if(before_range.compareEndPoints("StartToEnd",before_range)==0){before_finished=true;}else{before_range.moveEnd("character",-1);if(before_range.text==before_text){sel.start+=2;sel.end+=2;}else{before_finished=true;}}}if(!selection_finished){if(sel.rangeCopy.compareEndPoints("StartToEnd",sel.rangeCopy)==0){selection_finished=true;}else{sel.rangeCopy.moveEnd("character",-1);if(sel.rangeCopy.text==selection_text){sel.end+=2;}else{selection_finished=true;}}}}while((!before_finished||!selection_finished));var countNL=function(str){var m=str.split("\r\n");if(!m||!m.length)return 0;return m.length-1;};sel.fix=countNL(sel.obj.value.substring(0,sel.start));}return sel;}function setSelection(selection){if(document.getSelection){selection.obj.setSelectionRange(selection.start,selection.end);if(selection.scroll)selection.obj.scrollTop=selection.scroll;}else if(document.selection){selection.rangeCopy.collapse(true);selection.rangeCopy.moveStart('character',selection.start-selection.fix);selection.rangeCopy.moveEnd('character',selection.end-selection.start);selection.rangeCopy.select();}}function pasteText(selection,text,opts){if(!opts)opts={};selection.obj.value=selection.obj.value.substring(0,selection.start)+text+selection.obj.value.substring(selection.end,selection.obj.value.length);selection.end=selection.start+text.length;if(opts.startofs)selection.start+=opts.startofs;if(opts.endofs)selection.end-=opts.endofs;if(opts.nosel)selection.start=selection.end;setSelection(selection);}function insertTags(textAreaID,tagOpen,tagClose,sampleText){var txtarea=$(textAreaID);var selection=getSelection(txtarea);var text=selection.getText();var opts;if(text.charAt(text.length-1)==' '){selection.end--;text=selection.getText();}if(!text){text=sampleText;opts={startofs:tagOpen.length,endofs:tagClose.length};}else{opts={nosel:true};}text=tagOpen+text+tagClose;pasteText(selection,text,opts);}function insertAtCarret(textAreaID,text){var txtarea=$(textAreaID);var selection=getSelection(txtarea);pasteText(selection,text,{nosel:true});}var pickercounter=0;function initToolbar(tbid,edid,tb){var toolbar=$(tbid);if(!toolbar)return;var edit=$(edid);if(!edit)return;if(edit.readOnly)return;toolbar.innerHTML='';var cnt=tb.length;for(var i=0;i5)lvl=5;var tags='=';for(var i=0;i<=5-lvl;i++)tags+='=';insertTags(edid,tags+' ',' '+tags+"\n",props['text']);pickerClose();return false;}function addBtnActionPicker(btn,props,edid){var pickerid='picker'+(pickercounter++);createPicker(pickerid,props,edid);addEvent(btn,'click',function(){pickerToggle(pickerid,btn);return false;});return true;}function addBtnActionLinkwiz(btn,props,edid){linkwiz.init($(edid));addEvent(btn,'click',function(){linkwiz.toggle();return false;});return true;}function pickerToggle(pickerid,btn){var picker=$(pickerid);if(picker.style.marginLeft=='-10000px'){var x=findPosX(btn);var y=findPosY(btn);picker.style.left=(x+3)+'px';picker.style.top=(y+btn.offsetHeight+3)+'px';picker.style.marginLeft='0px';}else{picker.style.marginLeft='-10000px';}}function pickerClose(){var pobjs=getElementsByClass('picker');for(var i=0;i3){field.value=field.value.substr(0,linestart)+field.value.substr(linestart+2);selection.start=selection.start-2;selection.end=selection.start;}else{field.value=field.value.substr(0,linestart)+field.value.substr(selection.start);selection.start=linestart;selection.end=linestart;}setSelection(selection);e.preventDefault();return false;}}else if(e.keyCode==32){var match=search.match(/(\n +)([*-] )$/);if(match){field.value=field.value.substr(0,linestart)+' '+field.value.substr(linestart);selection.start=selection.start+2;selection.end=selection.start;setSelection(selection);e.preventDefault();return false;}}}addInitEvent(function(){var field=$('wiki__text');if(!field)return;addEvent(field,'keydown',keyHandler);});function currentHeadlineLevel(textboxId){var field=$(textboxId);var selection=getSelection(field);var search="\n"+field.value.substr(0,selection.start);var lasthl=search.lastIndexOf("\n==");if(lasthl==-1&&field.form.prefix){search=field.form.prefix.value;lasthl=search.lastIndexOf("\n==");}search=search.substr(lasthl+1,6);if(search=='======')return 1;if(search.substr(0,5)=='=====')return 2;if(search.substr(0,4)=='====')return 3;if(search.substr(0,3)=='===')return 4;if(search.substr(0,2)=='==')return 5;return 0;}var textChanged=false;function changeCheck(msg){if(textChanged){var ok=confirm(msg);if(ok){var dwform=$('dw__editform');if(dwform){var params='call=draftdel';params+='&id='+encodeURIComponent(dwform.elements.id.value);var sackobj=new sack(DOKU_BASE+'lib/exe/ajax.php');sackobj.AjaxFailedAlert='';sackobj.encodeURIString=false;sackobj.runAJAX(params);}}return ok;}else{return true;}}function initChangeCheck(msg){var edit_text=document.getElementById('wiki__text');if(!edit_text)return;if(edit_text.readOnly)return;if(!$('dw__editform'))return;var links=document.getElementsByTagName('a');for(var i=0;i30*1000){var params='call=lock&id='+encodeURIComponent(locktimer.pageid);if(locktimer.draft){var dwform=$('dw__editform');params+='&prefix='+encodeURIComponent(dwform.elements.prefix.value);params+='&wikitext='+encodeURIComponent(dwform.elements.wikitext.value);params+='&suffix='+encodeURIComponent(dwform.elements.suffix.value);params+='&date='+encodeURIComponent(dwform.elements.date.value);}locktimer.sack.runAJAX(params);locktimer.lasttime=now;}};locktimer.refreshed=function(){var data=this.response;var error=data.charAt(0);data=data.substring(1);$('draft__status').innerHTML=data;if(error!='1')return;locktimer.reset();};var linkwiz={wiz:null,entry:null,result:null,timer:null,sack:null,textArea:null,selected:-1,selection:null,init:function(textArea){linkwiz.sack=new sack(DOKU_BASE+'lib/exe/ajax.php');linkwiz.sack.AjaxFailedAlert='';linkwiz.sack.encodeURIString=false;linkwiz.wiz=document.createElement('div');linkwiz.wiz.id='link__wiz';linkwiz.wiz.className='picker';linkwiz.wiz.style.top=(findPosY(textArea)+20)+'px';linkwiz.wiz.style.left=(findPosX(textArea)+80)+'px';linkwiz.wiz.style.marginLeft='-10000px';linkwiz.wiz.innerHTML=''+'
'+LANG['linkto']+'
'+'';textArea.form.parentNode.appendChild(linkwiz.wiz);linkwiz.textArea=textArea;linkwiz.result=$('link__wiz_result');linkwiz.entry=$('link__wiz_entry');var obj;obj=$('link__wiz_close');obj.onclick=linkwiz.hide;linkwiz.sack.elementObj=linkwiz.result;addEvent(linkwiz.entry,'keyup',linkwiz.onEntry);addEvent(linkwiz.result,'click',linkwiz.onResultClick);drag.attach(linkwiz.wiz,$('link__wiz_header'));},onEntry:function(e){if(e.keyCode==37||e.keyCode==39){return true;}if(e.keyCode==27){linkwiz.hide();e.preventDefault();e.stopPropagation();return false;}if(e.keyCode==38){linkwiz.select(linkwiz.selected-1);e.preventDefault();e.stopPropagation();return false;}if(e.keyCode==40){linkwiz.select(linkwiz.selected+1);e.preventDefault();e.stopPropagation();return false;}if(e.keyCode==13){if(linkwiz.selected>-1){var obj=linkwiz.getResult(linkwiz.selected);if(obj){var a=obj.getElementsByTagName('A')[0];linkwiz.resultClick(a);}}else if(linkwiz.entry.value){linkwiz.insertLink(linkwiz.entry.value);}e.preventDefault();e.stopPropagation();return false;}linkwiz.autocomplete();},getResult:function(num){var obj;var childs=linkwiz.result.getElementsByTagName('DIV');obj=childs[num];if(obj){return obj;}else{return null;}},select:function(num){if(num<0){linkwiz.deselect();return;}var obj=linkwiz.getResult(num);if(obj){linkwiz.deselect();obj.className+=' selected';if(obj.offsetTop>linkwiz.result.scrollTop+linkwiz.result.clientHeight){linkwiz.result.scrollTop+=obj.clientHeight;}else if(obj.offsetTop-linkwiz.result.clientHeightlinkwiz.result.scrollTop+linkwiz.result.clientHeight)||(obj.offsetTop-1){var obj=linkwiz.getResult(linkwiz.selected);if(obj){obj.className=obj.className.replace(/ ?selected/,'');}}linkwiz.selected=-1;},onResultClick:function(e){if(e.target.tagName!='A')return;e.stopPropagation();e.preventDefault();linkwiz.resultClick(e.target);return false;},resultClick:function(a){var id=a.title;if(id==''||id.substr(id.length-1)==':'){linkwiz.entry.value=id;linkwiz.autocomplete_exec();}else{linkwiz.entry.value=id;if(a.nextSibling&&a.nextSibling.tagName=='SPAN'){linkwiz.insertLink(a.nextSibling.innerHTML);}else{linkwiz.insertLink('');}}},insertLink:function(title){if(!linkwiz.entry.value)return;var sel=getSelection(linkwiz.textArea);if(sel.start==0&&sel.end==0)sel=linkwiz.selection;var stxt=sel.getText();if(!stxt&&!DOKU_UHC)stxt=title;if(linkwiz.textArea.form['id'].value.indexOf(':')!=-1&&linkwiz.entry.value.indexOf(':')==-1){linkwiz.entry.value=':'+linkwiz.entry.value;}var link='[['+linkwiz.entry.value+'|';if(stxt)link+=stxt;link+=']]';var so=linkwiz.entry.value.length+3;var eo=2;pasteText(sel,link,{startofs:so,endofs:eo});linkwiz.hide();},autocomplete:function(){if(linkwiz.timer!==null){window.clearTimeout(linkwiz.timer);linkwiz.timer=null;}linkwiz.timer=window.setTimeout(linkwiz.autocomplete_exec,350);},autocomplete_exec:function(){linkwiz.deselect();linkwiz.result.innerHTML='';linkwiz.sack.runAJAX('call=linkwiz&q='+encodeURI(linkwiz.entry.value));},clear:function(){linkwiz.result.innerHTML='Search for a matching page name above, or browse through the pages on the right';linkwiz.entry.value='';},show:function(){linkwiz.selection=getSelection(linkwiz.textArea);linkwiz.wiz.style.marginLeft='0px';linkwiz.entry.focus();linkwiz.autocomplete();},hide:function(){linkwiz.wiz.style.marginLeft='-10000px';linkwiz.textArea.focus();},toggle:function(){if(linkwiz.wiz.style.marginLeft=='-10000px'){linkwiz.show();}else{linkwiz.hide();}}};var media_manager={keepopen:false,hide:false,treeattach:function(obj){if(!obj)return;var items=obj.getElementsByTagName('li');for(var i=0;i';ajax.elementObj=content;ajax.afterCompletion=function(){media_manager.selectorattach(content);media_manager.confirmattach(content);media_manager.updatehide();};ajax.runAJAX(link.search.substr(1)+'&call=mediasearchlist');return false;},togglekeepopen:function(event,cb){if(cb.checked){DokuCookie.setValue('keepopen',1);media_manager.keepopen=true;}else{DokuCookie.setValue('keepopen','');media_manager.keepopen=false;}},togglehide:function(event,cb){if(cb.checked){DokuCookie.setValue('hide',1);media_manager.hide=true;}else{DokuCookie.setValue('hide','');media_manager.hide=false;}media_manager.updatehide();},updatehide:function(){var obj=$('media__content');if(!obj)return;var details=getElementsByClass('detail',obj,'div');for(var i=0;i';ajax.elementObj=content;ajax.afterCompletion=function(){media_manager.selectorattach(content);media_manager.confirmattach(content);media_manager.updatehide();media_manager.initFlashUpload();};ajax.runAJAX(link.search.substr(1)+'&call=medialist');return false;},toggle:function(event,clicky){var listitem=clicky.parentNode;var sublists=listitem.getElementsByTagName('ul');if(sublists.length){listitem.removeChild(sublists[0]);clicky.src=DOKU_BASE+'lib/images/plus.gif';return false;}var link=listitem.getElementsByTagName('a')[0];var ajax=new sack(DOKU_BASE+'lib/exe/ajax.php');ajax.AjaxFailedAlert='';ajax.encodeURIString=false;if(ajax.failed)return true;var ul=document.createElement('ul');listitem.appendChild(ul);ajax.elementObj=ul;ajax.afterCompletion=function(){media_manager.treeattach(ul);};ajax.runAJAX(link.search.substr(1)+'&call=medians');clicky.src=DOKU_BASE+'lib/images/minus.gif';return false;},suggest:function(){var file=$('upload__file');var name=$('upload__name');if(!file||!name)return;var text=file.value;text=text.substr(text.lastIndexOf('/')+1);text=text.substr(text.lastIndexOf('\\')+1);name.value=text;},initFlashUpload:function(){if(!hasFlash(8))return;var oform=$('dw__upload');var oflash=$('dw__flashupload');if(!oform||!oflash)return;var clicky=document.createElement('img');clicky.src=DOKU_BASE+'lib/images/multiupload.png';clicky.title=LANG['mu_btn'];clicky.alt=LANG['mu_btn'];clicky.style.cursor='pointer';clicky.onclick=function(){oform.style.display='none';oflash.style.display='';};oform.appendChild(clicky);}};addInitEvent(function(){media_manager.treeattach($('media__tree'));media_manager.selectorattach($('media__content'));media_manager.confirmattach($('media__content'));media_manager.attachoptions($('media__opts'));media_manager.initFlashUpload();});function usrmgr_delconfirm(){if($('usrmgr__del')){addEvent($('usrmgr__del'),'click',function(){return confirm(reallyDel);});}};addInitEvent(usrmgr_delconfirm);addInitEvent(function(){var btns=getElementsByClass('btn_incledit',document,'form');for(var i=0;i/g,">");return str;},treetoggle:function(clicky){var listitem=clicky.parentNode.parentNode;var sublists=listitem.getElementsByTagName('ul');if(sublists.length){listitem.removeChild(sublists[0]);clicky.src=DOKU_BASE+'lib/images/plus.gif';clicky.alt='+';return false;}var link=listitem.getElementsByTagName('a')[0];var ajax=new sack(DOKU_BASE+'lib/plugins/acl/ajax.php');ajax.AjaxFailedAlert='';ajax.encodeURIString=false;if(ajax.failed)return true;var ul=document.createElement('ul');listitem.appendChild(ul);ajax.elementObj=ul;ajax.runAJAX(link.search.substr(1)+'&ajax=tree');clicky.src=DOKU_BASE+'lib/images/minus.gif';return false;},treehandler:function(e){if(e.target.src){acl.treetoggle(e.target);}else if(e.target.href){var obj=getElementsByClass('cur',$('acl__tree'),'a');for(var i=0;i-1){frm.elements['ns'].value='';frm.elements['id'].value=acl.hsc(acl.parseatt(e.target.search)['id']);}else if(e.target.className.search(/idx_dir/)>-1){frm.elements['ns'].value=acl.hsc(acl.parseatt(e.target.search)['ns']);frm.elements['id'].value='';}acl.loadinfo();}e.stopPropagation();e.preventDefault();return false;}};addInitEvent(acl.init);addInitEvent(function(){ajax_qsearch.init('qsearch__in','qsearch__out');});addInitEvent(function(){addEvent(document,'click',closePopups);});addInitEvent(function(){addTocToggle();});addInitEvent(function(){initSizeCtl('size__ctl','wiki__text');});addInitEvent(function(){initToolbar('tool__bar','wiki__text',toolbar);});addInitEvent(function(){initChangeCheck('Jsou tu neuložené změny, které budou ztraceny.\nChcete opravdu pokračovat?');});addInitEvent(function(){locktimer.init(840,'Váš zámek pro editaci za chvíli vyprší.\nAbyste předešli konfliktům, stiskněte tlačítko Náhled a zámek se prodlouží.',1);});addInitEvent(function(){scrollToMarker();});addInitEvent(function(){focusMarker();}); diff --git a/c/skripta/compilation/jazyk_c compilation_files/todo.gif b/c/skripta/compilation/jazyk_c compilation_files/todo.gif new file mode 100755 index 0000000000000000000000000000000000000000..6740360857f969d20ac01be669a833edda8d6324 GIT binary patch literal 1335 zcmeH`{WBW|7{|X65$Q`LURF2N1{={c%Z}x|^jf_VFFnqzFXnASXWFgZwK_Fj=QYKZ z%W02GsV3E~v2lG_?bK%GC5o+9%nWO_7$S(5%&>}Qu|Hsc!Jhlv=bj(FKRwTV1A`@A z-toS$z%n+5$z+%^!7>Gl#V})mZ3c5TcwF$gu(W_B4?AAQPCE$f;IJJ6dpOv`aVJDV zczeLd6Rs}2P(MTj;$Sdh!w|He_uf0~52NvM3{J-3Y$DQ=kdlmmfB*t=K0*Fzlzawx z21=xm=b=uHx-v`}sX+H_wAOMp*DE2& z2DN}%VQ2%XLG4)T0(F2oK|f;kG3XJf3kKt23_r%)AgCME14A#!NFV4|82Uj*euH5E zG=TL%to;re0vY`T^b|CVi8kJgF&IWb&p}3yg2u4+2gt|-XcD9WO@Xwa>CH5~g{CcN znol#9G_##%clM}7nogniCokPIG0h4{=Sn(v(!EYP5zTqgoDa?IuB{2wc1dXA04;>m z;vrg$Bz*$ukCHx#{yalVXKCpiEuA+kU7+PcT9(mr39VeAl`_q!gV$VX!?#_;G z#jP_M&sX_%?)LIj{lm5c#x`sd=Y-wj-Jay^D{)|WBSdUMO#>J)a2`4=y zY7v#gCODbqrM?;5?{9^gvQKp9E{wh}*%x-nl2K`O&Yhz!$hwhr#Ws|KT@er# z%hUAC0+}j2&g7JIQ*!dV^}RO*&JyX&x|(a1GSC8BI;t&NS$>SgtwTS^ z{Pr*}h>isH_*+F-n|3;8HD$@SHTFy>b41>eKwJzX6SV=FHtu|nc*G_yCa9ckpXMOt z3%PIc9P;P+(bCXZ{#dGKlsSsHXkzB^KVtuq>IP+Vs<$p}DAgvtc+}zzx1^38`6YoZ zsVTwtDoVt?wk8l>MJ8v@aHN{WYPkEfH1_jj<1)!wCX;)-C^OGKzsp8h`1WwUGY*G1 zNZIBBWGlpRUX0D>of%ci$gfv(w!T(nQ*3);U{H1Kh<4DWw9G933q^T)`c%Q*2Lji9 nPJQ7{D#htC*P@ql`_oi4)&0WOAl~(%?%NH2rE6Un4EX*7P}Sc0 literal 0 HcmV?d00001 diff --git a/c/skripta/start.txt b/c/skripta/start.txt new file mode 100755 index 0000000..f587422 --- /dev/null +++ b/c/skripta/start.txt @@ -0,0 +1,56 @@ + _ _ ____ + | | __ _ _____ _| | __ / ___| + _ | |/ _` |_ / | | | |/ / | | + | |_| | (_| |/ /| |_| | < | |___ + \___/ \__,_/___|\__, |_|\_\ \____| + |___/ + + + Jazyk C + Základy praktického programování + + V Praze 2oo7 pro SSPŠ + Tomáš Harvie Mudruňka a kolektiv + +TODO mergnout adresare c a sbirka do wiki... + +====== Předmluva ====== +Tento text vznikl puvodne jako skripta pro Smíchovskou Střední Průmyslovou Školu, nyní ho v jeho vlastním zájmu chci publikovat na wiki, kde je volně k použití i k editaci... + +Skripta si nekladou za cil byt dokonalou referencni priruckou, ani wiki o jazyce C, ucelem je vytvorit ucebni texty pro jednotlive lekce kurzu programovani v jazyce C v rozsahu stravitelnem studenty stredni skoly. + +**Se skripty v celém rozsahu můžete zatím nakládat v souladu s licencí +[[http://creativecommons.org/licenses/by-nc-sa/3.0/cz/|Creative Commons: Uveďte autora-Neužívejte dílo komerčně-Zachovejte licenci 3.0 Česko]]** + +Kromě plaintextové verze mám v plánu text vyexportovat také do následujících formátů + * PDF + * HTML + * nroff (manuálové stránky) + +//~~Tomáš Mudruňka~~// +====== Rozpis lekcí ====== + + + - [[c_00|Co bychom měli znát...]] + - [[c_01|Předmluva, Něco málo o C]] + - [[c_02|Hello World!]] + - [[c_03|Proměnné, printf()]] + - [[c_04|Výhody a nevýhody programování textových aplikací (Agitační materiál ;)]] + - [[c_05|Konstanty]] + - [[c_06|Základní operátory]] + - [[c_07|Standartní vstup a výstup]] + - [[c_08|Podmínky a cykly]] + - [[c_09|Statická pole]] + - [[c_10|Argumenty programu]] + - [[c_11|Preprocesor]] + - [[c_12|Funkce - úvod]] + - [[c_13|Funkce - pokračování, Globální proměnné]] + - [[c_14|Pointery]] + - [[c_15|Dynamická alokace paměti]] + - [[c_16|Dynamická pole]] + - [[c_17|Některé funkce OS]] + - [[c_18|Práce se soubory]] + - [[c_19|Napojení C na další systémy]] + - [[c_20|Zadání samostatné práce]] ->možno využít při suplování<- + - [[c_98|Odborné a slangové pojmy, Prameny]] + -- 2.30.2