SlideShare a Scribd company logo
Oddelený preklad, opakovanie v príkladoch
Anna Bou Ezzeddine
Obsah
oddelený preklad
opakovanie v príkladoch
Oddelený preklad
Oddelený preklad
vkladanie súborov
#include → vznikne jeden .OBJ súbor
 Vkladá sa jeden, alebo viac súborov
 Nevýhody:
 pri zmene v ľubovoľnom súbore musíme zbytočne prekladať aj
všetky ostatné
 medzi jednotlivými súbormi nie je možné skryť ich globálne
identifikátory
 oddelený preklad
každý súbor sa preloží zvlášť (vznikne viac .OBJ súborov) a
potom sa spoja pomocou linkeru
možnosť rozdelenia problému na viacero menších
nezávislých častí, na ktorých pracuje súčasne viacero
programátorov
Príklad oddeleného prekladu
s2.cs1.c s3.c s1.c s2.c s3.c
s.c
#include "s1.c"
#include "s2.c"
#include "s3.c"
s.obj
s1.obj s2.obj s3.obj
link s link s1, s2, s3
vkladanie súborov: oddelený preklad:
Oblasť platnosti identifikátorov
jazyk C umožňuje rôzne spôsoby ako
stanoviť kde, kedy a aký identifikátor bude
komu dostupný:
globálne a lokálne premenné
pamäťové triedy
typové modifikátory
Globálne premenné
organizácia v programe:
globálne definície a deklarácie
definície funkcií
globálne definície: definujú
premenné, rozsah ich platnosti:
od miesta definície po koniec
súboru (nie programu - program
sa môže skladať z viac súborov)
globálne deklarácie: deklarácie
premenných, ktoré sú definované
v inom súbore. často sú
špecifikované slovom extern -
externé deklarácie
príklad globálne definície
int i;
void prva()
{...}
int j;
int druha()
{...}
char *tretia()
{...}
premenná i je platná pre všetky 3
funkcie
premenná j je platná len pre funkcie:
druha() a tretia()
Lokálne premenné
definované vo funkciách
platnosť lokálnych premenných: od definície po koniec funkcie
int i1, i2;
void prva() {
int i1, j1;
...}
int j1, j2;
int druha(){
int i1, j1, k1;
...}
globálna premenná i1 je prekrytá
lokálnou premennou i1 (používať sa
môžu premenné: i1, j1 (lokálne) a i2
(globálna))
dve globálne premenné: i2, j2 a tri
lokálne premenné: i1, j1, k1.
Inicializácia lokálnych a globálnych
premenných
lokálne premenné:
nie sú automaticky inicializované
globálne premenné:
automaticky inicializované na 0 (0.0, 0)
(lepšie - nespoliehať sa na to)
Upozornenie
V jazyku C premenné definované vo funkcii main sú
lokálne iba pre túto funkciu
Pozor na zvyk z Pascalu, kde premenné definované v
hlavnom programe sú globálne pre všetky funkcie a
procedúry.
Pamäťové triedy
určujú v ktorej časti pamäte bude premenná
umiestnená a kde bude viditeľná
auto
extern
static
register
Trieda auto
automatické premenné
implicitne pre lokálne premenné
uložená v zásobníku (stacku)
existuje od vstupu do funkcie do jej konca
nie je automaticky inicializovaná (obsahuje náhodnú
hodnotu)
void func()
{
auto int i;
auto int j = 5;
}
je
ekvivalentné
void func()
{
int i;
int j = 5;
}
Trieda extern
implicitne pre globálne premenné
uložená v dátovej oblasti
používa sa pri oddelenom preklade súborov, kde viac súborov
zdiela jednu premennú
v jednom súbore je táto premenná definovaná bez kľúčového slova
extern, v ostatných súboroch musí byť použité extern
int suma;
v súbore
s1.c
definícia
extern int suma;
v súbore
s2.c
deklarácia
Trieda static
neexistuje žiadna implicitná definícia-kľúčové slovo musí byť uvedené
premenné tejto triedy sú uložené v dátovej oblasti
najčastejšie lokálne premenné (definované vo funkcii), ktoré si
nechávajú svoju hodnotu medzi jednotlivými volaniami funkcie
premenná existuje od prvého volania funkcie do konca programu
void f() {
int x = 2;
static int i = 0;
printf("i: %d, x: %d n", i, x);
i++; x++;
}
for(j = 0; j < 3; j++) f();
i: 0, x: 2
i: 1, x: 2
i: 2, x: 2
Trieda static
globálne premenné: tiež static - viditeľné len v
module, kde sú definované
ak viac static premenných, radšej každú na zvlášť
riadku
static int i, j; static int i;
static int j;
Trieda registerjazyk C - nízkoúrovňový a preto umožňuje, aby premenná bola
zapísaná v registri
ak sa dá
do ktorého registra - vyberá si prekladač
iba lokálne premenné
tie, ku ktorým je vhodné pristupovať rýchlo
nemôžeme získať adresu registrovej premenej
globálna premenná typu register neexistuje !
register int i;
register int i;
register int j;
ak je viac premenných,
označenie triedy
register vyznačiť pre
každú premennú zvlášť
Príklad použitia triedy register
void nasobilka(register int k)
{
register int i;
for (i = 1; i <= 10; i++)
printf("%2d x %2d = %2d n", i, k, i * k);
}
násobky čísla k
Typové modifikátory
ľubovoľná premenná nejakého dátového typu
(int i) zaradená do nejakej pamäťovej triedy
(napr. static) môže byť modifikovaná typovým
modifikátorom:
const
volatile
static const unsigned int j = 5;
napríklad:
Modifikátor const
v ANSI C
po inicializácii už nemôže byť menená hodnota premennej
podobne ako konštanta (#define), len má určený typ, čo
konštanta nemá (dá sa využiť ku kontrolám prekladača (napr.
typ skutočných parametrov funkcie))
najčastejšie: pri definícii formálnych parametrov funkcie -
parameter označený ako const je len vstupným parametrom
(vo funkcii sa nemení)
int hladaj(const char *str, char co)
napríklad:
Modifikátor const
 časté chyby:
const float pi = 3.14159;
const int max = 100;
int pole[max];
pi = 3.14;
chyba: pi sa už nedá
meniť
chyba: max nie je
konštanta
Modifikátor volatile
v ANSI C
málo časté
upozorňuje prekladač, že premenná môže byť modifikovaná nejakou
bližšie nešpecifikovanou asynchrónnou udalosťou (napr. pomocou
prerušenia)
napr. cyklus (neobsahujúci premennú pocet), ktorý je závislý na
premennej pocet a tá je menená hardverovým prerušením
ak by nebola označená modifikátorom volatile - prekladač by to
mohol optimalizovať tak, že by premennú pocet nahradil jej
hodnotou, akú mala pred cyklom
príklad modifikátor volatile
volatile int pocet;
void wait(int maximum)
{
pocet = 0;
while (pocet < maximum)
;
}
cyklus skončí po zmene premennej
pocet nejakým hardverovým
prerušením
Bloky
blok programu - uzatvorený v { } môže
obsahovať definície premenných
lokálne premenné (auto, alebo static)
viditeľné sú len v bloku if (i > 0) {
int i;
...
}
else {
double f;
...
}
Oblasť platnosti identifikátorov zhrnutie
globálne a lokálne premenné
pamäťové triedy:
auto (implicitne lokálne premenné, v stacku)
extern (implicitne globálne premenné, v dátovej oblasti)
static (lokálne premenné: zachovávajú hodnotu medzi
volaniami funkie, globálne premenné: platnosť v rámci viacerých
súborov)
register (lokálne premenné, zapísané v registri)
typové modifikátory:
const (konštantné premenné, nemenia hodnotu)
volatile (lokálne premenné, zmena hardverovým prerušením)
Oddelený preklad súborov
rozdeliť program na viac čo najmenej závislých
častí
definovať rozhranie - spôsob komunikácie medzi
oddelenými časťami (.h súbory)
pomocou funkcií (lepšie ako pomocou globálnych
premenných viditeľných vo všetkých súboroch)
Rozšírenie platnosti globálnej
premennej
globálna premenná:
definovaná v jednom súbore
deklarovaná pomocou extern v ostatných súboroch
Príklad: rozšírenie platnosti
globálnej premennej
int x;
extern double f;
int fun(void)
{
return (x + (int) f);
}
#include <stdio.h>
extern int x;
extern int fun(void);
double f;
void main()
{
x = 3;
f = 3.5;
printf("%d n", fun());
}
A.c: B.c:
definície
deklarácie
Statické globálne premenné a
funkcie
trieda static - viditeľné len v súbore, v ktorom
boli definované
pre globálne premenné
pre funkcie
Výhodné označenie, ak na programe pracuje viac
programátorov – nemusia sa obávať, že zvolia rovnaké
mená pre identifikátory
príklad statické globálne premenné a funkcie
static int x;
extern double f;
static int fun(void)
{
return x;
}
static int funkcia(void)
{
return (x + (int) f);
}
#include <stdio.h>
extern int x;
extern int funkcia(void);
double f;
static void fun(void) {
prinftf("%d n", funkcia());
}
void main() {
x = 3;
f = 3.5;
printf("%d n", fun());
}
A.c: B.c:
pri linkovaní chyba:
x: v A.c static
v B.c len deklarácia
Zdrojové a hlavičkové súbory
.c súbory - definície globálnych premenných a
funkcií:
pre všetky moduly (žiadne označenie)
len pre aktuálny modul (označenie static)
.h súbory - definujú rozhranie, t.j. definujú globálne
premenné a funkcie, ktoré sa používajú v iných
moduloch (označenie extern)
.c súbory include-ujú len .h súbory ktoré potrebujú
(nikdy ne-include-ujú .c súbory)
Ako udržať poriadok vo veľkom
programe
1. definície funkcií a premenných v súbore program_1.c
2. v program_1.c - striktrne rozlíšené, čo sa bude používať v rámci
súboru a čo mimo neho (čo najmenej)
3. všetky ostatné globálne premenné a funkcie označiť static
4. funkčné prototypy(hlavičky) zdielaných funkcií a premenných - do
program_1.h, označíme ich extern
5. ak poskytujeme aj symbolické konštanty - dáme ich len do
program_1.h
6. program_1.c začína:
#include <stdio.h>
#include "program_1.h"
Ako udržať poriadok vo veľkom
programe
7. súbor program_2.c obsahujúci ďalší súbor programu
a využíva premenné, funkcie alebo konštanty zo
súboru program_1, začína:
#include <stdio.h>
#include "program_1.h„ zdielané funkcie a premenné
#include "program_2.h„ deklarácia vlastného súboru
Odporučený obsah .c súborov
1. dokumentačná časť
(meno súboru, verzie, stručný popis modulu, meno
autora a dátum)
2. všetky potrebné #include
len súbory .h, nie .c!
najprv systémové < > a potom vlastné " "
3. deklarácie importovaných objektov
len ak nie sú v .h súbore spolupracujúceho modulu (čomu
dávame prednosť) - v iných moduloch sú tieto objetky bez
špecifikovanej triedy
4. definície globálnych premenných
premenné definované mimo funkcií zdielané inými
modulmi (čo najmenej!)
Odporučený obsah .c súborov
5. lokálne #define
definícia konštánt a makier len pre aktuálny modul
len ak veľmi rozsiahle - do zvlášť .h
6. definície lokálnych typov
typedef len pre aktuálny modul
len ak veľmi rozsiahle - do zvlášť .h
7. definície premenných len pre aktuálny modul
globálne len pre aktuálny modul - static
8. úplné funkčné prototypy funkcií len pre aktuálny modul
9. funkcia main()- iba ak v súbore existuje
10. definície (globálnych) funkcií - aj pre iné moduly
11. definície funkcií len pre aktuálny modul
Odporučený obsah .h súborov
1. dokumentačná časť
(meno súboru, verzie, stručný popis modulu, meno autora a
dátum)
2. definície symbolických konštánt ktoré sa budú používať aj v
iných moduloch
3. definície makier s parametrami, ktoré sa budú používať aj v
iných moduloch
4. definície typov, ktoré sa budú používať aj v iných moduloch
5. deklarácie premenných aktuálneho modulu, ktoré sa budú
používať v iných moduloch (tu označené extern)
6. funkčné prototypy funkcií aktuálneho modulu, ktoré sa budú
používať v iných moduloch (tu označené extern)
príklad oddelený preklad
program na výpočet obsahu a obvodu kruhu:
kruh_main.c, kruh_main.h, kruh_io.c, kruh_io.h
globálne premenné a
funkcie
lokálne premenné a
funkcie
kruh_mai
n
double obvod
double
vyp_priemer(double
polomer)
double polomer, obsah
void vyp_obsah(double
polomer)
doble vyp_obvod()
void vypocet(void)
kruh_io double vstup_dat()
double
vystup_dat(double
obsah)
double polomer
premenné a funkcie definované v jednom z modulov - môžu sa
používať aj v rámci druhého modulu
#include <stdio.h>
#include "kruh_main.h"
#include "kruh_io.h"
double obvod;
#define pi 3.14;
static double polomer;
static double obsah;
double vyp_priemer(double
polomer);
static void vyp_obsah
(double polomer);
static doble vyp_obvod();
static void vypocet(void);
void main() {
polomer = vstup_dat();
if (polomer == CHYBA_DAT)
printf("Chybny polomer.");
else {
vypocet();
vystup_dat(obsah);
}
}
static void vyp_obsah(double
polomer)
{
obsah = PI * polomer *polomer;
}
static doble vyp_obvod()
{
return(PI*vyp_priemer(polomer));
}
static void vypocet(void)
{
obvod = vyp_obvod();
vyp_obsah(polomer);
}
double vyp_priemer(double polomer)
{
return (2 * polomer);
}
kruh_main.cglob. definície
extern double obvod;
extern double vyp_priemer(double polomer);
kruh_main.h
Hlavičkový súbor modulu
kruh_main
deklarácie premenných a funkcií aktuálneho modulu,
ktoré sa budú používať v iných moduloch
(tu označené extern)
#include <stdio.h>
#include "kruh_io.h"
#include "kruh_main.h"
#define kontrola(x) ((x >= 0.0) ? x : CHYBA_DAT)
static double polomer;
double vstup_dat(void) {
printf("Zadaj polomer kruznice: ");
scanf("%lf", &polomer);
return kontrola(polomer);
}
void vystup_dat(double obsah) {
double priemer;
printf("Obsah kruhu s polomerom %6.2f je %.2fn",
polomer, obsah);
priemer = vyp_priemer(polomer);
printf("Obvod kruhu s polomerom %6.2f je %.2fn",
polomer, obvod);
}
glob. definície
kruh_io.c
#define CHYBA_DAT -1
extern double vstup_dat();
extern double vystup_dat(double obsah);
Hlavičkový súbor modulu
kruh_io
deklarácie premenných a funkcií aktuálneho modulu,
ktoré sa budú používať v iných moduloch
(tu označené extern)
kruh_io.h
#include <stdio.h>
#include "kruh_io.h"
#include "kruh_main.h"
#define kontrola(x) ((x >= 0.0) ? x : CHYBA_DAT)
static double polomer;
double vstup_dat(void) {
printf("Zadaj polomer kruznice: ");
scanf("%lf", &polomer);
return kontrola(polomer);
}
void vystup_dat(double obsah) {
double priemer;
printf("Obsah kruhu s polomerom %6.2f je %.2fn",
polomer, obsah);
priemer = vyp_priemer(polomer);
printf("Obvod kruhu s polomerom %6.2f je %.2fn",
polomer, obvod);
}
kruh_io.c
static void vyp_obsah(double
polomer)
{
obsah = PI * polomer *polomer;
}
static doble vyp_obvod()
{
return(PI*vyp_priemer(polomer));
}
static void vypocet(void)
{
obvod = vyp_obvod();
vyp_obsah(polomer);
}
double vyp_priemer(double polomer)
{
return (2 * polomer);
}
#include <stdio.h>
#include "kruh_main.h"
#include "kruh_io.h"
double obvod;
#define pi 3.14;
static double polomer;
static double obsah;
static void vyp_obsah
(double polomer);
static doble vyp_obvod();
static void vypocet(void);
void main() {
polomer = vstup_dat();
if (polomer == CHYBA_DAT)
printf("Chybny polomer.");
else {
vypocet();
vystup_dat(obsah);
}
} kruh_main.c
extern double obvod;
extern double vyp_priemer(double polomer);
kruh_main.h
#define CHYBA_DAT -1
extern double vstup_dat();
extern double vystup_dat(double obsah);
kruh_io.h
Oddelený preklad
Visual C++ a oddelený preklad
 vytvorenie projektu
(Win32 Console Application)
 vloženie súboru
 C++ Source File
 C/C++ Header File
 Menu Build
1. Build program.exe
2. Compile program.exe
Opakovanie
Operátory
Operátory rozdeľujeme podľa počtu operandov
(arity) na operátory unárne, binárne a ternálne.
Binárne operátory sú aritmetické, relačné,
logické, bitové, operátory priradenia a posuvu.
Operátory majú svoju prioritu a asociativitu.
Priorita určuje, že napríklad násobenie sa
vyhodnotí skôr, ako sčítanie. Asociativita určuje,
smer vyhodnocovania t.j. či sa výraz vyhodnocuje
zľava doprava, alebo naopak.
Operátory
Operátory delíme podľa pozície ich zápisu
vzhľadom k operandu(-om). Takto rozlišujeme
operátory prefixové, infixové a postfixové.
Operátory v jednotlivých prípadoch zapisujeme
pred operandy, medzi operandy, alebo za
operandy. Druhá varianta je nám zrejme
najbližšia. Infixový spôsob zápisu sme používali
už na základnej skole.
V jazyku C uplatníme všetky zmienené varianty
operátorov.
Unárne operátory
+,- aritmetické plus a mínus
& získanie adresy objektu
* získanie objektu podľa adresy
! logická negácia
~ bitová negácia
++,- - inkrementácia, dekrementácia hodnoty, prefixový
i postfixový zápis
(typ) pretypovanie na typ v zátvorke
sizeof operátor na získanie dĺžky objektu, alebo typu
Binárne operátory
= priradenie, možná je i kombinácia s inými
operátormi, napr. +=, -=, *=, /=, <<=, ^=
+ sčítanie
- odčítanie
* násobenie
/ delenie (podľa typu operandov)
% zvyšok po celočíselnom delení (modulo)
Binárne operátory
. bodka, priamy prístup k členu štruktúry
-> nepriamy prístup k členu štruktúry
, čiarka
< > menšie ako väčšie ako
<= >= menšie alebo rovné väčšie alebo rovné
== rovnosť
!= nerovnosť
Binárne operátory
<<, >> bitový posun vľavo, resp. vpravo
& bitový súčin (and)
| bitový súčet (or)
^ bitový exkluzívny súčet (xor)
&& logický súčin
|| logický súčet
Časté chyby – riadiace štruktúry
skrátené vyhodnocovanie zložených výrazov
if (i=100) chyba !
for (i=1; i==10; i++) chyba !
int i;
char c, str[10], *r;
r = (char *) malloc(5*sizeof(char));
scanf("%d", &i);
scanf("%c", &c);
scanf("%s", str);
scanf("%s", r);
scanf očakáva adresy
premenných, do ktorých má
zapísať načítanú hodnotu
vo funkcii scanf sa vytvorí lokálna
premenná ako kópia parametra -
adresa, tam sa zapíše načítaná
hodnota
keď skončí funkcia, zabudne sa
lokálna kópia, teda zabudne sa
adresa, no na tej adrese zostane
načítaná hodnota
i - premenná,
&i - adresa premennej,
c - premenná,
&c - adresa premennej,
str - statická adresa poľa
(reťazca znakov)
r - adresa poľa (reťazca znakov)
príklad typová konverzia
#include <stdio.h>
int main(void) {
int i, j;
float f;
i = 5, j = 2; /* pouzitie operatora ciarky */
f = (float) i / j;
printf("Typova konverzia - 1. moznost: %lfn", f);
f = i / (float) j;
printf("Typova konverzia- 2. moznost: %lfn", f);
f = (float) i / (float) j;
printf("Typova konverzia - 3. moznost: %lfn", f);
return 0; }
príklad typová konverzia
....
f = (float) (i / j);
printf("Explicitna typova konverzia - chybny sposob:
%lfn", f);
f = i / j;
printf("Implicitna typova konverzia - chybny sposob:
%lfn", f);
....
príklad
vrátenie prečítaného znaku späť na vstup
#include <stdio.h>
int main(void)
{
FILE *fr;
int c, cislo, suma = 0;
if ((fr = fopen("CISLA.TXT", "r")) == NULL) {
printf("Subor CISLA.TXT sa nepodarilo otvoritn");
return 1; }
while (1) {/* citanie uvodnych znakov '*' */
while ((c = getc(fr)) == '*')
;
if (c == EOF) break;
príklad
vrátenie prečítaného znaku späť na vstup
ungetc(c, fr);
/*vratenie prveho znaku cisla spat do suboru*/
fscanf(fr, "%dn", &cislo);
suma += cislo; }
printf("Sucet cisel je: %dn", suma);
if (fclose(fr) == EOF)
printf("Subor CISLA.TXT sa nepodarilo uzavrietn");
return 0; }
využitie makier isdigit(),isalpha(),
toupper()
#include <stdio.h>
#include <ctype.h>
#define EOLN 'n'
int main(void) {
int c, cislica = 0;
printf("Zadaj nejake znaky:n");
while ((c = getchar()) != EOLN) {
if (isdigit(c))
cislica++;
if (isalpha(c))
putchar(toupper(c)); }
printf("nNa vstupnom riadku bolo %d cislicn", cislica);
char najcastejsie_pismeno(char *str, int *pocet)
{
int hist['Z'-'A'+1], i, i_max;
for (i=0; i<'Z'-'A'+1; i++)
hist[i] = 0;
for (i=0; i<strlen(str); i++)
hist[toupper(str[i])-'A']++;
i_max = 0;
for (i=0; i<'Z'-'A'+1; i++)
if (hist[i]>hist[i_max])
i_max = i;
*pocet = hist[i_max];
return (i_max + 'A');
}
char str[10], pismeno;
int pocet;
...
pismeno = najcastejsie_pismeno(str, &pocet);
x = 11;
y = 4;
if (x && y)
printf("*");
if (x & y)
printf("+");
Čo vypíše táto časť programu?
Pomôcka:
11 = (1011)2
4 = (100)2
Logický súčin (&&): nenulové čísla sú PRAVDA,
11, 4 sú nenulové, preto výsledok je PRAVDA →
vypíše sa *
Bitový súčin (&): súčin po bitoch 0: NEPRAVDA →
+ sa nevypíše
Vypíše sa *
int **p, *q, r;
p: ukazovateľ
na ukazovateľ
na int
q: ukazovateľ
na int
r: int
17 51 67
p = &q;
51
q = &r;
67 5
r = 5;
printf("%p %p %p %p %p %d %p %d %d",
&p, &q, &r, p, q, r, *p, *q, **p);
17 51 67 51 67 5 67 5 5
& - vráti adresu premennej
bez operátora - hodnota
premennej (ak je hodnotou
adresa, tak je to adresa)
* - vráti hodnotu
premennej vezme ako
adresu a z tej adresy
vráti hodnotu
Ukazovatele a polia
int *p, q[5], i=4;
for (i=0; i<5; i++) q[i] = i;
19 57 59 61 63 65 103
57
p:
ukazovateľ na
int
q: statický ukazovateľ na
int
q[0]: int
q[1]: int
q[4]: int
i: int
p = q;
4
p = q+2; /* to iste ako p = &q[2] */
61
i = *(q+2); /* to iste ako i = q[2] */
20 1 2 3 4
Dvojrozmerné pole
.
definícia (M, N sú
konštanty)
načítanie prvkov poľa
int pole[M][N];
for (i=0; i<M; i++)
for (j=0; j<N; j++)
scanf("%d",&pole[i][j]);
príklad stránkovanie
Napíšte program, ktorý bude
vypisovať postupne vždy jednu
stránku zo súboru. Po stlačení
klávesy Enter vypíše ďalšiu, atď.
Počet riadkov na stránke bude
určený konštantou.
#include <stdio.h>
#define RIADKY_OBR 5
#define MENO "SUBOR.TXT"
void vypis(FILE *fr);
int main(void)
{
FILE *fr;
if ((fr = fopen(MENO, "r")) == NULL) {
printf("Subor %s nebol otvoreny.n", MENO);
return 1;
}
vypis(fr);
if (fclose(fr) == EOF)
printf("Subor %s nebol zatvoreny.n", MENO);
return 0;
}
/* vypis souboru */
void vypis(FILE *fr)
{
int c, pocet = 0;
while ((c = getc(fr)) != EOF) {
putchar(c);
if (c == 'n') {
if (++pocet >= RIADKY_OBR) {
pocet = 0;
while (getchar() != 'n')
;
}
}
}
}
zoznam záznamov
o knihách (pole)
Kartotéka v knižnici
Joseph Heller
Hlava XXII
1961
položky jedneho záznamu
Názov knihy
Meno autora
Rok
jeden záznam o jednej knihe
(obsahujúci všetky položky)
príklad kartotéka v knižnici – štruktúra v poli
Program načíta celé číslo n, následne
načíta n záznamov o knihách a uloží ich
do poľa. Potom ponúkne používateľovi
menu, kde môže pridávať záznam na
koniec, zmazať ktorýkoľvek záznam a
ukončiť program.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define N 50 /* dlzka retazcov znakov */
#define K 50 /* max. pocet prvkov v kartoteke */
typedef struct {
char meno[N];
char priezvisko[N];
} AUTOR;
typedef struct {
char nazov[N];
AUTOR autor;
int rok;
} KNIHA;
/* nacitanie a pridanie zaznamu na koniec zoznamu*/
void pridaj(KNIHA kniznica[], int *n);
/* nacitanie indexu zaznamu a jeho zmazanie */
int zmaz(KNIHA kniznica[], int n);
/* vypis zoznamu */
void vypis(KNIHA kniznica[], int n);
int main()
{
int i, n;
char c;
KNIHA kniznica[K];
printf("Zadajte pocet knih: ");
scanf("%d", &n);
if (n > K)
return 1;
i = 0; /* nacitanie zaznamov do zoznamu */
while (i < n)
pridaj(kniznica, &i);
do {
vypis(kniznica, n);
printf("p: pridanienz: zmazanienk: koniecn");
c = tolower(getch());
switch(c) {
case 'p': pridaj(kniznica, &n); break;
case 'z': n = zmaz(kniznica, n); break;
}
} while (c != 'k');
return 0;
}
void pridaj(KNIHA kniznica[], int *n)
{
if ((*n+1) > K) {
printf("Kniznica je plna.n");
return;
}
else {
printf("Zadajte nazov knihy, autora (meno, ");
printf("priezvisko) a rok vydania:n");
scanf("%s %s %s %d", kniznica[*n].nazov,
kniznica[*n].autor.meno,
kniznica[*n].autor.priezvisko,
&kniznica[*n].rok);
(*n)++;
}
}
int zmaz(KNIHA kniznica[], int n)
{
int i;
printf("Zadajte index zaznamu na zmazanie: ");
scanf("%d", &i);
if (i < 0 || i >= n-1) {
printf("Prvok sa v poli nenachadza.n");
return n;
}
while (i < n-2) {
kniznica[i] = kniznica[i+1];
i++;
}
return n-1;
}
void vypis(KNIHA kniznica[], int n)
{
int i;
printf("nKNIZNICAnn");
for (i=0; i<n; i++)
printf("%s %s: %s (%d)n", kniznica[i].autor.meno,
kniznica[i].autor.priezvisko, kniznica[i].nazov,
kniznica[i].rok);
printf("nn");
}
príklad Zlomky
oddelený preklad:
modul zlomky: zlomky.c a zlomky.h
modul hlavny: hlavny.c
typedef struct {
int citatel;
int menovatel;
} ZLOMOK;
extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b);
extern void vypis(ZLOMOK a);
zlomky.h
#include <stdio.h>
#include "zlomky.h"
ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b) {
int n;
ZLOMOK *z = (ZLOMOK *) malloc(sizeof(ZLOMOK);
z->citatel = a->citatel* b->menovatel +
b->citatel * a->menovatel;
z->menovatel = a->menovatel * b->menovatel;
n = nsd(z->citatel, z->menovatel);
z->citatel /= n;
z->menovatel /= n;
return z;
}
void vypis(ZLOMOK *a) {
printf("%d / %dn", a->citatel, a->menovatel);
}
static int nsd(int a, int b) {
/*... */
}
zlomky.c
#include <stdio.h>
#include "zlomky.h"
int main() {
ZLOMKY *x, *y, *z;
x = (ZLOMOK *) malloc(sizeof(ZLOMOK));
y = (ZLOMOK *) malloc(sizeof(ZLOMOK));
printf("Zadajte dva zlomky: ");
scanf("%d / %d", &x->citatel, &x->menovatel);
scanf("%d / %d", &y->citatel, &y->menovatel);
z = spocitaj(x, y);
printf("Sucet zlomkov je: ");
vypis(z);
return 0;
}
hlavny.c
#include <stdio.h>
#include "zlomky.h"
ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b) {
int n;
ZLOMOK *z = (ZLOMOK *) malloc(sizeof(ZLOMOK);
z->citatel = a->citatel + b->citatel;
z->menovatel = a->menovatel + b->menovatel;
n = nsd(z->citatel, z->menovatel);
z->citatel /= n;
z->menovatel /= n;
}
void vypis(ZLOMOK *a) {
printf("%d / %dn", a->citatel, a->menovatel);
}
static int nsd(int a, int b) {
}
#include <stdio.h>
#include "zlomky.h"
int main() {
ZLOMKY *x, *y, *z;
x = (ZLOMOK *) malloc(sizeof(ZLOMOK));
y = (ZLOMOK *) malloc(sizeof(ZLOMOK));
printf("Zadajte dva zlomky: ");
scanf("%d %d", &x->citatel, &x->menovatel);
scanf("%d %d", &y->citatel, &y->menovatel);
z = spocitaj(x, y);
printf("Sucet zlomkov je: ");
vypis(z);
return 0;
}
typedef struct {
int citatel;
int menovatel;
} ZLOMOK;
extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b);
extern void vypis(ZLOMOK a);
zlomky.c
zlomky.h
hlavny.c
príklad rozvrh
dvojrozmerné pole
práca so súborom
štruktúra
parametre funkcie main
Program načíta zo súboru
údaje o hodinách v rozvrhu
a vypíše rozvrh na
obrazovku
Po
Ut
St
Št
Pi
So
Ne
Matematika
Mrkvička
3 hodiny
Vstupný súbor a štruktúra
Súbor:
deň hodina
skratka predmetu
meno učiteľa
počet hodín
Štruktúra:
predmet
ucitel
cast:
 -1: voľno
 0: začiatok vyuč. hodiny
 1: stred alebo koniec vyuč.hodiny
0 1
MAT
Maly
4
1 3
FYZ
Velky
2
2 2
ANG
Pekna
1
2 3
TEL
Vesely
3
4 3
SJ
Zeleny
1
vyuč. hodina: 4
riadne hodiny →
4 záznamy:
MAT
Maly
0
MAT
Maly
1
MAT
Maly
1
MAT
Maly
1
ROZVRH
-----------------------------------------------------------------------
| Pondelok| MAT, Maly | |
-----------------------------------------------------------------------
| Utorok| | | FYZ,Velky | |
-----------------------------------------------------------------------
| Streda| | ANG,Pekna| TEL,Vesel |
-----------------------------------------------------------------------
| Stvrtok| | | | | |
-----------------------------------------------------------------------
| Piatok| | | SJ,Zelen| | |
-----------------------------------------------------------------------
| Sobota| | | | | |
-----------------------------------------------------------------------
| Nedela| | | | | |
-----------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#define N 6 /* pocet pismen v slove (5 znakov) */
#define ND 7 /* pocet dni */
#define NH 5 /* pocet hodin */
#define SUBOR "subor.txt" /* default nazov suboru */
typedef enum {
pondelok, utorok, streda, stvrtok,
piatok, sobota, nedela
};
typedef struct {
char predmet[N];
char ucitel[N];
int cast; /* -1 volno, 0 zaciatok, 1 stred,koniec */
} HODINA;
char *dni[] = {"Pondelok", "Utorok", "Streda", "Stvrtok",
"Piatok", "Sobota", "Nedela"};
void inicializuj(HODINA rozvrh[][NH], int ND);
int nacitaj(HODINA rozvrh[][NH], int ND, char subor[]);
void vypis(HODINA rozvrh[][NH], int ND);
int main (int argc, char *argv[]) {
HODINA rozvrh[ND][NH];
char subor[N];
if (argc == 2)
strcpy(subor, argv[1]);
else
strcpy(subor, SUBOR);
inicializuj(rozvrh);
if (nacitaj(rozvrh, subor)) {
return 1;
}
vypis(rozvrh);
return 0;
}
void inicializuj(HODINA rozvrh[][NH], int ND) {
int i, j;
for(i=0; i<ND; i++)
for(j=0; j<NH; j++)
rozvrh[i][j].cast = -1;
}
/* nacitanie rozvrhu zo suboru */
int nacitaj(HODINA rozvrh[][NH], int ND, char subor[]) {
int i, den, hodina, dlzka;
FILE *f;
if ((f = fopen(subor, "r")) == NULL) {
printf("Nepodarilo sa otvorit subor %s.n", subor);
return 1;
}
while(!feof(f)) {
fscanf(f, "%d %d", &den, &hodina);
den--; hodina--;
fscanf(f, "%s", rozvrh[den][hodina].predmet);
if (strlen(rozvrh[den][hodina].predmet) > 5)
rozvrh[den][hodina].predmet[5] = '0'; /*5 zn.*/
fscanf(f, "%s", rozvrh[den][hodina].ucitel);
if (strlen(rozvrh[den][hodina].ucitel) > 5)
rozvrh[den][hodina].ucitel[5] = '0'; /*5 zn.*/
fscanf(f, "%d", &dlzka);
rozvrh[den][hodina].cast = 0; /*zaciatok vyuc. h.*/
/* ak ma vyuc.hod. viac ako 1 hodinu,
naplnia sa dalsie zaznamy */
if (dlzka > 1) {
for (i=1; i<dlzka && hodina+i < NH; i++) {
rozvrh[den][hodina+i] = rozvrh[den][hodina];
rozvrh[den][hodina+i].cast = 1;
}
}
}
return 0;
}
void vypis(HODINA rozvrh[][NH], int ND) {
int i, j;
printf("nROZVRHnn");
for(i=0; i<ND; i++) {
/* horna ciara + ciary oddelujuce dni */
for(j=0; j<NH*12+1+10; j++)
putchar('-');
printf("n|%9s", dni[i]); /* oznacenie dna */
/* riadok */
for(j=0; j<NH; j++) {
if (j == 0 || rozvrh[i][j].cast < 1)
putchar('|'); /* ciara pred vyuc. hod. */
else
putchar(' '); /* vo vnutri v.h. ' ' */
if (rozvrh[i][j].cast == 0) /* vypis udajov */
printf("%5s,%5s", rozvrh[i][j].predmet,
rozvrh[i][j].ucitel);
else
printf(" "); /* medzery */
if (j == NH-1)
putchar('|'); /* koniec dna */
}
putchar('n'); /* prechod na dalsi riadok-den */
}
/* dolna ciara */
for(j=0; j<NH*12+1+10; j++)
putchar('-');
printf("n");
}
príklad bitové operácie
 Vytvorte program predstavujúci kalkulačku v dvojkovej sústave.
 a. V premennej hodnota si pamätajte aktuálnu hodnotu. Na začiatku túto hodnotu
inicializujte na 1.
 Tú umožnite násobit’ dvoma a delit’ dvoma (celočíselne). Pri násobení dvoma
skontrolujte, či číslo „nepretečie“- ak by to malo nastat’, vypíšte chybovú správu
Operaciu nie je mozne vykonat
 b. Do kalkulačky pridajte funkciu na pripočítavanie načítaného čísla. Tiež kontrolujte
pretečenie.
 Pripočítavajte po bitoch.
 Program bude na vstupe dostávať príkazy:
 C – na načítanie čísla do premennej hodnota. N – na násobenie dvoma. D – na
delenie dvoma. P – na pripočítavanie zadaného čísla. O – na odpočítavanie zadaného
čísla.
 K – na ukončenie programu.
#include <stdio.h>
#define RAD(x,i) (((x)>>(i))&1) // vrati cislicu i-teho radu
cisla x
#define VYTVORIT_CISLO(i) (1<<(i)) // vytvori cislo s 1 na mieste
i, ostatne su 0
//vypise cislo v dvojkovej sustave
void vypis2(unsigned x)
{
if (x>0)
{
vypis2(x>>1);
printf("%d",x&1);
}
}
void vypis(unsigned hodnota)
{ printf("Aktualna hodnota: %un",hodnota);}
unsigned sucet(unsigned a, unsigned b)
{ unsigned x=0,zv=0;
unsigned i;
unsigned s=0;
for (i=0;i<sizeof(x)*8;i++)
{ s=RAD(a,i)+RAD(b,i)+zv;
if (RAD(s,1)==1)
{ zv=1;
s&=(~VYTVORIT_CISLO(1));}
else {zv=0;}
if (RAD(s,0))
{x|=VYTVORIT_CISLO(i);}
}if (zv==0) {return x;}
else { printf("Operaciu nie je mozne vykonatn");
return a;}
}
unsigned rozdiel(unsigned a, unsigned b){
unsigned x=0,zv=0;
unsigned i;
unsigned s=0;
for (i=0;i<sizeof(x)*8;i++){
s=RAD(b,i)+zv;
zv=0;
if (RAD(s,1)==1) {
zv++;
s&=(~VYTVORIT_CISLO(1));
s&=(~VYTVORIT_CISLO(0)); }
if (RAD(a,i)<s){
s=0;
zv++;
x|=VYTVORIT_CISLO(i);}
else
if (RAD(a,i)>s)
{
x|=VYTVORIT_CISLO(i);
}
}
if (zv==0)
{
return x;
}
else
{
printf("Operaciu nie je mozne vykonatn");
return a;
}
int main()
{ char c;
unsigned hodnota=1,cislo;
while (1)
{ while ((c=getchar())=='n')
;
switch (c){
case 'C': // nacitanie hodnoty
scanf("%u",&hodnota);
vypis(hodnota);
break;
case 'N': // nasobenie dvomi
if (RAD(hodnota,sizeof(hodnota)*8-1))
{printf("Operaciu nie je mozne vykonatn");}
else{ hodnota<<=1;
vypis(hodnota);}
case 'D': // delenie dvomi
hodnota>>=1;
vypis(hodnota);
break;
case 'P': // pripocitanie
scanf("%u",&cislo);
hodnota=sucet(hodnota,cislo);
vypis(hodnota);
break;
case 'O': // odpocitanie
scanf("%u",&cislo);
hodnota=rozdiel(hodnota,cislo);
vypis(hodnota);
break;
case 'K':
return 0; // ukonci program}}

More Related Content

Viewers also liked

управление эффективностью рекламного сообщения, Ребров, Blizko
управление эффективностью рекламного сообщения, Ребров, Blizkoуправление эффективностью рекламного сообщения, Ребров, Blizko
управление эффективностью рекламного сообщения, Ребров, Blizkoweb2win
 
Kreatívna komunikácia za babku
Kreatívna komunikácia za babkuKreatívna komunikácia za babku
Kreatívna komunikácia za babkuEtarget
 
BioKube - Dodatna oprema
BioKube - Dodatna opremaBioKube - Dodatna oprema
BioKube - Dodatna oprema
otpadne-vode
 
Fénix jako symbol v čínské kultuře
 Fénix jako symbol v čínské kultuře  Fénix jako symbol v čínské kultuře
Fénix jako symbol v čínské kultuře Anna Hečková
 
NoSQL databáze, MongoDB
NoSQL databáze, MongoDBNoSQL databáze, MongoDB
NoSQL databáze, MongoDB
Lukas Korous
 
Women´s war
Women´s warWomen´s war
Women´s war
evavotav
 
Sociální média - audit FB
Sociální média - audit FBSociální média - audit FB
Sociální média - audit FBTomáš Marek
 
Religiositas
ReligiositasReligiositas
Religiositas
Projekat Nefertiti
 
Open Data e Open Data Sicilia
Open Data e Open Data SiciliaOpen Data e Open Data Sicilia
Open Data e Open Data Sicilia
Cristiano Longo
 
Chovatelské potřeby
Chovatelské potřebyChovatelské potřeby
Chovatelské potřeby
chovatel
 
Atomicka products presentation
Atomicka  products presentationAtomicka  products presentation
Atomicka products presentation
Atomicka SoftTech Pondicherry
 
What makes a good developer from a management perspective
What makes a good developer from a management perspectiveWhat makes a good developer from a management perspective
What makes a good developer from a management perspective
BrnoPHP
 
Bankovnictví peníze
Bankovnictví   penízeBankovnictví   peníze
Bankovnictví penízeolc_user
 
Anticki hram4
Anticki hram4Anticki hram4
Anticki hram4
art2you
 
C ciz seminar cktzj 2010
C ciz seminar cktzj 2010C ciz seminar cktzj 2010
C ciz seminar cktzj 2010Josef Zemek
 

Viewers also liked (20)

openMagazin 10/2009
openMagazin 10/2009openMagazin 10/2009
openMagazin 10/2009
 
управление эффективностью рекламного сообщения, Ребров, Blizko
управление эффективностью рекламного сообщения, Ребров, Blizkoуправление эффективностью рекламного сообщения, Ребров, Blizko
управление эффективностью рекламного сообщения, Ребров, Blizko
 
Kreatívna komunikácia za babku
Kreatívna komunikácia za babkuKreatívna komunikácia za babku
Kreatívna komunikácia za babku
 
BioKube - Dodatna oprema
BioKube - Dodatna opremaBioKube - Dodatna oprema
BioKube - Dodatna oprema
 
Fénix jako symbol v čínské kultuře
 Fénix jako symbol v čínské kultuře  Fénix jako symbol v čínské kultuře
Fénix jako symbol v čínské kultuře
 
100797
100797100797
100797
 
NoSQL databáze, MongoDB
NoSQL databáze, MongoDBNoSQL databáze, MongoDB
NoSQL databáze, MongoDB
 
Post of ABSRC
Post of ABSRC Post of ABSRC
Post of ABSRC
 
Women´s war
Women´s warWomen´s war
Women´s war
 
Sociální média - audit FB
Sociální média - audit FBSociální média - audit FB
Sociální média - audit FB
 
DíA 1
DíA 1DíA 1
DíA 1
 
Religiositas
ReligiositasReligiositas
Religiositas
 
Open Data e Open Data Sicilia
Open Data e Open Data SiciliaOpen Data e Open Data Sicilia
Open Data e Open Data Sicilia
 
Chovatelské potřeby
Chovatelské potřebyChovatelské potřeby
Chovatelské potřeby
 
Atomicka products presentation
Atomicka  products presentationAtomicka  products presentation
Atomicka products presentation
 
Cepicky osgeocz
Cepicky osgeoczCepicky osgeocz
Cepicky osgeocz
 
What makes a good developer from a management perspective
What makes a good developer from a management perspectiveWhat makes a good developer from a management perspective
What makes a good developer from a management perspective
 
Bankovnictví peníze
Bankovnictví   penízeBankovnictví   peníze
Bankovnictví peníze
 
Anticki hram4
Anticki hram4Anticki hram4
Anticki hram4
 
C ciz seminar cktzj 2010
C ciz seminar cktzj 2010C ciz seminar cktzj 2010
C ciz seminar cktzj 2010
 

Similar to Zppls11 prednaska 2014

Academy vol.13
Academy vol.13Academy vol.13
Academy vol.13
blueweb_sk
 
Tipy a triky na používanie funkcionálnych vlastností Pythonu
Tipy a triky na používanie funkcionálnych vlastností PythonuTipy a triky na používanie funkcionálnych vlastností Pythonu
Tipy a triky na používanie funkcionálnych vlastností Pythonu
sevcech
 
Programovanie v C++
Programovanie v C++Programovanie v C++
Programovanie v C++
Juraj Michálek
 
Interne dsl
Interne dslInterne dsl
There is much more to C
There is much more to CThere is much more to C
There is much more to C
Juraj Michálek
 
Záverečná úloha KPI
Záverečná úloha KPIZáverečná úloha KPI
Záverečná úloha KPIhull666666
 
SecureCam Program Guide
SecureCam Program GuideSecureCam Program Guide
SecureCam Program Guideguest146c167
 

Similar to Zppls11 prednaska 2014 (8)

Academy vol.13
Academy vol.13Academy vol.13
Academy vol.13
 
Tipy a triky na používanie funkcionálnych vlastností Pythonu
Tipy a triky na používanie funkcionálnych vlastností PythonuTipy a triky na používanie funkcionálnych vlastností Pythonu
Tipy a triky na používanie funkcionálnych vlastností Pythonu
 
Programovanie v C++
Programovanie v C++Programovanie v C++
Programovanie v C++
 
Interne dsl
Interne dslInterne dsl
Interne dsl
 
There is much more to C
There is much more to CThere is much more to C
There is much more to C
 
Záverečná úloha KPI
Záverečná úloha KPIZáverečná úloha KPI
Záverečná úloha KPI
 
SecureCam Program Guide
SecureCam Program GuideSecureCam Program Guide
SecureCam Program Guide
 
Cvicenie 9
Cvicenie 9Cvicenie 9
Cvicenie 9
 

Zppls11 prednaska 2014

  • 1. Oddelený preklad, opakovanie v príkladoch Anna Bou Ezzeddine
  • 4. Oddelený preklad vkladanie súborov #include → vznikne jeden .OBJ súbor  Vkladá sa jeden, alebo viac súborov  Nevýhody:  pri zmene v ľubovoľnom súbore musíme zbytočne prekladať aj všetky ostatné  medzi jednotlivými súbormi nie je možné skryť ich globálne identifikátory  oddelený preklad každý súbor sa preloží zvlášť (vznikne viac .OBJ súborov) a potom sa spoja pomocou linkeru možnosť rozdelenia problému na viacero menších nezávislých častí, na ktorých pracuje súčasne viacero programátorov
  • 5. Príklad oddeleného prekladu s2.cs1.c s3.c s1.c s2.c s3.c s.c #include "s1.c" #include "s2.c" #include "s3.c" s.obj s1.obj s2.obj s3.obj link s link s1, s2, s3 vkladanie súborov: oddelený preklad:
  • 6. Oblasť platnosti identifikátorov jazyk C umožňuje rôzne spôsoby ako stanoviť kde, kedy a aký identifikátor bude komu dostupný: globálne a lokálne premenné pamäťové triedy typové modifikátory
  • 7. Globálne premenné organizácia v programe: globálne definície a deklarácie definície funkcií globálne definície: definujú premenné, rozsah ich platnosti: od miesta definície po koniec súboru (nie programu - program sa môže skladať z viac súborov) globálne deklarácie: deklarácie premenných, ktoré sú definované v inom súbore. často sú špecifikované slovom extern - externé deklarácie
  • 8. príklad globálne definície int i; void prva() {...} int j; int druha() {...} char *tretia() {...} premenná i je platná pre všetky 3 funkcie premenná j je platná len pre funkcie: druha() a tretia()
  • 9. Lokálne premenné definované vo funkciách platnosť lokálnych premenných: od definície po koniec funkcie int i1, i2; void prva() { int i1, j1; ...} int j1, j2; int druha(){ int i1, j1, k1; ...} globálna premenná i1 je prekrytá lokálnou premennou i1 (používať sa môžu premenné: i1, j1 (lokálne) a i2 (globálna)) dve globálne premenné: i2, j2 a tri lokálne premenné: i1, j1, k1.
  • 10. Inicializácia lokálnych a globálnych premenných lokálne premenné: nie sú automaticky inicializované globálne premenné: automaticky inicializované na 0 (0.0, 0) (lepšie - nespoliehať sa na to)
  • 11. Upozornenie V jazyku C premenné definované vo funkcii main sú lokálne iba pre túto funkciu Pozor na zvyk z Pascalu, kde premenné definované v hlavnom programe sú globálne pre všetky funkcie a procedúry.
  • 12. Pamäťové triedy určujú v ktorej časti pamäte bude premenná umiestnená a kde bude viditeľná auto extern static register
  • 13. Trieda auto automatické premenné implicitne pre lokálne premenné uložená v zásobníku (stacku) existuje od vstupu do funkcie do jej konca nie je automaticky inicializovaná (obsahuje náhodnú hodnotu) void func() { auto int i; auto int j = 5; } je ekvivalentné void func() { int i; int j = 5; }
  • 14. Trieda extern implicitne pre globálne premenné uložená v dátovej oblasti používa sa pri oddelenom preklade súborov, kde viac súborov zdiela jednu premennú v jednom súbore je táto premenná definovaná bez kľúčového slova extern, v ostatných súboroch musí byť použité extern int suma; v súbore s1.c definícia extern int suma; v súbore s2.c deklarácia
  • 15. Trieda static neexistuje žiadna implicitná definícia-kľúčové slovo musí byť uvedené premenné tejto triedy sú uložené v dátovej oblasti najčastejšie lokálne premenné (definované vo funkcii), ktoré si nechávajú svoju hodnotu medzi jednotlivými volaniami funkcie premenná existuje od prvého volania funkcie do konca programu void f() { int x = 2; static int i = 0; printf("i: %d, x: %d n", i, x); i++; x++; } for(j = 0; j < 3; j++) f(); i: 0, x: 2 i: 1, x: 2 i: 2, x: 2
  • 16. Trieda static globálne premenné: tiež static - viditeľné len v module, kde sú definované ak viac static premenných, radšej každú na zvlášť riadku static int i, j; static int i; static int j;
  • 17. Trieda registerjazyk C - nízkoúrovňový a preto umožňuje, aby premenná bola zapísaná v registri ak sa dá do ktorého registra - vyberá si prekladač iba lokálne premenné tie, ku ktorým je vhodné pristupovať rýchlo nemôžeme získať adresu registrovej premenej globálna premenná typu register neexistuje ! register int i; register int i; register int j; ak je viac premenných, označenie triedy register vyznačiť pre každú premennú zvlášť
  • 18. Príklad použitia triedy register void nasobilka(register int k) { register int i; for (i = 1; i <= 10; i++) printf("%2d x %2d = %2d n", i, k, i * k); } násobky čísla k
  • 19. Typové modifikátory ľubovoľná premenná nejakého dátového typu (int i) zaradená do nejakej pamäťovej triedy (napr. static) môže byť modifikovaná typovým modifikátorom: const volatile static const unsigned int j = 5; napríklad:
  • 20. Modifikátor const v ANSI C po inicializácii už nemôže byť menená hodnota premennej podobne ako konštanta (#define), len má určený typ, čo konštanta nemá (dá sa využiť ku kontrolám prekladača (napr. typ skutočných parametrov funkcie)) najčastejšie: pri definícii formálnych parametrov funkcie - parameter označený ako const je len vstupným parametrom (vo funkcii sa nemení) int hladaj(const char *str, char co) napríklad:
  • 21. Modifikátor const  časté chyby: const float pi = 3.14159; const int max = 100; int pole[max]; pi = 3.14; chyba: pi sa už nedá meniť chyba: max nie je konštanta
  • 22. Modifikátor volatile v ANSI C málo časté upozorňuje prekladač, že premenná môže byť modifikovaná nejakou bližšie nešpecifikovanou asynchrónnou udalosťou (napr. pomocou prerušenia) napr. cyklus (neobsahujúci premennú pocet), ktorý je závislý na premennej pocet a tá je menená hardverovým prerušením ak by nebola označená modifikátorom volatile - prekladač by to mohol optimalizovať tak, že by premennú pocet nahradil jej hodnotou, akú mala pred cyklom
  • 23. príklad modifikátor volatile volatile int pocet; void wait(int maximum) { pocet = 0; while (pocet < maximum) ; } cyklus skončí po zmene premennej pocet nejakým hardverovým prerušením
  • 24. Bloky blok programu - uzatvorený v { } môže obsahovať definície premenných lokálne premenné (auto, alebo static) viditeľné sú len v bloku if (i > 0) { int i; ... } else { double f; ... }
  • 25. Oblasť platnosti identifikátorov zhrnutie globálne a lokálne premenné pamäťové triedy: auto (implicitne lokálne premenné, v stacku) extern (implicitne globálne premenné, v dátovej oblasti) static (lokálne premenné: zachovávajú hodnotu medzi volaniami funkie, globálne premenné: platnosť v rámci viacerých súborov) register (lokálne premenné, zapísané v registri) typové modifikátory: const (konštantné premenné, nemenia hodnotu) volatile (lokálne premenné, zmena hardverovým prerušením)
  • 26. Oddelený preklad súborov rozdeliť program na viac čo najmenej závislých častí definovať rozhranie - spôsob komunikácie medzi oddelenými časťami (.h súbory) pomocou funkcií (lepšie ako pomocou globálnych premenných viditeľných vo všetkých súboroch)
  • 27. Rozšírenie platnosti globálnej premennej globálna premenná: definovaná v jednom súbore deklarovaná pomocou extern v ostatných súboroch
  • 28. Príklad: rozšírenie platnosti globálnej premennej int x; extern double f; int fun(void) { return (x + (int) f); } #include <stdio.h> extern int x; extern int fun(void); double f; void main() { x = 3; f = 3.5; printf("%d n", fun()); } A.c: B.c: definície deklarácie
  • 29. Statické globálne premenné a funkcie trieda static - viditeľné len v súbore, v ktorom boli definované pre globálne premenné pre funkcie Výhodné označenie, ak na programe pracuje viac programátorov – nemusia sa obávať, že zvolia rovnaké mená pre identifikátory
  • 30. príklad statické globálne premenné a funkcie static int x; extern double f; static int fun(void) { return x; } static int funkcia(void) { return (x + (int) f); } #include <stdio.h> extern int x; extern int funkcia(void); double f; static void fun(void) { prinftf("%d n", funkcia()); } void main() { x = 3; f = 3.5; printf("%d n", fun()); } A.c: B.c: pri linkovaní chyba: x: v A.c static v B.c len deklarácia
  • 31. Zdrojové a hlavičkové súbory .c súbory - definície globálnych premenných a funkcií: pre všetky moduly (žiadne označenie) len pre aktuálny modul (označenie static) .h súbory - definujú rozhranie, t.j. definujú globálne premenné a funkcie, ktoré sa používajú v iných moduloch (označenie extern) .c súbory include-ujú len .h súbory ktoré potrebujú (nikdy ne-include-ujú .c súbory)
  • 32. Ako udržať poriadok vo veľkom programe 1. definície funkcií a premenných v súbore program_1.c 2. v program_1.c - striktrne rozlíšené, čo sa bude používať v rámci súboru a čo mimo neho (čo najmenej) 3. všetky ostatné globálne premenné a funkcie označiť static 4. funkčné prototypy(hlavičky) zdielaných funkcií a premenných - do program_1.h, označíme ich extern 5. ak poskytujeme aj symbolické konštanty - dáme ich len do program_1.h 6. program_1.c začína: #include <stdio.h> #include "program_1.h"
  • 33. Ako udržať poriadok vo veľkom programe 7. súbor program_2.c obsahujúci ďalší súbor programu a využíva premenné, funkcie alebo konštanty zo súboru program_1, začína: #include <stdio.h> #include "program_1.h„ zdielané funkcie a premenné #include "program_2.h„ deklarácia vlastného súboru
  • 34. Odporučený obsah .c súborov 1. dokumentačná časť (meno súboru, verzie, stručný popis modulu, meno autora a dátum) 2. všetky potrebné #include len súbory .h, nie .c! najprv systémové < > a potom vlastné " " 3. deklarácie importovaných objektov len ak nie sú v .h súbore spolupracujúceho modulu (čomu dávame prednosť) - v iných moduloch sú tieto objetky bez špecifikovanej triedy 4. definície globálnych premenných premenné definované mimo funkcií zdielané inými modulmi (čo najmenej!)
  • 35. Odporučený obsah .c súborov 5. lokálne #define definícia konštánt a makier len pre aktuálny modul len ak veľmi rozsiahle - do zvlášť .h 6. definície lokálnych typov typedef len pre aktuálny modul len ak veľmi rozsiahle - do zvlášť .h 7. definície premenných len pre aktuálny modul globálne len pre aktuálny modul - static 8. úplné funkčné prototypy funkcií len pre aktuálny modul 9. funkcia main()- iba ak v súbore existuje 10. definície (globálnych) funkcií - aj pre iné moduly 11. definície funkcií len pre aktuálny modul
  • 36. Odporučený obsah .h súborov 1. dokumentačná časť (meno súboru, verzie, stručný popis modulu, meno autora a dátum) 2. definície symbolických konštánt ktoré sa budú používať aj v iných moduloch 3. definície makier s parametrami, ktoré sa budú používať aj v iných moduloch 4. definície typov, ktoré sa budú používať aj v iných moduloch 5. deklarácie premenných aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern) 6. funkčné prototypy funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
  • 37. príklad oddelený preklad program na výpočet obsahu a obvodu kruhu: kruh_main.c, kruh_main.h, kruh_io.c, kruh_io.h globálne premenné a funkcie lokálne premenné a funkcie kruh_mai n double obvod double vyp_priemer(double polomer) double polomer, obsah void vyp_obsah(double polomer) doble vyp_obvod() void vypocet(void) kruh_io double vstup_dat() double vystup_dat(double obsah) double polomer premenné a funkcie definované v jednom z modulov - môžu sa používať aj v rámci druhého modulu
  • 38. #include <stdio.h> #include "kruh_main.h" #include "kruh_io.h" double obvod; #define pi 3.14; static double polomer; static double obsah; double vyp_priemer(double polomer); static void vyp_obsah (double polomer); static doble vyp_obvod(); static void vypocet(void); void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) printf("Chybny polomer."); else { vypocet(); vystup_dat(obsah); } } static void vyp_obsah(double polomer) { obsah = PI * polomer *polomer; } static doble vyp_obvod() { return(PI*vyp_priemer(polomer)); } static void vypocet(void) { obvod = vyp_obvod(); vyp_obsah(polomer); } double vyp_priemer(double polomer) { return (2 * polomer); } kruh_main.cglob. definície
  • 39. extern double obvod; extern double vyp_priemer(double polomer); kruh_main.h Hlavičkový súbor modulu kruh_main deklarácie premenných a funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
  • 40. #include <stdio.h> #include "kruh_io.h" #include "kruh_main.h" #define kontrola(x) ((x >= 0.0) ? x : CHYBA_DAT) static double polomer; double vstup_dat(void) { printf("Zadaj polomer kruznice: "); scanf("%lf", &polomer); return kontrola(polomer); } void vystup_dat(double obsah) { double priemer; printf("Obsah kruhu s polomerom %6.2f je %.2fn", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2fn", polomer, obvod); } glob. definície kruh_io.c
  • 41. #define CHYBA_DAT -1 extern double vstup_dat(); extern double vystup_dat(double obsah); Hlavičkový súbor modulu kruh_io deklarácie premenných a funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern) kruh_io.h
  • 42. #include <stdio.h> #include "kruh_io.h" #include "kruh_main.h" #define kontrola(x) ((x >= 0.0) ? x : CHYBA_DAT) static double polomer; double vstup_dat(void) { printf("Zadaj polomer kruznice: "); scanf("%lf", &polomer); return kontrola(polomer); } void vystup_dat(double obsah) { double priemer; printf("Obsah kruhu s polomerom %6.2f je %.2fn", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2fn", polomer, obvod); } kruh_io.c static void vyp_obsah(double polomer) { obsah = PI * polomer *polomer; } static doble vyp_obvod() { return(PI*vyp_priemer(polomer)); } static void vypocet(void) { obvod = vyp_obvod(); vyp_obsah(polomer); } double vyp_priemer(double polomer) { return (2 * polomer); } #include <stdio.h> #include "kruh_main.h" #include "kruh_io.h" double obvod; #define pi 3.14; static double polomer; static double obsah; static void vyp_obsah (double polomer); static doble vyp_obvod(); static void vypocet(void); void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) printf("Chybny polomer."); else { vypocet(); vystup_dat(obsah); } } kruh_main.c extern double obvod; extern double vyp_priemer(double polomer); kruh_main.h #define CHYBA_DAT -1 extern double vstup_dat(); extern double vystup_dat(double obsah); kruh_io.h Oddelený preklad
  • 43. Visual C++ a oddelený preklad  vytvorenie projektu (Win32 Console Application)  vloženie súboru  C++ Source File  C/C++ Header File  Menu Build 1. Build program.exe 2. Compile program.exe
  • 45. Operátory Operátory rozdeľujeme podľa počtu operandov (arity) na operátory unárne, binárne a ternálne. Binárne operátory sú aritmetické, relačné, logické, bitové, operátory priradenia a posuvu. Operátory majú svoju prioritu a asociativitu. Priorita určuje, že napríklad násobenie sa vyhodnotí skôr, ako sčítanie. Asociativita určuje, smer vyhodnocovania t.j. či sa výraz vyhodnocuje zľava doprava, alebo naopak.
  • 46. Operátory Operátory delíme podľa pozície ich zápisu vzhľadom k operandu(-om). Takto rozlišujeme operátory prefixové, infixové a postfixové. Operátory v jednotlivých prípadoch zapisujeme pred operandy, medzi operandy, alebo za operandy. Druhá varianta je nám zrejme najbližšia. Infixový spôsob zápisu sme používali už na základnej skole. V jazyku C uplatníme všetky zmienené varianty operátorov.
  • 47. Unárne operátory +,- aritmetické plus a mínus & získanie adresy objektu * získanie objektu podľa adresy ! logická negácia ~ bitová negácia ++,- - inkrementácia, dekrementácia hodnoty, prefixový i postfixový zápis (typ) pretypovanie na typ v zátvorke sizeof operátor na získanie dĺžky objektu, alebo typu
  • 48. Binárne operátory = priradenie, možná je i kombinácia s inými operátormi, napr. +=, -=, *=, /=, <<=, ^= + sčítanie - odčítanie * násobenie / delenie (podľa typu operandov) % zvyšok po celočíselnom delení (modulo)
  • 49. Binárne operátory . bodka, priamy prístup k členu štruktúry -> nepriamy prístup k členu štruktúry , čiarka < > menšie ako väčšie ako <= >= menšie alebo rovné väčšie alebo rovné == rovnosť != nerovnosť
  • 50. Binárne operátory <<, >> bitový posun vľavo, resp. vpravo & bitový súčin (and) | bitový súčet (or) ^ bitový exkluzívny súčet (xor) && logický súčin || logický súčet
  • 51. Časté chyby – riadiace štruktúry skrátené vyhodnocovanie zložených výrazov if (i=100) chyba ! for (i=1; i==10; i++) chyba !
  • 52. int i; char c, str[10], *r; r = (char *) malloc(5*sizeof(char)); scanf("%d", &i); scanf("%c", &c); scanf("%s", str); scanf("%s", r); scanf očakáva adresy premenných, do ktorých má zapísať načítanú hodnotu vo funkcii scanf sa vytvorí lokálna premenná ako kópia parametra - adresa, tam sa zapíše načítaná hodnota keď skončí funkcia, zabudne sa lokálna kópia, teda zabudne sa adresa, no na tej adrese zostane načítaná hodnota i - premenná, &i - adresa premennej, c - premenná, &c - adresa premennej, str - statická adresa poľa (reťazca znakov) r - adresa poľa (reťazca znakov)
  • 53. príklad typová konverzia #include <stdio.h> int main(void) { int i, j; float f; i = 5, j = 2; /* pouzitie operatora ciarky */ f = (float) i / j; printf("Typova konverzia - 1. moznost: %lfn", f); f = i / (float) j; printf("Typova konverzia- 2. moznost: %lfn", f); f = (float) i / (float) j; printf("Typova konverzia - 3. moznost: %lfn", f); return 0; }
  • 54. príklad typová konverzia .... f = (float) (i / j); printf("Explicitna typova konverzia - chybny sposob: %lfn", f); f = i / j; printf("Implicitna typova konverzia - chybny sposob: %lfn", f); ....
  • 55. príklad vrátenie prečítaného znaku späť na vstup #include <stdio.h> int main(void) { FILE *fr; int c, cislo, suma = 0; if ((fr = fopen("CISLA.TXT", "r")) == NULL) { printf("Subor CISLA.TXT sa nepodarilo otvoritn"); return 1; } while (1) {/* citanie uvodnych znakov '*' */ while ((c = getc(fr)) == '*') ; if (c == EOF) break;
  • 56. príklad vrátenie prečítaného znaku späť na vstup ungetc(c, fr); /*vratenie prveho znaku cisla spat do suboru*/ fscanf(fr, "%dn", &cislo); suma += cislo; } printf("Sucet cisel je: %dn", suma); if (fclose(fr) == EOF) printf("Subor CISLA.TXT sa nepodarilo uzavrietn"); return 0; }
  • 57. využitie makier isdigit(),isalpha(), toupper() #include <stdio.h> #include <ctype.h> #define EOLN 'n' int main(void) { int c, cislica = 0; printf("Zadaj nejake znaky:n"); while ((c = getchar()) != EOLN) { if (isdigit(c)) cislica++; if (isalpha(c)) putchar(toupper(c)); } printf("nNa vstupnom riadku bolo %d cislicn", cislica);
  • 58. char najcastejsie_pismeno(char *str, int *pocet) { int hist['Z'-'A'+1], i, i_max; for (i=0; i<'Z'-'A'+1; i++) hist[i] = 0; for (i=0; i<strlen(str); i++) hist[toupper(str[i])-'A']++; i_max = 0; for (i=0; i<'Z'-'A'+1; i++) if (hist[i]>hist[i_max]) i_max = i; *pocet = hist[i_max]; return (i_max + 'A'); } char str[10], pismeno; int pocet; ... pismeno = najcastejsie_pismeno(str, &pocet);
  • 59. x = 11; y = 4; if (x && y) printf("*"); if (x & y) printf("+"); Čo vypíše táto časť programu? Pomôcka: 11 = (1011)2 4 = (100)2 Logický súčin (&&): nenulové čísla sú PRAVDA, 11, 4 sú nenulové, preto výsledok je PRAVDA → vypíše sa * Bitový súčin (&): súčin po bitoch 0: NEPRAVDA → + sa nevypíše Vypíše sa *
  • 60. int **p, *q, r; p: ukazovateľ na ukazovateľ na int q: ukazovateľ na int r: int 17 51 67 p = &q; 51 q = &r; 67 5 r = 5; printf("%p %p %p %p %p %d %p %d %d", &p, &q, &r, p, q, r, *p, *q, **p); 17 51 67 51 67 5 67 5 5 & - vráti adresu premennej bez operátora - hodnota premennej (ak je hodnotou adresa, tak je to adresa) * - vráti hodnotu premennej vezme ako adresu a z tej adresy vráti hodnotu
  • 61. Ukazovatele a polia int *p, q[5], i=4; for (i=0; i<5; i++) q[i] = i; 19 57 59 61 63 65 103 57 p: ukazovateľ na int q: statický ukazovateľ na int q[0]: int q[1]: int q[4]: int i: int p = q; 4 p = q+2; /* to iste ako p = &q[2] */ 61 i = *(q+2); /* to iste ako i = q[2] */ 20 1 2 3 4
  • 62. Dvojrozmerné pole . definícia (M, N sú konštanty) načítanie prvkov poľa int pole[M][N]; for (i=0; i<M; i++) for (j=0; j<N; j++) scanf("%d",&pole[i][j]);
  • 63. príklad stránkovanie Napíšte program, ktorý bude vypisovať postupne vždy jednu stránku zo súboru. Po stlačení klávesy Enter vypíše ďalšiu, atď. Počet riadkov na stránke bude určený konštantou.
  • 64. #include <stdio.h> #define RIADKY_OBR 5 #define MENO "SUBOR.TXT" void vypis(FILE *fr); int main(void) { FILE *fr; if ((fr = fopen(MENO, "r")) == NULL) { printf("Subor %s nebol otvoreny.n", MENO); return 1; } vypis(fr); if (fclose(fr) == EOF) printf("Subor %s nebol zatvoreny.n", MENO); return 0; }
  • 65. /* vypis souboru */ void vypis(FILE *fr) { int c, pocet = 0; while ((c = getc(fr)) != EOF) { putchar(c); if (c == 'n') { if (++pocet >= RIADKY_OBR) { pocet = 0; while (getchar() != 'n') ; } } } }
  • 66. zoznam záznamov o knihách (pole) Kartotéka v knižnici Joseph Heller Hlava XXII 1961 položky jedneho záznamu Názov knihy Meno autora Rok jeden záznam o jednej knihe (obsahujúci všetky položky)
  • 67. príklad kartotéka v knižnici – štruktúra v poli Program načíta celé číslo n, následne načíta n záznamov o knihách a uloží ich do poľa. Potom ponúkne používateľovi menu, kde môže pridávať záznam na koniec, zmazať ktorýkoľvek záznam a ukončiť program.
  • 68. #include <stdio.h> #include <stdlib.h> #include <conio.h> #define N 50 /* dlzka retazcov znakov */ #define K 50 /* max. pocet prvkov v kartoteke */ typedef struct { char meno[N]; char priezvisko[N]; } AUTOR; typedef struct { char nazov[N]; AUTOR autor; int rok; } KNIHA;
  • 69. /* nacitanie a pridanie zaznamu na koniec zoznamu*/ void pridaj(KNIHA kniznica[], int *n); /* nacitanie indexu zaznamu a jeho zmazanie */ int zmaz(KNIHA kniznica[], int n); /* vypis zoznamu */ void vypis(KNIHA kniznica[], int n); int main() { int i, n; char c; KNIHA kniznica[K]; printf("Zadajte pocet knih: "); scanf("%d", &n); if (n > K) return 1; i = 0; /* nacitanie zaznamov do zoznamu */ while (i < n) pridaj(kniznica, &i);
  • 70. do { vypis(kniznica, n); printf("p: pridanienz: zmazanienk: koniecn"); c = tolower(getch()); switch(c) { case 'p': pridaj(kniznica, &n); break; case 'z': n = zmaz(kniznica, n); break; } } while (c != 'k'); return 0; }
  • 71. void pridaj(KNIHA kniznica[], int *n) { if ((*n+1) > K) { printf("Kniznica je plna.n"); return; } else { printf("Zadajte nazov knihy, autora (meno, "); printf("priezvisko) a rok vydania:n"); scanf("%s %s %s %d", kniznica[*n].nazov, kniznica[*n].autor.meno, kniznica[*n].autor.priezvisko, &kniznica[*n].rok); (*n)++; } }
  • 72. int zmaz(KNIHA kniznica[], int n) { int i; printf("Zadajte index zaznamu na zmazanie: "); scanf("%d", &i); if (i < 0 || i >= n-1) { printf("Prvok sa v poli nenachadza.n"); return n; } while (i < n-2) { kniznica[i] = kniznica[i+1]; i++; } return n-1; }
  • 73. void vypis(KNIHA kniznica[], int n) { int i; printf("nKNIZNICAnn"); for (i=0; i<n; i++) printf("%s %s: %s (%d)n", kniznica[i].autor.meno, kniznica[i].autor.priezvisko, kniznica[i].nazov, kniznica[i].rok); printf("nn"); }
  • 74. príklad Zlomky oddelený preklad: modul zlomky: zlomky.c a zlomky.h modul hlavny: hlavny.c
  • 75. typedef struct { int citatel; int menovatel; } ZLOMOK; extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b); extern void vypis(ZLOMOK a); zlomky.h
  • 76. #include <stdio.h> #include "zlomky.h" ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b) { int n; ZLOMOK *z = (ZLOMOK *) malloc(sizeof(ZLOMOK); z->citatel = a->citatel* b->menovatel + b->citatel * a->menovatel; z->menovatel = a->menovatel * b->menovatel; n = nsd(z->citatel, z->menovatel); z->citatel /= n; z->menovatel /= n; return z; } void vypis(ZLOMOK *a) { printf("%d / %dn", a->citatel, a->menovatel); } static int nsd(int a, int b) { /*... */ } zlomky.c
  • 77. #include <stdio.h> #include "zlomky.h" int main() { ZLOMKY *x, *y, *z; x = (ZLOMOK *) malloc(sizeof(ZLOMOK)); y = (ZLOMOK *) malloc(sizeof(ZLOMOK)); printf("Zadajte dva zlomky: "); scanf("%d / %d", &x->citatel, &x->menovatel); scanf("%d / %d", &y->citatel, &y->menovatel); z = spocitaj(x, y); printf("Sucet zlomkov je: "); vypis(z); return 0; } hlavny.c
  • 78. #include <stdio.h> #include "zlomky.h" ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b) { int n; ZLOMOK *z = (ZLOMOK *) malloc(sizeof(ZLOMOK); z->citatel = a->citatel + b->citatel; z->menovatel = a->menovatel + b->menovatel; n = nsd(z->citatel, z->menovatel); z->citatel /= n; z->menovatel /= n; } void vypis(ZLOMOK *a) { printf("%d / %dn", a->citatel, a->menovatel); } static int nsd(int a, int b) { } #include <stdio.h> #include "zlomky.h" int main() { ZLOMKY *x, *y, *z; x = (ZLOMOK *) malloc(sizeof(ZLOMOK)); y = (ZLOMOK *) malloc(sizeof(ZLOMOK)); printf("Zadajte dva zlomky: "); scanf("%d %d", &x->citatel, &x->menovatel); scanf("%d %d", &y->citatel, &y->menovatel); z = spocitaj(x, y); printf("Sucet zlomkov je: "); vypis(z); return 0; } typedef struct { int citatel; int menovatel; } ZLOMOK; extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b); extern void vypis(ZLOMOK a); zlomky.c zlomky.h hlavny.c
  • 79. príklad rozvrh dvojrozmerné pole práca so súborom štruktúra parametre funkcie main Program načíta zo súboru údaje o hodinách v rozvrhu a vypíše rozvrh na obrazovku Po Ut St Št Pi So Ne Matematika Mrkvička 3 hodiny
  • 80. Vstupný súbor a štruktúra Súbor: deň hodina skratka predmetu meno učiteľa počet hodín Štruktúra: predmet ucitel cast:  -1: voľno  0: začiatok vyuč. hodiny  1: stred alebo koniec vyuč.hodiny 0 1 MAT Maly 4 1 3 FYZ Velky 2 2 2 ANG Pekna 1 2 3 TEL Vesely 3 4 3 SJ Zeleny 1 vyuč. hodina: 4 riadne hodiny → 4 záznamy: MAT Maly 0 MAT Maly 1 MAT Maly 1 MAT Maly 1
  • 81. ROZVRH ----------------------------------------------------------------------- | Pondelok| MAT, Maly | | ----------------------------------------------------------------------- | Utorok| | | FYZ,Velky | | ----------------------------------------------------------------------- | Streda| | ANG,Pekna| TEL,Vesel | ----------------------------------------------------------------------- | Stvrtok| | | | | | ----------------------------------------------------------------------- | Piatok| | | SJ,Zelen| | | ----------------------------------------------------------------------- | Sobota| | | | | | ----------------------------------------------------------------------- | Nedela| | | | | | -----------------------------------------------------------------------
  • 82. #include <stdio.h> #include <string.h> #define N 6 /* pocet pismen v slove (5 znakov) */ #define ND 7 /* pocet dni */ #define NH 5 /* pocet hodin */ #define SUBOR "subor.txt" /* default nazov suboru */ typedef enum { pondelok, utorok, streda, stvrtok, piatok, sobota, nedela }; typedef struct { char predmet[N]; char ucitel[N]; int cast; /* -1 volno, 0 zaciatok, 1 stred,koniec */ } HODINA; char *dni[] = {"Pondelok", "Utorok", "Streda", "Stvrtok", "Piatok", "Sobota", "Nedela"};
  • 83. void inicializuj(HODINA rozvrh[][NH], int ND); int nacitaj(HODINA rozvrh[][NH], int ND, char subor[]); void vypis(HODINA rozvrh[][NH], int ND); int main (int argc, char *argv[]) { HODINA rozvrh[ND][NH]; char subor[N]; if (argc == 2) strcpy(subor, argv[1]); else strcpy(subor, SUBOR); inicializuj(rozvrh); if (nacitaj(rozvrh, subor)) { return 1; } vypis(rozvrh); return 0; }
  • 84. void inicializuj(HODINA rozvrh[][NH], int ND) { int i, j; for(i=0; i<ND; i++) for(j=0; j<NH; j++) rozvrh[i][j].cast = -1; }
  • 85. /* nacitanie rozvrhu zo suboru */ int nacitaj(HODINA rozvrh[][NH], int ND, char subor[]) { int i, den, hodina, dlzka; FILE *f; if ((f = fopen(subor, "r")) == NULL) { printf("Nepodarilo sa otvorit subor %s.n", subor); return 1; } while(!feof(f)) { fscanf(f, "%d %d", &den, &hodina); den--; hodina--; fscanf(f, "%s", rozvrh[den][hodina].predmet); if (strlen(rozvrh[den][hodina].predmet) > 5) rozvrh[den][hodina].predmet[5] = '0'; /*5 zn.*/ fscanf(f, "%s", rozvrh[den][hodina].ucitel); if (strlen(rozvrh[den][hodina].ucitel) > 5) rozvrh[den][hodina].ucitel[5] = '0'; /*5 zn.*/ fscanf(f, "%d", &dlzka); rozvrh[den][hodina].cast = 0; /*zaciatok vyuc. h.*/
  • 86. /* ak ma vyuc.hod. viac ako 1 hodinu, naplnia sa dalsie zaznamy */ if (dlzka > 1) { for (i=1; i<dlzka && hodina+i < NH; i++) { rozvrh[den][hodina+i] = rozvrh[den][hodina]; rozvrh[den][hodina+i].cast = 1; } } } return 0; }
  • 87. void vypis(HODINA rozvrh[][NH], int ND) { int i, j; printf("nROZVRHnn"); for(i=0; i<ND; i++) { /* horna ciara + ciary oddelujuce dni */ for(j=0; j<NH*12+1+10; j++) putchar('-'); printf("n|%9s", dni[i]); /* oznacenie dna */
  • 88. /* riadok */ for(j=0; j<NH; j++) { if (j == 0 || rozvrh[i][j].cast < 1) putchar('|'); /* ciara pred vyuc. hod. */ else putchar(' '); /* vo vnutri v.h. ' ' */ if (rozvrh[i][j].cast == 0) /* vypis udajov */ printf("%5s,%5s", rozvrh[i][j].predmet, rozvrh[i][j].ucitel); else printf(" "); /* medzery */ if (j == NH-1) putchar('|'); /* koniec dna */ } putchar('n'); /* prechod na dalsi riadok-den */ } /* dolna ciara */ for(j=0; j<NH*12+1+10; j++) putchar('-'); printf("n"); }
  • 89. príklad bitové operácie  Vytvorte program predstavujúci kalkulačku v dvojkovej sústave.  a. V premennej hodnota si pamätajte aktuálnu hodnotu. Na začiatku túto hodnotu inicializujte na 1.  Tú umožnite násobit’ dvoma a delit’ dvoma (celočíselne). Pri násobení dvoma skontrolujte, či číslo „nepretečie“- ak by to malo nastat’, vypíšte chybovú správu Operaciu nie je mozne vykonat  b. Do kalkulačky pridajte funkciu na pripočítavanie načítaného čísla. Tiež kontrolujte pretečenie.  Pripočítavajte po bitoch.  Program bude na vstupe dostávať príkazy:  C – na načítanie čísla do premennej hodnota. N – na násobenie dvoma. D – na delenie dvoma. P – na pripočítavanie zadaného čísla. O – na odpočítavanie zadaného čísla.  K – na ukončenie programu.
  • 90. #include <stdio.h> #define RAD(x,i) (((x)>>(i))&1) // vrati cislicu i-teho radu cisla x #define VYTVORIT_CISLO(i) (1<<(i)) // vytvori cislo s 1 na mieste i, ostatne su 0 //vypise cislo v dvojkovej sustave void vypis2(unsigned x) { if (x>0) { vypis2(x>>1); printf("%d",x&1); } } void vypis(unsigned hodnota) { printf("Aktualna hodnota: %un",hodnota);}
  • 91. unsigned sucet(unsigned a, unsigned b) { unsigned x=0,zv=0; unsigned i; unsigned s=0; for (i=0;i<sizeof(x)*8;i++) { s=RAD(a,i)+RAD(b,i)+zv; if (RAD(s,1)==1) { zv=1; s&=(~VYTVORIT_CISLO(1));} else {zv=0;} if (RAD(s,0)) {x|=VYTVORIT_CISLO(i);} }if (zv==0) {return x;} else { printf("Operaciu nie je mozne vykonatn"); return a;} }
  • 92. unsigned rozdiel(unsigned a, unsigned b){ unsigned x=0,zv=0; unsigned i; unsigned s=0; for (i=0;i<sizeof(x)*8;i++){ s=RAD(b,i)+zv; zv=0; if (RAD(s,1)==1) { zv++; s&=(~VYTVORIT_CISLO(1)); s&=(~VYTVORIT_CISLO(0)); } if (RAD(a,i)<s){ s=0; zv++; x|=VYTVORIT_CISLO(i);}
  • 93. else if (RAD(a,i)>s) { x|=VYTVORIT_CISLO(i); } } if (zv==0) { return x; } else { printf("Operaciu nie je mozne vykonatn"); return a; }
  • 94. int main() { char c; unsigned hodnota=1,cislo; while (1) { while ((c=getchar())=='n') ; switch (c){ case 'C': // nacitanie hodnoty scanf("%u",&hodnota); vypis(hodnota); break; case 'N': // nasobenie dvomi if (RAD(hodnota,sizeof(hodnota)*8-1)) {printf("Operaciu nie je mozne vykonatn");} else{ hodnota<<=1; vypis(hodnota);}
  • 95. case 'D': // delenie dvomi hodnota>>=1; vypis(hodnota); break; case 'P': // pripocitanie scanf("%u",&cislo); hodnota=sucet(hodnota,cislo); vypis(hodnota); break; case 'O': // odpocitanie scanf("%u",&cislo); hodnota=rozdiel(hodnota,cislo); vypis(hodnota); break; case 'K': return 0; // ukonci program}}