Jazyk C

Transkript

Jazyk C
Jazyk C
středa 8:50 A3
úterý 14:20 HI3
Úvodní strana
Titulní strana
Obsah
Petr Kolář
místnost A-10
tel: +420-485 353 673
e-mail:
[email protected]
WWW: http://www.kai.vslib.cz/~kolar/cecko/
Pracovní verze!
JJ
II
J
I
Strana 1 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Literatura
• Herout, P.: Učebnice jazyka C, III upravené vydání. Kopp, České Budějovice 1994. ISBN 80-85828-21-9. – doporučeno
• Kernighan, B. W. – Ritchie, D. M.: The C Programming Language. Second Edition. Prentice Hall 1988. ISBN 0-13-110362-8, K&R – klasická
učebnice, která ovšem popisuje dnes již zastaralou „normuÿ jazyka
Úvodní strana
• Kernighan, B. W. – Ritchie, D. M.: Programovací jazyk C. SNTL – Alfa,
Bratislava 1988 – slovenský překlad prvního vydání předchozího titulu
Obsah
Titulní strana
JJ
II
J
I
Strana 2 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Překladače jazyka C
Kompletní profesionální vývojové prostředí pro jazyk C mívá cenu desítek
tisíc Kč.
Úvodní strana
Existuje však řada volně dostupných překladačů a jednoduchých vývojových
prostředí, které jsou pro výuku plně dostačující:
V OS Linux je vývojové prostředí s gcc, gdb, součástí prakticky všech distribucí.
Pro Windows:
DJGPP http://www.delorie.com/djgpp/ – kompletní aktuální vývojové prostředí (ovšem s uživatelským rozhraním poplatným MS-DOSu a roku 1990).
Archivy zabírají asi 20 MB (nebo více podle množství použitých balíků). Výběr souborů se provádí pomocí ZIP Picker. V Čechách zrcadleno na serveru
ftp://ftp.zcu.cz/pub/win/simtelnet/gnu/djgpp/.
Borland Museum: http://community.borland.com/museum/ – starší verze integrovaného prostředí s překladačem C od firmy Borland. Turbo C++ verze
1.01 (2,7 MB) nebo Turbo C verze 2.01 (1,1 MB).
Titulní strana
Obsah
JJ
II
J
I
Strana 3 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Srovnání jazyků Pascal a C
C
pro praktické programování
původním „standardemÿ je
kniha K&R, standardy
z let 1989-90 a 1999
„language of choiceÿ
modulární programování
(oddělená kompilace)
objektová rozšíření C++,
Objective C, C#
rozsáhlé standardní knihovny
jsou volnou součástí jazyka,
množství dalších knihoven
Pascal
pro výuku
od počátku existence standardu
jazyka, je však příliš omezující
→ rozšíření
„language of bondage and disciplineÿ
modulární programování
v rozšířeních
objektové rozšíření Turbo
Pascal, Delphi
standardní funkce jsou
nedílnou součástí jazyka
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 4 z 89
Zpět
Celá obrazovka
Zavřít
#include <stdio.h>
Konec
int main()
{
printf("Hello, world!\n");
return 0;
}
program Hello(Output);
begin
Writeln(’Hello, world!’);
end.
Proč jazyk C?
C je univerzální programovací jazyk.
Proč jazyk C stojí za pozornost mezi desítkami jiných univerzálních programovacích jazyků? Jedná se o jazyk pro opravdové programování. Niklaus Wirth,
autor jazyka Pascal, věnoval značné úsilí, aby jeho jazyk, určený pro výuku
programování, byl co možná nejbezpečnější, aby bylo obtížné v něm programovat ošklivě. Popularita jaké Pascal dosáhl, svědčí o tom, že Wirth vytvořil
něco lepšího, než o co usiloval. Nicméně něco je možné napsat ve standardním
Pascalu jen s velkým úsilím, něco vůbec ne. Obhájci Pascalu se chlubí, že
Pascal má od začátku závaznou normu, ale neprogramují v ní. Množství vzájemně nekompatibilních rozšíření (nejvýznamnější z nich je asi Turbo Pascal)
svědčí o tom, že standardnímu Pascalu mnoho užitečných rysů chybí.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 5 z 89
Zpět
Jazyk C prošel několikaletým vývojem, kdy se skutečně používal i na věci
nesnadné a komplikované (přenos operačního systému Unix na počítače několika značně odlišných typů). Během vývoje byl doplněn o vlastnosti, které
se ukázaly jako užitečné (např. prototypy funkcí), a naopak některé vlastnosti matoucí, zbytečně složité nebo zbytečné byly odstraněny. Důležitými
mezníky vývoje jazyka C bylo vydání jeho standardů – ANSI X3.159-1989,
ANSI/ISO/IEC 9899:1990 a ISO/IEC 9899:1999.
Jazyk C vytvořili programátoři pro programátory. Díky tomu neobsahuje podobné přehmaty jako parametry procedur volané jménem z jazyka Algol 60
Celá obrazovka
Zavřít
Konec
– vlastnost, která se obtížně implementuje, nepříliš efektivně překládá a přitom je možné ji nahradit něčím mnohem čistším a průhlednějším (parametry
volanými referencí), nebo „návaznostÿ souborů na operační systém pomocí
parametrů programu v Pascalu.
Způsob zápisu algoritmů v jazyce C je velice podobný zápisu v jazycích Algol,
Pascal, Basic, PL/I, Modula–2, Ada, což tyto jazyky favorizuje před jazyky
s méně obvyklou syntaxí (Fortran, Cobol, Forth, Perl, . . . ). Syntaxe jazyka
C umožňuje stručné vyjádření algoritmu a navíc často naznačuje překladači
možnost optimalizace.
Jazyk C umožňuje oddělený překlad jednotlivých částí programu, používání a
vytváření knihoven. Díky tomu je možné jej používat i na rozsáhlé projekty
a pro týmovou práci.
Jazyk C nepokutuje programátora za použití některých svých vlastností (číselná návěští v Pascalu s nutností je předem deklarovat, logické spojky and
a or v Pascalu s povinným vyhodnocením obou operandů), ani nenabízí
„mocnéÿ konstrukce, které je snadné použít, ale které vedou ke komplexním
operacím a k udivení nad pomalým během programu. Většinu příkazů jazyka
je možné přeložit jednou nebo několika málo strojovými instrukcemi.
Jazyk C je relativně jednoduchý. Nejedná se o ohromné monstrum, jakým je
například jazyk PL/I (O) nebo dokonce Ada, pro kterou několik let neexistoval překladač. Nejedná se ani o jazyk, na který si činí vlastnické právo některá
firma či jiná organizace. Jazyk C je k dispozici na většině platforem, od jed-
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 6 z 89
Zpět
Celá obrazovka
Zavřít
Konec
nočipových mikropočítačů (překladače pro ně samozřejmě pracují na větších
strojích – jedná se o tzv. křížové překladače; cross compilers), přes domácí a
osobní počítače, pracovní stanice, střediskové počítače až k superpočítačům.
Nejrozšířenější operační systémy (DOS a UNIX) jsou napsány jazyce C.
Jazyk C nenutí programátora použít jediný správný přístup; tentýž algoritmus
je možné zapsat s použitím různých prostředků a do různé míry zhuštěně. C je
typickým jazykem volby.
Programování v jazyce C však přináší i některá nebezpečí. Některé konstrukce
mohou různé překladače chápat odlišně – speciálně se to týká datových typů
– rozsah stejně pojmenovaných celočíselných typů je v různých prostředích
různý. Také reprezentace složených typů může být v programech vytvořených
různými překladači různá, což může způsobovat chyby při výměně souborů
nebo síťové komunikaci. Téměř žádný překladač nehlídá přetečení rozsahu
číselných hodnot. U funkcí s proměnným počtem parametrů se typy těchto
parametrů nekontrolují. Při práci s řetězci a ukazateli se lze snadno dopustit
chyb, které překladač neodhalí. Standardní knihovna obsahuje funkce, jejichž
používání je nebezpečné (gets). Některé konstrukce může překladač chápat
díky opomenutí programátora jinak, než byly zamýšleny. Mezi časté chyby
patří například použití operátoru = namísto == pro porovnávání, zapomenutí
příkazu break na konci větve uvnitř switch, neuvedení hlavičkového souboru
pro použité funkce, chybné používání ukazatelů a nesprávné sestavení programu.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 7 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Lexikální symboly
Stejně jako jsou základním stavebním kamenem přirozeného jazyka slova, ze
kterých se skládají věty, základním stavebním kamenem programu v jazyce C
jsou lexikální symboly, ze kterých se skládají příkazy, definice a deklarace:
čeština
slovo
věta, odstavec
text
jazyk C
lexikální symbol
příkaz, deklarace, definice
kompilační jednotka
Jazyk C rozlišuje šest tříd lexikálních symbolů:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 8 z 89
• Identifikátory
• Klíčová slova
• Konstanty
Zpět
Celá obrazovka
• Řetězce
Zavřít
• Operátory
Konec
• Ostatní oddělovače
Identifikátory
Identifikátory – začínají písmenem nebo znakem podtržítko (_) a obsahují alfanumerické znaky, tj. písmena, číslice a znaky podtržítko; nepoužívejte identifikátory začínající podtržítkem, pokud nevíte, co děláte.
Úvodní strana
Titulní strana
Klíčová slova
Klíčová slova – několik desítek vybraných slov, které mají speciální význam
v programu v jazyce C.
Obsah
JJ
II
J
I
Strana 9 z 89
Konstanty
Zpět
V jazyce C lze používat celočíselné, reálné a znakové konstanty. Řetězcové
konstanty jsou považovány za zvláštní druh lexikálních symbolů.
Celá obrazovka
Zavřít
Celočíselné mohou být zapsány v desítkové, osmičkové nebo šestnáctkové soustavě; reálné pouze v desítkové soustavě.
Konec
Celočíselné konstanty
Celočíselné konstanty začínají vždy číslicí.
• konstanta, která začíná 0x nebo 0X, je zapsána v šestnáctkové soustavě,
skládá se z číslic a písmen a až f nebo A až F, které reprezentují číslice
10 až 15
Úvodní strana
• pokud konstanta začíná 0, je zapsána v osmičkové soustavě, a může
obsahovat pouze číslice 0 až 7
Obsah
• pokud konstanta začíná jinou číslicí než 0, je v desítkové soustavě
Pokud konstanta přesahuje největší číslo typu int, je typu long; jinak je typu
int.
Celočíselné konstanty mohou být (bez ohledu na to, v jaké jsou zapsány číselné
soustavě) zakončeny znaky U, L, UL, LL, nebo ULL, které stanovují, že se číslo má
považovat za konstantu typu unsigned, long, unsigned long, long long,
resp. unsigned long long. Toto zakončení lze psát i malými písmeny, ovšem
malé l se snadno plete s číslici 1.
Titulní strana
JJ
II
J
I
Strana 10 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Reálné konstanty
Reálné konstanty vyhovují následujícímu syntaktickému diagramu:
To znamená, že reálné konstanty začínají číslicí nebo desetinnou tečkou a
musí být zapsány v desítkové soustavě; skládají se z mantisy a nepovinného
exponentu; mantisa obsahuje aspoň jednu číslici a nejvýše jednu desetinnou
tečku, exponent je uveden znakem e nebo E, za kterým může být znaménko +
nebo - a alespoň jedna číslice; reálná konstanta může být zakončena znakem
f nebo F, která zajistí, že konstanta bude typu float a nikoli typu double.
Příklady reálných konstant: 1.0, 0., .5, -12.345e27.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 11 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Znakové konstanty
Libovolný tisknutelný znak (včetně mezery) s výjimkou znaku apostrof mezi
znaky apostrof: ’ ’, ’\"’, ’A’, ’6’. Nebo escape posloupnost mezi znaky
apostrof:
\n
\11
\n
\r
\t
\b
\f
\\
\’
\"
kód řídícího znaku v osm.soust bez 0
znak s kódem 9 (v kódu ASCII znak TAB)
znak konce řádku (newline)
návrat vozíku (carriage return)
tabelátor (tab)
backspace (o znak zpět)
form feed (přechod na novou stránku)
znak \
znak ’
znak "
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 12 z 89
Zpět
Celá obrazovka
Znakové konstanty jsou typu char.
Zavřít
Konec
Řetězce
Řetězec je posloupnost (může být i prázdná) tisknutelných znaků různých od
znaku uvozovky (") a escape posloupností jako u konstant typu char uzavřená
mezi znaky uvozovky:
Úvodní strana
"Ahoj", "\"", "\r\n"
Titulní strana
Dlouhé řetězce lze na libovolném místě rozdělit znakem uvozovky, odřádkováním, libovolným počtem mezer a dalšími uvozovkami.
Řetězce se chovají jako pole znaků s paměťovou třídou static. Překladač vyhradí v paměti tolik bytů, kolik znaků nebo escape posloupností obsahuje
řetězec, plus jeden navíc a do každého bytu uloží jeden znak (nebo hodnotu
zadanou escape posloupností) a na konec přidá znak ’\0’. Většina řetězcových funkcí pracuje s těmito řetězci zakončenými znakem s kódem 0, řetězec
sám proto znak s kódem 0 nesmí obsahovat, funkce by jej považovaly za konec
řetězce.
Obsah
JJ
II
J
I
Strana 13 z 89
Zpět
Celá obrazovka
Zavřít
Operátory
Operátory jsou tvořeny jedním nebo více nealfanumerickými znaky. Kromě
notoricky známých operátorů +, -, *, /, <, >, <=, >= a ( ) obsahuje jazyk další
více či méně exotické operátory:
Konec
Prior.
1
1
1
2
2
2
2
2
Operátor
( )
[ ]
-> .
! ~
+ ++ -&
*
Vyhodn.
−→
Oper.
−
−→
−→
←−
←−
←−
2
2
1
1
1
←−
←−
1
1
* / %
←−
←−
−→
1
1
2
+ << >>
< <= > >=
== !=
&
^
|
&&
||
−→
−→
−→
−→
−→
−→
−→
−→
−→
2
2
2
2
2
2
2
2
2
2
3
4
(type)
5
6
7
8
9
10
11
12
13
sizeof
Význam
pořadí vyhodnocování, parametry funkce
přístup k prvku pole
přístup k položce záznamu
logická negace, bitová negace
unární plus, unární minus
inkrement (+1), dekrement
(−1)
ukazatel na objekt
objekt, na který ukazatel ukazuje
změna typu
velikost objektu v bytech
násobení, dělení, zbytek po
dělení
sčítání, odčítání
bitový posun vlevo, vpravo
porovnání
je rovno, není rovno
bitové and
bitové xor
bitové or
logické and
logické or
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 14 z 89
Zpět
Celá obrazovka
Zavřít
Konec
14
15
15
? :
= *= /=
%= += -=
←−
←−
←−
3
2
2
15
15
16
&= ^= |=
<<= >>=
,
←−
←−
−→
2
2
2
podmíněný výraz
přiřazení, znásobení, vydělení
zbytek po dělení, přičtení,
odečtení
bitové and, xor, or
posunutí doleva, doprava
vyhodnotit zleva doprava, použít poslední výsledek
Úvodní strana
Titulní strana
Obsah
Slouží pro jednotlivé operace (například + pro sčítání, - pro odčítání, = pro
přiřazení hodnoty, == pro test na rovnost, -> pro přístup k položce záznamu,
na který ukazuje ukazatel, [ ] pro přístup k prvku pole a podobně)
JJ
II
J
I
Strana 15 z 89
Ostatní oddělovače
Ostatní oddělovače – symboly používané zejména pro oddělování příkazů jako
{, }, ;, apod.
Zpět
Celá obrazovka
Zavřít
Konec
Bílé znaky
Překladač při zpracování programu rozděluje vstupní text na lexikální symboly tak, že vždy načítá co nejdelší posloupnost znaků, která může být lexikálním symbolem. Příkaz a4=210*297; je možné psát bez mezer, protože
se v něm střídají identifikátory a konstanty složené z alfanumerických znaků
s operátory a oddělovači z nealfanumerických znaků.
Jméno typu int a identifikátor main však musí být odděleny alespoň jedním
znakem mezera, tabelátor nebo znak konce řádku (tzv. bílé znaky), protože
jinak by je překladač považoval za identifikátor intmain. Mezi libovolné dva
lexikální symboly je možné napsat jakýkoli počet bílých znaků pro zpřehlednění programu.
Úvodní strana
Titulní strana
Obsah
Direktivy preprocesoru
Zvláštní pravidla platí pro direktivy preprocesoru, které začínají znakem křížek (#) a jménem direktivy, a musí být na samostatném řádku. Jedná se
zejména o příkazy pro vkládání souborů
#include <soubor.h>
#include "soubor.h"
pro definice konstant a maker
#define JMENO hodnota
#define makro(p1) ((p1)*(p1))
a pro podmíněný překlad
#ifdef JMENO
#if výraz
#else
#endif.
JJ
II
J
I
Strana 16 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Komentáře
Součástí bílých míst oddělujících lexikální symboly mohou být i komentáře.
Tradiční komentáře v jazyce C začínají dvojicí znaků /*, končí dvojicí */ a
není je možné vnořovat.
Většina novějších překladačů umí pracovat i s komentáři používanými v jazyce
C++, které začínají dvojicí znaků // a končí s koncem řádku.
Úvodní strana
Titulní strana
Obsah
Protože není možné komentáře vnořovat, je problém s vykomentováváním
částí programu – pokud bychom použili standardní komentář mezi /* a */
a vykomentovaná část programu by obsahovala také komentáře, překladač
by první dvojici znaků */ pochopil jako konec komentáře a další text by se
pokoušel překládat. V takovém případě je možné pro vykomentovávání částí
programu používat direktivu preprocesoru pro podmíněný překlad – například
takto:
JJ
II
J
I
Strana 17 z 89
Zpět
Celá obrazovka
#ifdef 0
... vykomentovaná část programu
/* může obsahovat komentáře, ale nesmí obsahovat
* křížící se direktivy preprocesoru #if, #else, #endif */
#endif
Zavřít
Konec
Výraz, kterým se přiřazuje do proměnné a4 součin čísel 210 a 297 je možné
psát
a4 = 210 * 297 ;
ale i
a4=210*297;
Úvodní strana
nebo
a4
=
Titulní strana
210
Obsah
*
297
;
JJ
II
J
I
Strana 18 z 89
Zpět
Celá obrazovka
Zavřít
Konec
První program
Snad každá kniha o jazyce C začíná ukázkou jednoduchého programu v tomto
jazyce – programu, který vypíše na obrazovku nápis Hello, world! a odřádkuje. Zde je tento program:
Úvodní strana
Titulní strana
#include <stdio.h>
Obsah
main()
{
printf("Hello, world!\n");
}
JJ
II
J
I
Strana 19 z 89
Jazyk C prošel od svého vzniku určitým vývojem, takže novější překladače
budou pravděpodobně vypisovat při překladu uvedeného programu varování.
Text programu upravený podle současných standardů vypadá takto:
Zpět
Celá obrazovka
Zavřít
#include <stdio.h>
int main()
{
printf("Hello, world!\n");
return 0;
}
Konec
Jazyk C používá volný formát zápisu, který programátorovi umožňuje různými
způsoby formátovat zdrojový text. Program by bylo možné zapsat kompaktněji takto:
#include <stdio.h>
int main(){printf("Hello, world!\n");return 0;}
Text #include <stdio.h>, stejně jako další příkazy začínající znakem # musí
být na samostatném řádku; jedná se o direktivy preprocesoru, pro které platí
zvláštní pravidla. Ze zbývajícího textu bylo možné odstranit většinu mezer
a odřádkování (kromě mezery mezi slovy int a main, která by bez mezery
splynula v jedno slovo intmain). Výsledný zápis je ale méně přehledný než
předešlý, takže je lépe se takovémuto „šetřeníÿ vyhýbat.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 20 z 89
Zpět
Na programu je vidět několik podstatných rysů:
Celá obrazovka
• Procedura printf není součástí jazyka, ale patří do standardní knihovny.
Aby ji bylo možné použít, musí být do programu pomocí direktivy preprocesoru #include vložen hlavičkový soubor obsahující mj. deklaraci
funkce printf.
• Hlavní program je funkce se jménem main.
• Za jménem funkce se vždy píší závorky (i když jsou prázdné).
Zavřít
Konec
• Pro tisk na standardní výstup (normálně na obrazovku, ale je možné
přesměrovat), se používá procedura printf.
• Odřádkování se zajistí vložením posloupnosti \n do tisknutého řetězce.
• Pro ohraničení bloku slouží složené závorky { a }, a nikoli příkazy begin
a end.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 21 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Jednoduché typy
Ve standardu jazyka C jsou následující typy: char, unsigned char, signed
char, short, unsigned short, int, unsigned, long, unsigned long, float
a double.
Úvodní strana
Titulní strana
Celočíselné typy
typ
signed char
unsigned char
short
unsigned short
int
unsigned
long
unsigned long
long long
unsigned long long
Obsah
rozsah
SCHAR_MIN až SCHAR_MAX
0 až UCHAR_MAX
SHRT_MIN až SHRT_MAX
0 až USHRT_MAX
INT_MIN až INT_MAX
0 až UINT_MAX
LONG_MIN až LONG_MAX
0 až ULONG_MAX
LLONG_MIN až LLONG_MAX
0 až ULLONG_MAX
obvyklý rozsah
-128 až 127
0 až 255
-32768 až 32767
0 až 65536
jako long nebo short
JJ
II
J
I
Strana 22 z 89
Zpět
Celá obrazovka
-2147483648 až 2147483647
0 až 4294967296
Zavřít
Konec
Reálné typy
typ
float
double
long double
přesnost
7 desítkových číslic
15 desítkových číslic
19 desítkových číslic
rozsah
±1.1755 × 10−38 .. ± 3.4028 × 1038
±2.2251 × 10−308 .. ± 1.7976 × 10308
±3.3622 × 10−4932 .. ± 1.1897 × 104932
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 23 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Standardní aritmetické konverze
Při množství číselných typů je stanoveno, že při vyhodnocování aritmetického
výrazu se automaticky provádějí následující standardní konverze (tento postup přesně platí pro binární operátory +, -, * a /, u ostatních operátorů je
poněkud modifikován):
Úvodní strana
Titulní strana
1. hodnoty typu signed char a short se převedou na typ int a
2. hodnoty typu unsigned char a unsigned short se převedou na typ
unsigned; potom
3. je-li jeden z operandů typu long double, převede se druhý na tento typ
a provede se operace pro tento typ
4. jinak je-li jeden z operandů typu double, převede se druhý na tento typ
a provede se operace pro tento typ
5. jinak je-li jeden z operandů typu float, převede se druhý na tento typ
a provede se operace pro tento typ
6. jinak je-li jeden z operandů typu unsigned long, převede se druhý na
tento typ a provede se operace pro tento typ
7. jinak je-li jeden z operandů typu long, převede se druhý na tento typ a
provede se operace pro tento typ
8. jinak je-li jeden z operandů typu unsigned, převede se druhý na tento
typ a provede se operace pro tento typ
Obsah
JJ
II
J
I
Strana 24 z 89
Zpět
Celá obrazovka
Zavřít
Konec
9. jinak musí být oba operandy typu int, a provede se operace pro tento
typ
V normě podle K&R se navíc převáděly všechny hodnoty typu float na typ
double.
Kromě těchto implicitně prováděných konverzí lze konverzi vynutit operátorem změny typu: ( typ ) výraz. Příklad je v kapitole „Výpočty s celými
číslyÿ.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 25 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Výpočty s celými čísly
• Každý celočíselný typ reprezentuje omezený interval celých čísel
• Pokud nedojde při výpočtu k překročení číselného rozsahu jsou výpočty
přesné
• Překročení číselného rozsahu se ale snad v žádné implementaci nekontroluje (to není vlastnost jazyka C, ale týká se to téměř všech programovacích jazyků)
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 26 z 89
Zpět
Celá obrazovka
Zavřít
Konec
/* K zadanému roku vypočítá datum velikonoc podle Gaussova vzorce */
#include <stdio.h>
int
main() {
int r, k, pr, d, e, den;
Úvodní strana
Titulní strana
Obsah
printf("Rok: ");
scanf("%d", &r);
k=r/100;
pr=k-k/4;
d = (19*(r%19) + (15-(8*k+13)/25+pr)%30) % 30;
e = (2*(r%4)+4*(r%7)+6*d+(4+pr)%7) % 7;
den=22+d+e;
if (d==29 && e==6) den-=7;
if (d==28 && e==6 && r/19>10) den-=7;
if (den>31) printf("Velikonoce: %d. 4. %d\n", den-31, r);
else printf("Velikonoce: %d. 3. %d\n", den, r);
}
JJ
II
J
I
Strana 27 z 89
Zpět
Celá obrazovka
Zavřít
Konec
/*
* Pro zadané datum spočítá den v týdnu
* (1=pondělí, 2=úterý, ... 6=sobota, 0=neděle)
*/
Úvodní strana
#include <stdio.h>
int
main() {
int rok, mesic, den, p;
printf("Zadej datum dd.mm.rrrr: ");
if (scanf("%d.%d.%d", &den, &mesic, &rok)==3) {
if (mesic<3) {
mesic+=12;
rok--;
}
p=(long)rok*365+rok/4-rok/100+rok/400+(306*(mesic+1))/10+den-1;
printf("Den v týdnu: %d\n", (int) (p % 7));
} else {
printf("Spatně zadané datum.");
}
}
Titulní strana
Obsah
JJ
II
J
I
Strana 28 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Výpočet kořenů kvadratické rovnice
Napíšeme program, který vypočítá kořeny kvadratické rovnice
ax2 + bx + c = 0
Úvodní strana
Titulní strana
Podle hodnoty diskriminantu D
Obsah
D = b2 − 4ac
JJ
II
J
I
musíme rozlišit tři případy
Strana 29 z 89
jestliže D > 0
jestliže D = 0
jestliže D < 0
√
x1,2 = −b±2a D
x1,2 = −b
2a
√
−D
−b
x1,2 = 2a ± 2a
i
Zpět
Celá obrazovka
(dvojnásobný kořen)
Zavřít
Konec
Budeme potřebovat tři reálné proměnné pro uložení koeficientů a, b, c. Aby
nebylo nutné počítat diskriminant opakovaně, použijeme pro jeho uložení další
proměnnou.
V jazyce C je nutné každou proměnnou deklarovat. Deklarace bude vypadat
takto:
double a, b, c, D;
Úvodní strana
V programu budeme potřebovat podmíněný příkaz. Jeho syntaktický diagram
vypadá takto:
- else - příkaz
- if
- ( - výraz - ) - příkaz
Výraz bývá nejčastěji relační – porovnání s použitím jednoho z následujících
operátorů:
Titulní strana
Obsah
JJ
II
J
I
Strana 30 z 89
==
!=
<
>
<=
>=
je rovno
není rovno
je menší než
je větší než
je menší nebo rovno
je větší nebo rovno
V případě, že je výraz pravdivý, provede se příkaz uvedený za kulatou závorkou. Pokud by mělo být provedeno více příkazů, je nutné použít složený
příkaz. Příkaz, který se má provést při
Zpět
Celá obrazovka
Zavřít
Konec
#include <stdio.h>
#include <math.h>
void main()
{
float a, b, c, D;
printf("Program na výpočet kořenů kvadratické rovnice ax^2+bx+c=0\n\n");
printf("Koeficient a: ");
scanf("%f", &a);
printf("Koeficient b: ");
scanf("%f", &b);
printf("Koeficient c: ");
scanf("%f", &c);
printf("Rovnice %G.x^2 %+G.x %+G = 0\n", a, b, c);
if (a==0) {
if (b==0) {
if (c==0) {
printf("Rovnici vyhovuje každé x.\n");
} else {
printf("Rovnice nemá řešení.\n");
}
} else {
printf("Lineární rovnice; řešení x = %G.\n", -c/b);
}
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 31 z 89
Zpět
Celá obrazovka
Zavřít
Konec
} else {
D=b*b-4*a*c;
if (D>0) {
printf("Řešení: x1 = %G, x2 = %G.\n", (-b+sqrt(D))/(2*a),
(-b-sqrt(D))/(2*a));
} else if (D==0) {
printf("Řešení: x1,2 = %G.\n", -b/(2*a));
} else {
printf("Řešení: x1,2 = %G +- %Gi.\n", -b/(2*a),
fabs(sqrt(-D)/(2*a)));
}
}
}
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 32 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Výpočet Ludolfova čísla π
Napíšeme program, který vypočítá Ludolfovo číslo pí. Použijeme vzorec
π
1
1
= arctg + arctg
4
2
3
Úvodní strana
Titulní strana
Pro výpočet hodnoty funkce arctg použijeme Taylorův vzorec
Obsah
x3 x5 x7 x9
arctgx = x −
+
+
−
+ . . . (pro x < 1)
3
5
7
9
JJ
II
J
I
#include <stdio.h>
#include <math.h>
Strana 33 z 89
void main()
{
int n;
double moc2, moc3;
double znam;
double epsilon;
double clen, suma;
Celá obrazovka
epsilon=1e-9;
znam=1.0;
Zpět
Zavřít
Konec
moc2=1.0/2.0;
moc3=1.0/3.0;
n=1;
clen=moc2+moc3;
suma=clen;
while (fabs(clen)>epsilon) {
n=n+2;
znam=-znam;
moc2=moc2/4.0;
moc3=moc3/9.0;
clen=znam/n*(moc2+moc3);
suma=suma+clen;
}
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 34 z 89
printf("Ludolfovo číslo: %.10lG\n", 4.0*suma);
}
Zpět
Celá obrazovka
Zavřít
Konec
Výpočet faktoriálu
#include <stdio.h>
#include <limits.h>
Úvodní strana
unsigned long factorial(unsigned long n) {
unsigned long fnm1;
if (n<=1) return 1UL; /* 1UL is 1 of type unsigned long */
fnm1=factorial(n-1);
if (ULONG_MAX/n<fnm1) return 0; /* Signals overflow error */
return n*fnm1;
}
Titulní strana
Obsah
JJ
II
J
I
Strana 35 z 89
int main() {
unsigned long n, f;
printf("Program na výpočet faktoriálu\n");
printf("Zadej číslo: ");
if (scanf("%lu", &n)!=1) {
fprintf(stderr, "Nebylo zadáno číslo!\n");
return 2;
}
printf("Počítám %lu!\n", n);
f=factorial(n);
if (f==0) {
Zpět
Celá obrazovka
Zavřít
Konec
fprintf(stderr, "Výsledek je příliš velký!\n");
return 1;
}
printf("%lu! = %lu\n", n, f);
return 0;
}
Úvodní strana
Titulní strana
Problémem rekurzivního výpočtu faktoriálu je, že i když hlídám aritmetické
přetečení, dojde k přetečení zásobníku dříve než k aritmetickému přetečení.
Obsah
JJ
II
J
I
Strana 36 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Práce s logickými hodnotami
Jazyk C nemá (na rozdíl od Pascalu) zvláštní typ pro logické hodnoty. Logické
hodnoty často používáme, niž bychom je potřebovali někam ukládat:
Úvodní strana
if (a>b) max=a; else max=b;
if (max>0 && max<=10) ...
Titulní strana
Obsah
– && je logické „aÿ (konjunkce).
JJ
II
V jazyce C lze pro ukládání logických hodnot použít libovolný celočíselný typ:
J
I
Strana 37 z 89
int a_je_vetsi;
a_je_vetsi = (a>b);
if (a_je_vetsi) max=a; else max=b;
Zpět
Celá obrazovka
Zavřít
Jako hodnota „nepravdaÿ se v jazyce C používá 0, jako „pravdaÿ 1. Příkazy if
a while a logické operátory &&, || (logické „neboÿ – disjunkce), a ! (negace)
jsou benevolentnější – za hodnotu „pravdaÿ považují libovolnou nenulovou
hodnotu.
Konec
Pravdivostní tabulka v jazyce C:
a
b
a && b
a || b
!a
!b
0
0
nenula
nenula
0
nenula
0
nenula
0
0
0
1
0
1
1
1
1
1
0
0
1
0
1
0
Úvodní strana
Titulní strana
Logické operátory && a || v jazyce C mají dvě sympatické vlastnosti:
• Mají správné priority – ve výrazu i>0 && i<=10 není nutné (na rozdíl
od Pascalu) používat závorky.
• V případě, že po vyhodnocení jednoho členu je zřejmé, jaká bude hodnota celého výrazu, zbývající členy se již nevyhodnocují (tzv. shortcircuit evaluation). Díky tomu je možné jednoduše zapisovat složené
podmínky jako while (i<MAX_A && hodnota>a[i]) i=i+1;.
Obsah
JJ
II
J
I
Strana 38 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Typ pole
Pole je složený datový typ – proměnná typu pole obsahuje několik hodnot
(prvků) téhož typu. Počet prvků pole se stanovuje při deklaraci. Jednotlivé
prvky se vybírají pomocí indexu, který v jazyce C může být libovolného celočíselného typu a index prvního prvku je vždy 0. U pole lze projít všechny
prvky pomocí cyklu. Pole může mít více rozměrů než jeden.
Je dobrou praxí deklarovat horní meze všech polí pomocí konstant a tyto
konstanty používat na všech místech, kde se jedná o horní mez pole:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
#define MAXPRVKU 10
Strana 39 z 89
double pole[MAXPRVKU];
int i;
Zpět
Celá obrazovka
pole[0]=0.0;
pole[MAXPRVKU-1]=1.0;
pole[MAXPRVKU/2]=2.0;
Zavřít
Konec
For cyklus
Jazyk C má zajímavou syntaxi i sémantiku for-cyklu:
Úvodní strana
for (výraz1; výraz2; výraz3) příkaz;
Titulní strana
znamená přesně totéž co
výraz1;
while (výraz2) {
příkaz;
výraz3;
}
Zapamatujte si, jak vypadá for cyklus přes všechny prvky pole:
Obsah
JJ
II
J
I
Strana 40 z 89
Zpět
Celá obrazovka
Zavřít
#define MAXPRVKU 10
Konec
double pole[MAXPRVKU];
int i;
for (i=0; i<[MAXPRVKU; i++) pole[i]=0.0;
Podprogramy, funkce, procedury
K čemu slouží
Nejobvyklejší odpověď na otázku, k čemu slouží podprogramy, funkce nebo
procedury, bývá „aby bylo možné určitou akci provádět na různých místechÿ.
Tato odpověď nám však téměř vůbec nepomůže k tomu, abychom vytvářeli
srozumitelné a pěkné programy. Pokud se budeme držet tohoto principu a čirou náhodou budeme mít napsat program, ve kterém se žádná činnost neprovádí vícekrát, bude výsledkem jedna, velmi dlouhá a nesrozumitelná funkce.
Lidská mysl je schopna obsáhnout pouze objekty omezené složitosti. Proto je
třeba při programování rozdělovat řešení složitých problémů na menší části,
kterým je člověk schopen snadno porozumět. Tyto části se realizují pomocí
podprogramů. Každý podprogram by měl řešit určitou dobře definovatelnou
a definovanou úlohu.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 41 z 89
Zpět
Celá obrazovka
Zavřít
HLAVNÍM DŮVODEM POUŽÍVÁNÍ FUNKCÍ JE
ZLEPŠENÍ SROZUMITELNOSTI PROGRAMU
Při programování (nebo při čtení cizího programu) je v každém stádiu důležité,
co dělají jednotlivé podprogramy, ale ne jak to dělají (to je zajímavé až při
bližším pohledu).
Konec
Proto jsou podprogramy prostředkem programové abstrakce.
K snazšímu pochopení přispívají mnemotechnické názvy procedur a proměnných a rozumné komentáře, které popisují části programu z hlediska řešeného
problému a ne z hlediska použitého programovacího jazyka.
Úvodní strana
Podprogramy v jazyce C – funkce
Titulní strana
Obsah
V různých jazycích se používají různé názvy pro podprogramy; v jazyce Pascal
se například podprogramy dělí na funkce (které vracejí hodnotu) a procedury
(které hodnotu nevracejí).
V jazyce C je rozlišování funkcí a procedur dosti uvolněné – každou funkci je
možné vyvolat jako proceduru (pokud nezáleží na vrácené hodnotě). V jazyce
C se obvykle podprogramům říká pouze funkce, i když lze vytvářet funkce,
které nevracejí žádnou hodnotu (funkce typu void).
Deklarace – sděluje překladači, jak funkce vypadá (jaké má jméno, hodnotu
jakého typu vrací, kolik má parametrů a jaké jsou jejich typy) – funkci deklarujeme zapsáním její hlavičky
Definice – definuje, co funkce dělá – obsahuje hlavičku a tělo funkce
Použití – vyvolání funkce ve výrazu nebo příkazu
Každá funkce může mít pouze jedinou definici. Deklarací může být více, ale
JJ
II
J
I
Strana 42 z 89
Zpět
Celá obrazovka
Zavřít
Konec
nesmí být v rozporu mezi sebou ani s definicí.
Použití funkce by měla předcházet deklarace nebo definice (pokud nepředchází, doplní si překladač, že se jedná o funkci bez parametrů vracející typ
int).
Úvodní strana
V jazyce C musí být za jménem funkce vždy otvírací kulatá závorka (i když
funkce nemá žádné parametry).
Titulní strana
Obsah
Definice funkcí nelze v jazyce C vnořovat.
Funkční hodnota se v jazyce C vrací příkazem return hodnota;.
JJ
II
Každá funkce by měla mít co možná nejjednodušší interakci se svým okolím.
Přesněji veškeré interakce s okolím by měly být prováděné pomocí parametrů.
J
I
Funkce, která mění i jiné hodnoty než své parametry, se nazývá funkce s postranními efekty (side effects). Pokud možno bychom se takovýmto funkcím
měli vyhýbat, stejně jako funkcím, které jsou kromě parametrů ovlivňovány
jinými hodnotami.
Strana 43 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Typ ukazatel
Ukazatele slouží jako odkazy na jiné proměnné. Zatímco běžná proměnná
může během výpočtu měnit svoji hodnotu, proměnná typu ukazatel může
ukazovat na různé proměnné (měly by být téhož typu, ale toto omezení lze
v případě potřeby obejít). Zatímco ve standardním Pascalu lze ukazatele používat pouze pro odkazy na dynamicky vytvářené proměnné, v jazyce C je
jejich použití mnohem širší – mohou ukazovat na libovolné proměnné včetně
lokálních.
Deklarace proměnných typu ukazatel
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 44 z 89
Ukazatele se deklarují takto:
typ *identifikátor;
Pro práci s ukazateli slouží unární operátory & a *.
Operátor &objekt je získání adresy objektu – je-li objekt typu t, je výraz typu
„ukazatel na tÿ, neboli *t.
Operátor *ukazatel je dereference ukazatele – jeho hodnotou je proměnná,
na kterou ukazatel ukazuje.
Hodnota NULL – je zaručeno, že žádný ukazatel na některý objekt nemá hod-
Zpět
Celá obrazovka
Zavřít
Konec
notu NULL.
Porovnání operací s ukazateli v jazyce C a v Pascalu
Úvodní strana
operace
dereference
ukázání na objekt
prázdná hodnota
alokace paměti
uvolnění paměti
přístup k položce
C
Pascal
*ptr
&objekt
NULL
ptr=malloc(sizeof(typ))
free(ptr)
ptr->item
ptr^
@objekt (pouze Turbo Pascal)
nil
new(ptr)
dispose(ptr)
ptr^.item
Titulní strana
Obsah
JJ
II
J
I
Strana 45 z 89
Zpět
Celá obrazovka
Zavřít
Konec
int i, j, k, l;
int *p, *q, *r;
p=&i; /* p ukazuje na i, lze provést i když i není inicializováno */
i=1;
j=2;
q=&j; /* q ukazuje na j */
r=q; /* r ukazuje tam, co q (tj. na j) */
*p=*q; /* p ukazuje nadále na i, ale tímto se do i uloží 2 */
p=NULL; /* p neukazuje nikam */
*p=*q; /* chybně p neukazuje nikam, nelze tam kam ukazuje něco uložit */
r=&k; /* r ukazuje na k */
*r=3; /* tam, kam r ukazuje dej 3, tj. do k */
p=r; /* O.K. p ukazuje na k */
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 46 z 89
Zpět
Celá obrazovka
Prohození obsahu proměnných
void prohod(int *p1, int *p2) {
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
Zavřít
Konec
}
Proměnná temp musí být skutečně typu int a ne int *. Pokud by byla typu
int *, nebylo by možné do ni přiřadit hodnotu.
Úvodní strana
#include <stdlib.h>
#include <string.h>
Titulní strana
Obsah
int prohodcokoli(void *p1, void *p2, int size) {
void *ptemp;
ptemp=malloc(size);
if (ptemp==NULL) return 0;
memcpy(ptemp, p1, size);
memcpy(p1, p2, size);
memcpy(p2, ptemp, size);
free(ptemp);
return 1;
JJ
II
J
I
Strana 47 z 89
Zpět
Celá obrazovka
Zavřít
}
Konec
Ukazatele a pole
Identifikátor pole se chová jako ukazatel. Má typ „ukazatel na typ prvku poleÿ.
Jeho hodnota je ukazatel na nultý prvek pole (první prvek v poli, který má
index nula).
Úvodní strana
Přesto se pole a ukazatel od sebe liší:
Titulní strana
Obsah
• Identifikátor pole není l-hodnota – není možné do něj přiřadit hodnotu.
• Pokud deklarujeme pole, máme skutečně prostor pro počet položek,
který je uveden v deklaraci; pokud deklarujeme ukazatel, máme prostor
pouze pro tento ukazatel; aby bylo možné ukládat hodnoty na místo,
kam ukazatel ukazuje, je potřeba buď s ním někam ukázat: ptr=&proměnná;
nebo alokovat místo: ptr=malloc(n*(sizeof(*ptr)));.
JJ
II
J
I
Strana 48 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Algoritmus quicksort
Pracuje na principu „rozděl a panujÿ – při třídění vzestupně jsou na začátek
pole přemístěna malá čísla, na konec velká a na obě části zvlášť je znovu
uplatněn stejný algoritmus. Opakuje se dokud část, která se má třídit, nemá
méně než dva prvky – pak je jistě setříděná.
Úvodní strana
Titulní strana
1
3 5
7 9
2
4 6
8 0
Obsah
1
3 5
0 9
2
4 6
8 7
JJ
II
1
3 5
0 6
2
4 9
8 7
J
I
Strana 49 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Aritmetika ukazatelů
Je-li p ukazatel a n celé číslo, pak výrazy p+n a p-n jsou výrazy typu ukazatel
a mají hodnotu „ukazatel na prvek o n míst dáleÿ, resp. „ukazatel na prvek
o n míst zpětÿ.
Ukazují-li ukazatele p a q do téhož pole, je výraz p-q typu int a jeho hodnotou
je počet prvků mezi ukazateli q a p.
Úvodní strana
Titulní strana
Obsah
Typ void * – slouží pro konverze ukazatelů.
JJ
II
J
I
Strana 50 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Funkce pro vstup a výstup
Funkce pro vstup a výstup lze rozdělit na několik skupin:
hlavičkový soubor
operace
otevření souboru
vytvoření souboru
zavření souboru
posunutí v souboru
je konec souboru?
vstup
znaku
znaku
návrat znaku
řetězce
bloku
formátovaný
výstup
znaku
znaku
řetězce
bloku
formátovaný
stdio.h
stdio.h
conio.h
(gets)
scanf
stdout
putchar
fputchar
puts
printf
io.h
Úvodní strana
file handle
FILE
fopen
fopen
fclose
fseek
feof
stdin
getchar
fgetchar
curses.h
(initscr)
FILE
getc
fgetc
ungetc
fgets
fread
fscanf
klávesnice
klávesnice
getch
getche
ungetch
cgets
getch
cscanf
scanw
FILE
putc
fputc
fputs
fwrite
fprintf
obrazovka
obrazovka
putch
addch
insch
addstr
open
creat
close
lseek
eof
file handle
Titulní strana
Obsah
JJ
II
J
I
Strana 51 z 89
Zpět
ungetch
getnstr
Celá obrazovka
read
cputs
Zavřít
file handle
write
cprintf
printw
Konec
Ve druhém sloupci tabulky jsou funkce pro práci se standardním vstupem
a výstupem. O otevírání a zavírání standardního vstupu a výstupu se stará
operační systém. Místo dalších chybějících funkcí lze použít příslušné funkce
ze třetího sloupce, u kterých se na místě parametru typu FILE * použije stdin
– standardní vstup, nebo stdout – standardní výstup.
Funkce gets pro vstup řádku ze standardního vstupu by se rozhodně neměla
používat, protože neumožňuje zadat maximální délku čteného řetězce. Díky
tomu může dojít k přetečení použitého řetězce, které může mít za následek
přepsání dalších proměnných, havárii programu a za určitých podmínek i ohrožení bezpečnosti operačního systému. Místo funkce gets používejte fgets.
Ve třetím sloupci jsou funkce pro práci s libovolnými soubory používající
vyrovnávací paměti (buffered input/output). Pokud program pracuje s jinými
soubory než se standardním vstupem a výstupem, obvykle používá právě tyto
funkce.
Ve čtvrtém sloupci jsou funkce pro práci s obrazovkou a klávesnicí, které byly
použity u překladačů firmy Borland pro OS MS-DOS. Mají jednoduchou podporu oken v textovém režimu, umožňují přemisťovat a zjišťovat pozici kursoru
na obrazovce a mazat obrazovku. Jedná se o funkce převzaté z turbopascalské
jednotky Crt. Jsou dostupné pouze pokud použitý překladač má knihovny pro
zajištění kompatibility s překladači Borland. V OS Unix existuje pro podobný
účel knihovna curses, resp. ncurses, která má ovšem poněkud jiné funkce a
zcela jiné ovládání.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 52 z 89
Zpět
Celá obrazovka
Zavřít
Konec
V pátém sloupci jsou funkce z knihovny curses, která umožňuje vytvářet okna
v textovém režimu v Unixu. Její použití je poměrně komplikované.
V posledním sloupci jsou funkce, které tvoří minimální nadstavbu nad službami pro práci se soubory, které poskytuje operační systém. Jako odkazy
na soubory se používají malá celá čísla, tak zvané manipulátory (file handles), které vracejí funkce open a creat (funkce se skutečně jmenuje creat a
ne create). Tyto funkce nepoužívají vyrovnávací paměti, proto jsou při práci
s malými bloky málo efektivní.
Při otevírání souboru je nutné stanovit způsob práce se souborem: zda se bude
pouze číst, pouze zapisovat nebo obojí, zda se má připisovat na konec, zda
má být existující soubor přepsán a konečně zda mají být konvertovány znaky
\n (newline) na znaky používané pro ukončení řádku v příslušném operačním
systému (při výstupu; při vstupu bude prováděna opačná konverze). Způsob
práce se souborem stanovuje zvláštní parametr funkcí fopen a open.
Druhý parametr funkce fopen udává způsob práce se souborem. Je to řetězec,
který je složen z hodnot uvedených v jednotlivých částech následující tabulky:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 53 z 89
Zpět
Celá obrazovka
Zavřít
Konec
r
r+
w
w+
a
a+
t
b
jinak
hodnota parametru mode ve funkci fopen
(read) otevřít existující soubor pro čtení
otevřít existující soubor pro čtení a zápis (update)
(write) vytvořit soubor pro zápis; existující soubor bude přepsán
vytvořit soubor pro zápis a čtení (update); pokud soubor se
zadaným jménem existuje, bude přepsán
(append) otevřít soubor pro připisování na konec; pokud soubor
neexistuje, bude vytvořen
otevřít soubor pro připisování na konec a čtení; pokud soubor
neexistuje, bude vytvořen
otevřít v textovém režimu
otevřít v binárním režimu
otevřít v režimu určeném proměnnou fmode
Podobně funkce open má jako druhý parametr celé číslo, které je tvořeno logickým součtem konstant uvedených v jednotlivých částech následující tabulky,
a které určuje způsob práce se souborem:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 54 z 89
Zpět
Celá obrazovka
Zavřít
Konec
O
O
O
O
O
O
O
O
O
O
O
O
RDONLY
WRONLY
RDWR
NONBLOCK
NDELAY
SYNC
APPEND
CREAT
TRUNC
EXCL
BINARY
TEXT
příznaky pro access v open
otevřít jen pro čtení
otevřít jen pro zápis
otevřít pro čtení a zápis
neblokující přístup (pouze při práci s FIFO v Unixu)
totéž jako O NONBLOCK
výstupní funkce skončí až po fyzickém zápisu na zařízení
před každým zápisem nastavit file pointer na konec souboru
vytvořit soubor
existující soubor bude při otevření zkrácen na délku 0
po dobu otevření nebude soubor moci otevřít jiný program
otevřít v binárním režimu
otevřít v textovém režimu
Při zpracování vstupu je někdy potřeba načíst (provést vstupní konverzi) číslo,
které se nachází v již načtených datech. Pro tento účel lze použít funkci sscanf,
která funguje podobně jako scanf, ale místo ze standardního vstupu čte ze
řetězce. Obdobně pro výstup existuje funkce sprintf, které formátovaný výstup
ukládá do řetězce a ne do souboru.
Pro vstupní konverze existují i specializované funkce:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 55 z 89
Zpět
Celá obrazovka
Zavřít
Konec
druh konverze
konverze řetězec
konverze řetězec
konverze řetězec
konverze řetězec
konverze řetězec
konverze řetězec
konverze řetězec
konverze řetězec
funkce
→
→
→
→
→
→
→
→
typ
typ
typ
typ
typ
typ
typ
typ
integer
long
long long
unsigned long
unsigned long long
float
double
long double
strtol
strtoll
strtoul
strtoull
strtof
strtod
strtold
funkce
atoi
atol
atoll, atoq
Úvodní strana
Titulní strana
atof
Program pro výpis obsahu souboru na standardní výstup
Ošetření všech chyb, ke kterým může dojít při vstupu a výstupu, bývá komplikované. Ovšem v situacích, kdy může dojít k chybě, by program měl testovat,
zda k ní nedošlo, a pokud ano, měl by o ní srozumitelně informovat uživatele.
Obsah
JJ
II
J
I
Strana 56 z 89
Zpět
Celá obrazovka
#include <stdio.h>
#include <errno.h>
FILE *fp;
char buffer[1000];
int code=0;
int main(int argc, char *argv[])
Zavřít
Konec
{
if (argc!=2) {
fputs("Usage: typec filename\n", stderr);
return 1;
}
Úvodní strana
if (!(fp=fopen(argv[1], "rt"))) {
fprintf(stderr, "Error opening file %s: %s\n", argv[1], strerror(errno));
Titulní strana
return 2;
} else {
Obsah
while (!feof(fp)) {
JJ
II
if (!fgets(buffer, sizeof(buffer)-1, fp) && errno!=0) {
fprintf(stderr, "Error reading file %s: %s\n", argv[1], strerror(errno));
J
I
code=2;
break;
Strana 57 z 89
} else {
Zpět
if (fputs(buffer, stdout)==EOF) {
fprintf(stderr, "Error writing stdout: %s\n", strerror(errno));
Celá obrazovka
code=3;
break;
Zavřít
}
Konec
}
}
if (fclose(fp) && code==0) {
/* This error shouldn’t happen */
fprintf(stderr, "Error closing file %s: %s\n", argv[1], strerror(errno));
code=2;
}
/* Check whether flushing buffers doesn’t cause an error;
it would be really bad luck if it does, but what if the stdout
is redirected to a disk file, disk is just full and there is no
space to write the contents of bufffers? */
if (fflush(stdout) && code==0) {
fprintf(stderr, "Error flushing stdout: %s\n", strerror(errno));
code=3;
}
}
return code;
}
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 58 z 89
Načítání čísel
Zpět
Celá obrazovka
Pro třídicí program vytvoříme funkci, která načítá čísla typu double. Funkce
bude vracet hodnotu 1, pokud bylo načteno číslo a 0 jinak:
Zavřít
Konec
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<string.h>
"readdbl.h"
#define BUFLEN 80
char buffer[BUFLEN];
int readdouble(double *value) {
double val;
char *p;
int status;
int len;
status=0; /* Nic neprecteno */
if (fgets(buffer, BUFLEN, stdin)!=NULL) {
val=strtod(buffer, &p);
if (p!=buffer) {
*value=val;
status=1; /* Cislo nacteno */
}
/* Jeste docist zbytek radku, pokud nebyl docten */
len=strlen(buffer);
while (len>0 && buffer[len-1]!=’\n’) {
if (fgets(buffer, BUFLEN, stdin)==NULL) break;
len=strlen(buffer);
}
}
return status;
}
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 59 z 89
Zpět
Celá obrazovka
Zavřít
Konec
S touto funkcí lze snadno napsat proceduru na přečtení předem neznámého
počtu prvků do pole (maximální počet načtených prvků je samozřejmě omezen
velikostí pole):
#include <stdio.h>
#include "rdwrarr.h"
#include "readdbl.h"
int readarray(double x[], int n)
{
int i;
i=0;
while (i<n && readdouble(&x[i])) {
i++;
}
return i;
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 60 z 89
Zpět
Celá obrazovka
}
Zavřít
void writearray(double *x, int n)
{
int i;
for (i=0; i<n-1; i++) printf("%lG, ", x[i]);
if (n != 0) printf("%lG\n", x[n-1]);
}
Konec
Vazba programu na operační systém
Jazyk C byl navrhován s jasnou představou, jakým způsobem má program
komunikovat s operačním systémem. Činnost programu je možné ovlivnit
pomocí parametrů, které se zadávají na příkazovém řádku za jménem programu. Naopak program při svém skončení informuje operační systém, jak
byl úspěšný, pomocí tzv. návratového kódu.
Úvodní strana
Titulní strana
Obsah
Zpracování parametrů
Jazyk C umožňuje elegantně číst parametry programu zadaná na příkazovém
řádku při jeho spouštění. Parametry bývají často jména souborů, ale není to
podmínkou.
Pro zpřístupnění parametrů programu je nutné definovat funkci main jako
funkci se dvěma parametry. První parametr musí být typu int, druhý typu
char *[] (pole ukazatelů na znak). Jména parametrů mohou být libovolná,
ale tradičně se používají jména argc a argv (jako argument count a argument
values). Použití parametrů ilustruje následující ukázka:
#include <stdio.h>
int main(int argc, char *argv[])
JJ
II
J
I
Strana 61 z 89
Zpět
Celá obrazovka
Zavřít
Konec
{
int i;
printf("Jméno programu: %s\n", argv[0]);
printf("Počet parametrů: %d\n", argc-1);
for (i=1; i<argc; i++)
printf("Parametr %d: %s\n", i, argv[i]);
return 5;
Úvodní strana
Titulní strana
}
Návratový kód
Obsah
JJ
II
J
I
Strana 62 z 89
Funkce main by měla být typu int a její provádění by mělo končit příkazem
return vracejícím celé číslo (případně je možné ukončit program v libovolné
funkci voláním procedury exit, která má jako parametr celé číslo, jež bude
také použito pro nastavení návratového kódu). Je zvykem, že vrácená hodnota
informuje o úspěšnosti běhu programu. Hodnota 0 znamená běh bez chyb,
nenulové hodnoty obvykle znamenají chyby, tím závažnější, čím je vrácená
hodnota vyšší, ale konkrétní použití může být i odlišné. Ačkoli je hodnota
typu int používají se hodnoty 0 až 255.
Zpět
Celá obrazovka
Zavřít
Konec
Funkce pro práci s řetězci
Jsou definovány v hlavičkovém souboru string.h. Lze je rozdělit na funkce
pro práci s ASCIIZ řetězci, funkce pro práci s ASCIIZ řetězci omezené délky,
a funkce pro práci poli znaků. U funkcí z druhé a třetí skupiny se zadává
délka nebo maximální délka řetězce; funkce z poslední skupiny nepovažují
znak s kódem nula za konec řetězce.
Operace
zjištění délky
vyplnění znakem
zkopírování
připojení na konec
porovnání <, =, >
porovnání, malá=velká
porovnání, malá=velká
vyhledání znaku
vyhledání podřetězce
ASCIIZ řetězec
strlen
strset
strcpy
strcat
strcmp
stricmp
strcmpi
strchr
strstr
řetěz. omez. délky
blok paměti
strnset
strncpy
strncat
strncmp
strnicmp
strncmpi
memset
memcpy
memcmp
memicmp
memchr
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 63 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Další funkce
• memmove – Zkopíruje blok bytů, vypořádá se s překrýváním zdrojového
a cílového bloku
• memccpy – Zkopíruje blok bytů zakončený zadaným znakem zadané ma-
ximální délky
• stpcpy – Zkopíruje řetězec, vrátí ukazatel na koncovou nulu v kopii
• strdup – Naalokuje paměť na haldě a do ní zkopíruje řetězec
• strrchr – Vrátí poslední výskyt zadaného znaku v řetězci nebo NULL
• strspn – Vrátí délku počáteční části prvního řetězce, která obsahuje
pouze znaky z druhého řetězce, strcspn – která neobsahuje žádný znak
z druhého řetězce
• strpbrk – Vyhledá první výskyt libovolného znaku z druhého řetězce
v prvním řetězci
• strtok – Postupně vrací části z prvního řetězce, které neobsahují žádný
znak z druhého řetězce
• strlwr – Převede velká písmena v řetězci na malá, strupr – malá na
velká, strrev – malá na velká a velká na malá
• strcoll – Porovná dva řetězce, bere v potaz národní zvyklosti podle
nastavení setlocale
• strxfrm – Transformuje řetězec tak, aby následné porovnání dvou transformovaných řetězců pomocí strcmp vrátilo stejnou hodnotu jako strcoll
na původní řetězce
• strerror – Vrátí textový popis chyby zadaného čísla
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 64 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Oddělený překlad
Oddělený překlad (samostatná kompilace) je prostředek, který usnadňuje vytváření rozsáhlých programů.
Úvodní strana
• Program je rozdělen na logické celky – kompilační jednotky, moduly
Titulní strana
• Každá kompilační jednotka se překládá zvlášť
Obsah
• Jeden modul obsahuje obvykle definice datových struktur a funkcí, které
s nimi pracují
JJ
II
• Program se sestavuje z jedné nebo několika kompilačních jednotek
J
I
• Větší množství přeložených kompilačních jednotek lze sloučit do knihovny
• Pokud se změní pouze jedna kompilační jednotka, stačí přeložit pouze
ji a znovu sestavit program
• Na různých modulech mohou pracovat různí lidé
• Některé moduly mohou být použity ve více programech (znovupoužitelnost)
Strana 65 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Program je rozdělen na části, moduly (například modul pro vytváření menu,
vstup údajů, zpracování údajů, grafický výstup na obrazovku, výstup na tiskárnu a práci se soubory). Každý modul je umístěn ve zvláštním zdrojovém
souboru obsahující definice všech potřebných objektů (procedur, proměnných,
konstant a typů). Každý zdrojový soubor se překládá samostatně. Aby objekty definované v jednom modulu mohly být používány v dalších, musí každý
z těchto modulů obsahovat deklarace použitých objektů. V jazyce C je zvykem
umísťovat tyto deklarace do tzv. hlavičkových souborů, které se vloží direktivou #include do všech zdrojových souborů, ve kterých se budou používat.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 66 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Rozdíl mezi definicí a deklarací:
Definice skutečně vytvoří proměnnou (vyhradí pro ni místo) nebo proceduru
(definuje, jaké budou příkazy v těle procedury).
Deklarace pouze oznamuje, že existuje (to znamená „někde je definovánÿ)
objekt s určitého jména, typu a dalších vlastností.
Úvodní strana
Titulní strana
Následující příklad ukazuje jednoduché použití samostatně kompilovaných
modulů.
Souboru modul.c obsahuje definice proměnné x a procedury printx() pro
tisk obsahu této proměnné.
Obsah
JJ
II
J
I
Strana 67 z 89
Soubor modul.c:
#include "modul.h"
int x;
Zpět
Celá obrazovka
Zavřít
Konec
void printx()
{
printf("%d\n", x);
}
Souboru modul.h obsahuje deklarace objektů definovaných v modul.c. Tento
soubor se pomocí direktivy #include vkládá, do každého souboru, ve kterém
se používá sdílená proměnná x nebo procedura printx().
Soubor modul.h:
Úvodní strana
Titulní strana
extern int x;
Obsah
void printx();
Příklad programu, který používá objekty z modul.c.
JJ
II
J
I
Strana 68 z 89
Soubor program.c:
Zpět
Celá obrazovka
#include "modul.h"
Zavřít
void main()
{
x=2;
printx();
x++;
printx();
}
Konec
Makra preprocesoru
Jednou z funkcí preprocesoru je používání maker s parametry. Vhodně definovaná makra mohou značně zlepšit srozumitelnost programu.
Úvodní strana
Makra s parametry se definují pomocí direktivy #define – stejně jako konstanty. Jméno makra je od #define odděleno alespoň jednou mezerou, bezprostředně za jménem je otevírací kulatá závorka, jeden nebo více parametrů oddělených čárkami a uzavírací kulatá závorka. Za další alespoň jednou mezerou
následuje hodnota makra – text, ve kterém se mohou vyskytovat parametry.
Je-li text makra dlouhý, lze jej rozdělit pomocí znaku obrácené lomítko a pokračovat na další řádku. Pokud se v textu programu vyskytne řetězec shodný
se jménem makra následovaný argumenty v závorce, preprocesor dosadí (textově), argumenty z volání makra za argumenty z definice a místo volání makra
vloží text z definice. Vzhledem k tomu, že hodnoty parametrů mohou být libovolné posloupnosti znaků (tedy libovolné výrazy), je nutné v textu makra
uzavírat každý parametr do závorek, a totéž udělat i s celým textem makra
(aby nedošlo k problémům způsobeným různou prioritou operátorů).
Titulní strana
Obsah
JJ
II
J
I
Strana 69 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Použití maker – heapsort
Následující příklad ukazuje, jak pomocí maker zpřehlednit třídicí algoritmus
heapsort. V tomto algoritmu se na tříděné hodnoty pohlíží, jako by byly uspořádány do binárního stromu (s hodnotou v každém uzlu) tak, že hodnota otce
každého uzlu je větší nebo rovna hodnotě obou jeho potomků. Algoritmus
se skládá ze dvou částí: vytvoření heapu, a postupného odebírání největších
prvků z heapu.
Heap se vytváří postupným přidáváním prvků; jednoprvkový strom je vždy
heap. Pokud přidáním dalšího prvku dojde porušení podmínky, je prvek prohozen se svým otcem, což může vyvolat potřebu dalšího prohození (otce s jeho
otcem) atd. .
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 70 z 89
Odebírání prvků z heapu se provádí tak, že se odebere prvek z vrcholu a vloží
se na první místo již setříděné části pole (setříděné pole se vytváří odzadu). Na
jeho místo se dá nejpravější prvek z heapu, čímž se heap zmenší o jeden prvek.
Prvek, který byl umístěn do vrcholu, může porušit podmínku pro heap, a pak
je nutné jej prohodit s větším z jeho synů, atd. až prvek, který byl umístěn
do vrcholu heapu, klesne tam, kde už neporušuje podmínku heapu. Pak se
odebere další prvek atd. .
Heap je realizován v poli tak, že vrchol je nultý prvek, a následují další vrstvy
odshora, takže synové vrcholu jsou první a druhý prvek, synové levého syna
vrcholu jsou třetí a čtvrtý prvek, synové pravého syna pátý a šestý prvek atd. .
Zpět
Celá obrazovka
Zavřít
Konec
Makra LEFT(i), RIGHT(i) a PARENT(i) vracejí po řadě index levého syna,
pravého syna, resp. otce prvku, který má v poli index i.
#include <stdio.h>
Úvodní strana
#define LEFT(i) (2*(i)+1)
#define RIGHT(i) (2*(i)+2)
#define PARENT(i) (((i)-1)/2)
Titulní strana
Obsah
void heapsort (double a[], int n) {
JJ
II
int z, i;
double temp;
J
I
Strana 71 z 89
/* Vytváření heapu; jednoprvkové pole je vždy heap */
for (z=1; z<n; z++) {
temp=a[z];
i=z;
/* Bublání přidaného prvku nahoru */
while (i>0 && temp>a[PARENT(i)]) {
a[i]=a[PARENT(i)];
i=PARENT(i);
}
a[i]=temp;
}
/* Postupné odebírání vždy jednoho největšího prvku z heapu */
Zpět
Celá obrazovka
Zavřít
Konec
for (z=n-1; z>0; z--) {
temp=a[z]; /* Posledni prvek zkusím umístit do kořene a bublat dolů */
a[z]=a[0]; /* Odebrání prvku; z je už za heapem */
i=0;
/* Je-li některý z následníků větší, je třeba bublat dolů */
while (LEFT(i)<z && a[LEFT(i)]>temp ||
RIGHT(i)<z && a[RIGHT(i)]>temp) {
/* Který z následníků je větší? Oba existují, je-li RIGHT(i)<z. */
if (RIGHT(i)<z && a[LEFT(i)]<a[RIGHT(i)]) {
a[i]=a[RIGHT(i)];
i=RIGHT(i);
} else {
a[i]=a[LEFT(i)];
i=LEFT(i);
}
}
a[i]=temp;
}
}
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 72 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Knihovna conio.h
• Pro práci s obrazovkou a klávesnicí v MS-DOSu.
• Zavedeno v Turbo-C (analogie jednotky Crt z Turbo Pascalu).
• Není standardní knihovnou jazyka C (např. v DJGPP je z důvodu kompatibility)
Úvodní strana
Titulní strana
Obsah
Funkce pro umístění kursoru a zjištění jeho souřadnic:
void gotoxy(int _x, int _y);
int wherex(void);
int wherey(void);
JJ
II
J
I
Strana 73 z 89
Zpět
x vodorovně, y svisle, (1,1) je levý horní roh obrazovky. Pokud je definováno
okno, jsou souřadnice v rámci něj a relativní vůči němu. Funkci pro výpis a
čtení znaku s echem posouvají kursor.
Celá obrazovka
Zavřít
Konec
Podporuje jednoduchá okénka:
void window(int _left, int _top, int _right, int _bottom);
Úvodní strana
– definuje (neviditelný) obdélník na obrazovce, všechny funkce z conio.h, které
pracují s obrazovkou používají tento obdélník. Při startu programu je okno
přes celou obrazovku. Není žádná podpora pro obnovování překrytých částí
oken apod. – lze použít gettext() a puttext().
Titulní strana
Obsah
JJ
II
J
I
Strana 74 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Analogie běžných funkcí pro vstupy a výstupy:
int putch(int _c);
int cputs(const char *_str);
int cprintf(const char *_format, ...);
int getch(void);
int getche(void);
int ungetch(int);
int kbhit(void);
char * cgets(char *_str);
int cscanf(const char *_format, ...);
/*
/*
/*
/*
/*
/*
/*
/*
/*
Výpis znaku */
Výpis řetězce */
Formátovaný výstup */
Vstup znaku (bez echa) */
Vstup znaku (s echem) */
Vrácení přečteného znaku */
Byla stisknuta klávesa? */
Vstup řetězce */
Formátovaný vstup */
Funkce cgets očekává v prvním bytu řetězce hodnotu udávající maximální
délku načítaného řetězce (včetně koncové nuly), po návratu je v _str[1] skutečná délka načteného řetězce – na rozdíl od gets je bezpečná. Pokud se výpis
dostane do pravého dolního rohu okna, obrazovka odskroluje o jeden řádek
nahoru. Po nastavení proměnné _wscroll na 0 se scrollovat nebude.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 75 z 89
Zpět
Celá obrazovka
Zavřít
Smazání okna a smazání řádku v okně od pozice kursoru k pravému okraji
okna:
void clrscr(void);
void clreol(void);
Konec
Barvy:
BLACK
BLUE
GREEN
CYAN
RED
MAGENTA
BROWN
LIGHTGRAY
černá
tmavě modrá
zelená
modrozelená
červená
fialová
hnědá
bílá (světle šedá)
#define BLINK
DARKGRAY
LIGHTBLUE
LIGHTGREEN
LIGHTCYAN
LIGHTRED
LIGHTMAGENTA
YELLOW
WHITE
šedá
světle modrá
světle zelená
světle modrozelená
světle červená
světle fialová
žlutá
jasně bílá
0x80 /* Přičíst k parametru funkce textcolor() pro blikání */
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 76 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Nastavování barev:
void
void
void
void
void
void
void
void
textattr(int _attr);
textcolor(int _color);
textbackground(int _color);
normvideo(void);
highvideo(void);
lowvideo(void);
blinkvideo(void);
intensevideo(void);
/*
/*
/*
/*
/*
/*
/*
/*
Nastaví barvu písma i pozadí */
Nastaví barvu písma (spodní 4 bity + bit 7) */
Nastaví barvu pozadí (bity 4-6) */
Úvodní strana
Nastaví barvy, které byly při startu */
Titulní strana
Nastaví jasnější barvy písma */
Nastaví tmavší barvy písma */
Obsah
Blikání */
Jasné barvy pozadí */
JJ
II
J
Scrollování textu v okně (uplatňuje se od řádku, na kterém stojí kursor, až
do posledního řádku v okně):
I
Strana 77 z 89
Zpět
void delline(void); /* Smaže řádek s kursorem, zbytek okna posune nahoru */
void insline(void); /* Vloží prázdný řádek, zbytek okna posune dolů */
Celá obrazovka
Zavřít
Konec
Načtení nastavení hodnot knihovny conio.h (poloha a velikost okna, poloha
a viditelnost kursoru, atd.):
void gettextinfo(struct text_info *_r);
Úvodní strana
struct text_info {
unsigned char winleft;
unsigned char wintop;
unsigned char winright;
unsigned char winbottom;
unsigned char attribute;
unsigned char normattr;
unsigned char currmode;
unsigned char screenheight;
unsigned char screenwidth;
unsigned char curx;
unsigned char cury;
};
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
levý okraj okna */
horní okraj okna */
pravý okraj okna */
spodní okraj okna */
aktuální barevné atributy */
normální barevné atributy */
aktuální videorežim */
šířka obrazovky (znaků) */
výška obrazovky (řádků) */
x-ová pozice kursoru */
y-ová pozice kursoru */
Titulní strana
Obsah
JJ
II
J
I
Strana 78 z 89
Zpět
Celá obrazovka
Zavřít
Nastavení vzhledu kursoru:
void _setcursortype(int _type); /* Nastavení vzhledu kursoru */
#define _NOCURSOR
#define _SOLIDCURSOR
#define _NORMALCURSOR
0
1
2
Konec
Nastavení textového režimu videoadaptéru (přičtením C4350 dojde k přepnutí
na 50 řádků na VGA nebo 43 na EGA):
void textmode(int _mode); /* Nastaví textový režim z následujících: */
enum text_modes { LASTMODE=-1, BW40=0, C40, BW80, C80, MONO=7, C4350=64 };
Úvodní strana
Titulní strana
Nastavení počtu řádek na obrazovce (používají se zvláštní znakové sady s výškou znaku 8, 14 nebo 16 bodů):
void _set_screen_lines(int _nlines);
Uložení, obnovení a kopie obdélníku na obrazovce (2 byty na pozici – první je
zobrazený znak, druhý barevné atributy):
Obsah
JJ
II
J
I
Strana 79 z 89
Zpět
Celá obrazovka
int gettext(int _left, int _top, int _right, int _bottom, void *_destin);
Zavřít
int puttext(int _left, int _top, int _right, int _bottom, void *_source);
int movetext(int _left, int _top, int _right, int _bottom, int _destleft, int _desttop);
Konec
Deklarace složitých typů
int *fnc[20](int n)
je totéž jako
Úvodní strana
Titulní strana
int *((fnc[20])(int n));
pole dvaceti funkcí s parametrem typu int, které vracejí ukazatel na int, ale
něco jiného než
Obsah
JJ
II
J
I
Strana 80 z 89
int (*fnc[20])(int n);
co je totéž jako
Zpět
Celá obrazovka
Zavřít
int (*(fnc[20]))(int n);
pole dvaceti ukazatelů na funkci, která má parametr typu int a vrací hodnotu
typu int, a to je je něco jiného než
Konec
int (*fnc)[20](int n);
což je totéž jako
int ((*fnc)[20])(int n);
Úvodní strana
Titulní strana
ukazatel na pole dvaceti funkcí, které mají parametr typu int a vrací hodnoty
typu int
Obsah
JJ
II
J
I
Strana 81 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Vlastnosti proměnných, funkcí, návěští a dalších pojmenovaných entit
• doba trvání (existence, duration) – jakou část doby běhu programu proměnná existuje
• oblast platnosti (výskytu, scope) – kde ve zdrojovém textu je možné
používat určitý identifikátor pro odkazování na týž objekt
Úvodní strana
Titulní strana
Obsah
• způsob spojování – za jakých podmínek znamenají dva stejné identifikátory tutéž věc
JJ
II
J
I
věci (proměnné) mohou být z hlediska doby trvání (duration)
Strana 82 z 89
• statické – existují po celou dobu běhu programu; proměnné deklarované
vně funkcí a proměnné deklarované uvnitř funkcí s klíčovým slovem
static nebo extern
• automatické – lokální proměnné funkcí (deklarované bez static i extern) a formální parametry funkcí; existují po dobu vyvolání funkce;
je-li funkce vyvolána rekurzivně, existují ve více exemplářích
• řízené (controled) – vznikají voláním malloc a zanikají voláním free
(nebo ukončením programu); pokud se provede ptr=malloc(4), je řízená ta paměť, která byla alokována, ne proměnná ptr – ta na ni pouze
ukazuje
Zpět
Celá obrazovka
Zavřít
Konec
způsob spojování (linkage):
• žádný – každá oblast platnosti identifikátoru se vztahuje k jinému objektu; tento způsob spojování mají proměnné a deklarované uvnitř funkce;
pokud jsou ale deklarovány s klíčovým slovem extern, mají interní linkage
• interní – různé oblasti platnosti identifikátoru v jednom zdrojovém souboru se vztahují k jednomu objektu; proměnné deklarované vně funkcí
mají interní linkage; pokud jsou ale deklarovány s klíčovým slovem extern, mají externí linkage
• externí – různé oblasti platnosti identifikátoru v různých zdrojových
souborech se vztahují k jednomu objektu
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 83 z 89
Zpět
jmenné prostory
Celá obrazovka
Objekt je identifikovatelná oblast paměti, která může obsahovat v čase proměnnou nebo konstantní hodnotu nebo sadu hodnot. (Objekt zde nemusí
objektem ve smyslu objektově orientovaného programování.)
Entita je procedura, návěští, typ anebo objekt ve smyslu uvedeném výše.
L-hodnota je výraz, který je odkazem na objekt. Objekt může být konstantní, pak mluvíme o konstantní l-hodnotě. Na levé straně přiřazovacího
příkazu musí být l-hodnota, která není konstantní.
Zavřít
Konec
Program se skládá z jednoho nebo více zdrojových souborů, které se překládají
samostatně.
Oblast výskytu identifikátoru (scope) je souvislá část programu, ve které
lze identifikátor použít pro přístup k jedné určité entitě.
Úvodní strana
Různé entity mají různé oblasti výskytu. Oblast výskytu
Titulní strana
blok mají identifikátory deklarované uvnitř bloku a parametry procedur (lokální identifikátory). Oblastí výskytu je u parametrů procedur hlavička
procedury a blok, který je jejím tělem, u ostatních identifikátorů nejvnitřnější blok obklopující deklaraci.
procedura mají návěští, která se deklarují uvedením návěští a dvojtečky
před příkazem. Příkaz goto label ; lze použít pouze uvnitř procedury,
kde je návěští label deklarováno.
prototyp procedury mají parametry prototypů procedur. Oblast výskytu
je omezena na příslušný prototyp (tj. seznam parametrů v deklaraci
procedury).
Obsah
JJ
II
J
I
Strana 84 z 89
Zpět
Celá obrazovka
Zavřít
Konec
soubor mají identifikátory deklarované mimo všechny bloky (globální identifikátory), například identifikátory funkcí.
Oblasti výskytu dvou různých entit označených týmž identifikátorem se mohou překrývat jestliže
• Identifikátory mají různé jmenné prostory (name space).
• Identifikátory mají stejné jmenné prostory, ale oblast výskytu identifikátoru jedné entity je blok, procedura nebo prototyp procedury, který
je vnořen do oblasti výskytu druhé entity, čímž dočasně zakrývá tuto
druhou entitu.
Jmenné prostory označují skutečnost, že identifikátory určitých entit si
vzájemně nekonkurují, protože mohou být použity pouze v přesně stanovených
disjunktních případech. Jednotlivé jmenné prostory:
Návěští mohou být použity pouze v deklaraci návěští a v příkazu goto.
Jména struktur, unionů a výčtových typů se používají vždy ve spojení
struct ident, union ident nebo enum ident.
Jména položek struktur nebo unionů musí být jednoznačná pouze v rámci
jedné struktury nebo unionu. Kromě deklarace se používají pouze pro
přístup k položce struktury nebo unionu, na pravé straně operátoru
tečka (.) nebo šipka (->).
Ostatní identifikátory proměnných, procedur, konstant a typů (typedef
jména).
Viditelnost identifikátoru (visibility) je rovna oblasti jeho výskytu zmenšené o vnořené oblasti výskytu téhož identifikátoru se stejným jmenným prostorem, kde je první identifikátor zakryt.
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 85 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Trvání objektu (duration) je doba, po kterou objekt existuje. Rozeznáváme
objekty s trváním
statickým, které existují po celou dobu běhu programu.
automatickým, které existují pouze po dobu provádění bloku, ve kterém
mají výskyt.
dynamickým, které se vytvářejí vyvoláním funkce (například malloc()) a
existují až do svého zrušení vyvoláním další funkce (free()) nebo do
konce běhu programu.
Způsob spojování (linkage) entit rozhoduje o tom, zda dva výskyty entity
s týmž identifikátorem budou považovány za odkaz na tutéž entitu. Rozeznáváme následující způsoby spojování:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 86 z 89
Zpět
externí – entity se stejným jménem a jmenným prostorem se považují za
tutéž entitu ve všech souborech a knihovnách, ze kterých je sestavován
program.
interní – entity téhož jména, patřící do stejného jmenného prostoru se považují za tutéž entitu v rámci souboru v němž se vyskytují.
žádný – každý výskyt je považován za jinou entitu.
Pravidla pro určení způsobu spojování jsou dosti složitá.
Celá obrazovka
Zavřít
Konec
Další třídy paměti
• register – rada pro překladač, aby proměnnou umístil do registru; přístup k registrům je obvykle rychlejší než do paměti; překladač se touto
radou může ale nemusí řídit (může do registru umístit i jinou proměnnou, než která je deklarována s register); na takto deklarovanou proměnnou nelze použít operátor získání adresy (&); lze použít pouze u
automatických proměnných
• auto – proměnná má být automatická; prakticky nemá žádný význam,
lze použít pouze u proměnných, které už automatické jsou
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 87 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Zacházení s proměnnými
• const – hodnotu proměnné nelze (kromě inicializace) měnit:
const double pi = 3.14159265358979;
double r, plocha;
scanf("%lf", &r);
plocha=pi*r*r;
printf("Plocha kruhu je %lG\n", plocha);
pi=22.0/7.0;
Poslední příkaz způsobí při překladu chybu nebo alespoň výpis varování.
• volatile – hodnota proměnné se může měnit i jiným způsobem než programem; překladač musí při každém použití skutečně pracovat s proměnnou; používat například pro hardwarové registry nebo sdílené proměnné
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 88 z 89
Zpět
Celá obrazovka
Zavřít
Konec
Použití typedef
Jestliže deklarace obsahuje specifikátor typedef, není deklarovaný identifikátor proměnnou, ale typem. Takto deklarovaný identifikátor je možné použít
v dalších deklaracích jako specifikátor typu:
typedef unsigned char byte;
typedef unsigned short word;
byte b;
word w;
– v prvním řádku je deklarován typ byte jako unsigned char, ve druhém typ
word jako unsigned short; v dalších dvou řádcích jsou pomocí těchto nových
typů deklarovány proměnné b a w.
Použitím typedef lze zpřehlednit zejména používání složitějších typů:
Úvodní strana
Titulní strana
Obsah
JJ
II
J
I
Strana 89 z 89
Zpět
Celá obrazovka
Zavřít
struct listitem {
struct listitem *next;
int value;
} titem, *pitem;
pitem seznam;
p1=malloc(sizeof(titem));
Konec

Podobné dokumenty

Upravená učebnice C a C++

Upravená učebnice C a C++ i více řádek, pokud vám ale stačí řádek jen jeden, můžete psát komentář i za dvé lomítka // (kompilátor si nebude všímat toho co je mezi těmito lomítky a koncem řádku. Není potřeba ho tedy nijak uk...

Více

Vivotek IP7131

Vivotek IP7131 Po  skončení  instalace  by  měl  Administrátor  pokračovat  ke  kapitole  „První  přístup  k síťové kameře“ pro nastavení nejnutnějších parametrů. 

Více

PF ČR - nabídka pozemků k pronájmu 3.11.2010

PF ČR - nabídka pozemků k pronájmu 3.11.2010 !{di#ii.r nemovf{osfr- poze+1ik6ve fil/dr ffe\irrl;portisft: Kat*tf nernovFosfi- pozankov* fnhdr t?dvriiFsnis: l(€,latritt*ernovitos{i:- F Více

LABORATORNÍ PŘÍRUČKA 20.8.2014

LABORATORNÍ PŘÍRUČKA 20.8.2014 není do laboratoře dodán celý objem moče, je třeba moč důkladně promíchat, změřit celkový objem s přesností na 10 ml (u velmi malých dětí s přesností na 1 ml) a odlít vzorek. Na průvodku se vyznačí...

Více

LP Laboratorní příručka,v3,23.2.2015

LP Laboratorní příručka,v3,23.2.2015 sestrám i pacientům. Laboratorní příručka obsahuje všechny nezbytné informace pro snadnou a bezproblémovou spolupráci s naší laboratoří. V případě jakýchkoliv dotazů se můžete kdykoliv obrátit na k...

Více

close

close sck – deskriptor socketu (z funkce socket) name – struktura sockaddr_in s IP adresou socketu a číslem portu sin_family – AF_INET – protokol IPv4 sin_addr.s_addr – IP adresa (INADDR_ANY) sin_port – ...

Více