Zppls11 prednaska 2014

95
Oddelený preklad, opakovanie v príkladoch Anna Bou Ezzeddine

description

Temporary slide save

Transcript of Zppls11 prednaska 2014

Page 1: Zppls11 prednaska 2014

Oddelený preklad, opakovanie v príkladoch

Anna Bou Ezzeddine

Page 2: Zppls11 prednaska 2014

Obsahoddelený prekladopakovanie v príkladoch

Page 3: Zppls11 prednaska 2014

Oddelený preklad

Page 4: Zppls11 prednaska 2014

Oddelený prekladvkladanie 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ý prekladkaždý súbor sa preloží zvlášť (vznikne viac .OBJ súborov) a

potom sa spoja pomocou linkerumožnosť rozdelenia problému na viacero menších

nezávislých častí, na ktorých pracuje súčasne viacero programátorov

Page 5: Zppls11 prednaska 2014

Príklad oddeleného prekladus2.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:

Page 6: Zppls11 prednaska 2014

Oblasť platnosti identifikátorovjazyk 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é triedytypové modifikátory

Page 7: Zppls11 prednaska 2014

Globálne premennéorganizácia v programe:

globálne definície a deklaráciedefiní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

Page 8: Zppls11 prednaska 2014

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()

Page 9: Zppls11 prednaska 2014

Lokálne premennédefinované vo funkciáchplatnosť 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.

Page 10: Zppls11 prednaska 2014

Inicializácia lokálnych a globálnych premennýchlokálne premenné:

nie sú automaticky inicializovanéglobálne premenné:

automaticky inicializované na 0 (0.0, \0) (lepšie - nespoliehať sa na to)

Page 11: Zppls11 prednaska 2014

UpozornenieV jazyku C premenné definované vo funkcii main sú

lokálne iba pre túto funkciuPozor na zvyk z Pascalu, kde premenné definované v

hlavnom programe sú globálne pre všetky funkcie a procedúry.

Page 12: Zppls11 prednaska 2014

Pamäťové triedyurčujú v ktorej časti pamäte bude premenná

umiestnená a kde bude viditeľnáautoexternstaticregister

Page 13: Zppls11 prednaska 2014

Trieda autoautomatické premenné

implicitne pre lokálne premennéuložená v zásobníku (stacku)existuje od vstupu do funkcie do jej koncanie 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;}

Page 14: Zppls11 prednaska 2014

Trieda externimplicitne pre globálne premennéuložená v dátovej oblastipouží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

Page 15: Zppls11 prednaska 2014

Trieda staticneexistuje žiadna implicitná definícia-kľúčové slovo musí byť uvedené premenné tejto triedy sú uložené v dátovej oblastinajč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: 2i: 1, x: 2i: 2, x: 2

Page 16: Zppls11 prednaska 2014

Trieda staticglobá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;

Page 17: Zppls11 prednaska 2014

Trieda registerjazyk C - nízkoúrovňový a preto umožňuje, aby premenná bola

zapísaná v registriak sa dádo ktorého registra - vyberá si prekladačiba lokálne premennétie, ku ktorým je vhodné pristupovať rýchlonemôžeme získať adresu registrovej premenejglobá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ášť

Page 18: Zppls11 prednaska 2014

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

Page 19: Zppls11 prednaska 2014

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:constvolatile

static const unsigned int j = 5;

napríklad:

Page 20: Zppls11 prednaska 2014

Modifikátor constv ANSI Cpo inicializácii už nemôže byť menená hodnota premennejpodobne 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:

Page 21: Zppls11 prednaska 2014

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

Page 22: Zppls11 prednaska 2014

Modifikátor volatilev ANSI Cmá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ímak by nebola označená modifikátorom volatile - prekladač by to

mohol optimalizovať tak, že by premennú pocet nahradil jej hodnotou, akú mala pred cyklom

Page 23: Zppls11 prednaska 2014

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

Page 24: Zppls11 prednaska 2014

Blokyblok programu - uzatvorený v { } môže

obsahovať definície premennýchlokálne premenné (auto, alebo static)viditeľné sú len v bloku if (i > 0) {

int i; ...}else { double f; ...}

Page 25: Zppls11 prednaska 2014

Oblasť platnosti identifikátorov zhrnutieglobá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)

Page 26: Zppls11 prednaska 2014

Oddelený preklad súborovrozdeliť 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)

Page 27: Zppls11 prednaska 2014

Rozšírenie platnosti globálnej premennejglobálna premenná:

definovaná v jednom súboredeklarovaná pomocou extern v ostatných súboroch

Page 28: Zppls11 prednaska 2014

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

Page 29: Zppls11 prednaska 2014

Statické globálne premenné a funkcietrieda 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

Page 30: Zppls11 prednaska 2014

príklad statické globálne premenné a funkciestatic 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

Page 31: Zppls11 prednaska 2014

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)

Page 32: Zppls11 prednaska 2014

Ako udržať poriadok vo veľkom programe1. definície funkcií a premenných v súbore program_1.c2. 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ť static4. funkčné prototypy(hlavičky) zdielaných funkcií a premenných - do

program_1.h, označíme ich extern5. ak poskytujeme aj symbolické konštanty - dáme ich len do

program_1.h6. program_1.c začína:

#include <stdio.h>#include "program_1.h"

Page 33: Zppls11 prednaska 2014

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

Page 34: Zppls11 prednaska 2014

Odporučený obsah .c súborov1. 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 objektovlen 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ýchpremenné definované mimo funkcií zdielané inými modulmi (čo najmenej!)

Page 35: Zppls11 prednaska 2014

Odporučený obsah .c súborov5. lokálne #define

definícia konštánt a makier len pre aktuálny modullen ak veľmi rozsiahle - do zvlášť .h

6. definície lokálnych typovtypedef len pre aktuálny modullen ak veľmi rozsiahle - do zvlášť .h

7. definície premenných len pre aktuálny modulglobálne len pre aktuálny modul - static

8. úplné funkčné prototypy funkcií len pre aktuálny modul9. funkcia main()- iba ak v súbore existuje10. definície (globálnych) funkcií - aj pre iné moduly 11. definície funkcií len pre aktuálny modul

Page 36: Zppls11 prednaska 2014

Odporučený obsah .h súborov1. 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 moduloch5. 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)

Page 37: Zppls11 prednaska 2014

príklad oddelený prekladprogram 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_main

double obvoddouble vyp_priemer(double polomer)

double polomer, obsahvoid 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

Page 38: Zppls11 prednaska 2014

#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

Page 39: Zppls11 prednaska 2014

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)

Page 40: Zppls11 prednaska 2014

#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 %.2f\n", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2f\n", polomer, obvod);}

glob. definície

kruh_io.c

Page 41: Zppls11 prednaska 2014

#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

Page 42: Zppls11 prednaska 2014

#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 %.2f\n", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2f\n", 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

Page 43: Zppls11 prednaska 2014

Visual C++ a oddelený preklad vytvorenie projektu

(Win32 Console Application) vloženie súboru

C++ Source File C/C++ Header File

Menu Build1. Build program.exe2. Compile program.exe

Page 44: Zppls11 prednaska 2014

Opakovanie

Page 45: Zppls11 prednaska 2014

OperátoryOperá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.

Page 46: Zppls11 prednaska 2014

OperátoryOperá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.

Page 47: Zppls11 prednaska 2014

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átvorkesizeof operátor na získanie dĺžky objektu, alebo typu

Page 48: Zppls11 prednaska 2014

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)

Page 49: Zppls11 prednaska 2014

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ť

Page 50: Zppls11 prednaska 2014

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

Page 51: Zppls11 prednaska 2014

Časté chyby – riadiace štruktúryskrátené vyhodnocovanie zložených výrazovif (i=100) chyba !for (i=1; i==10; i++) chyba !

Page 52: Zppls11 prednaska 2014

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ú hodnotuvo funkcii scanf sa vytvorí lokálna premenná ako kópia parametra - adresa, tam sa zapíše načítaná hodnotakeď 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)

Page 53: Zppls11 prednaska 2014

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: %lf\n", f);

f = i / (float) j;

printf("Typova konverzia- 2. moznost: %lf\n", f);

f = (float) i / (float) j;

printf("Typova konverzia - 3. moznost: %lf\n", f);

return 0; }

Page 54: Zppls11 prednaska 2014

príklad typová konverzia

....

f = (float) (i / j);

printf("Explicitna typova konverzia - chybny sposob: %lf\n", f);

f = i / j;

printf("Implicitna typova konverzia - chybny sposob: %lf\n", f);

....

Page 55: Zppls11 prednaska 2014

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 otvorit\n");

return 1; }

while (1) {/* citanie uvodnych znakov '*' */

while ((c = getc(fr)) == '*')

;

if (c == EOF) break;

Page 56: Zppls11 prednaska 2014

príklad vrátenie prečítaného znaku späť na vstup

ungetc(c, fr);

/*vratenie prveho znaku cisla spat do suboru*/

fscanf(fr, "%d\n", &cislo);

suma += cislo; }

printf("Sucet cisel je: %d\n", suma);

if (fclose(fr) == EOF)

printf("Subor CISLA.TXT sa nepodarilo uzavriet\n");

return 0; }

Page 57: Zppls11 prednaska 2014

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 cislic\n", cislica);

return 0; }

Page 58: Zppls11 prednaska 2014

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);

Page 59: Zppls11 prednaska 2014

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 *

Page 60: Zppls11 prednaska 2014

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

Page 61: Zppls11 prednaska 2014

Ukazovatele a poliaint *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] */

2 0 1 2 3 4

Page 62: Zppls11 prednaska 2014

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]);

Page 63: Zppls11 prednaska 2014

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.

Page 64: Zppls11 prednaska 2014

#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;

}

Page 65: Zppls11 prednaska 2014

/* 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')

;

}

}

}}

Page 66: Zppls11 prednaska 2014

zoznam záznamovo knihách (pole)

Kartotéka v knižnici

Joseph Heller

Hlava XXII

1961položky jedneho záznamu

Názov knihy

Meno autora

Rok

jeden záznam o jednej knihe(obsahujúci všetky položky)

Page 67: Zppls11 prednaska 2014

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.

Page 68: Zppls11 prednaska 2014

#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;

Page 69: Zppls11 prednaska 2014

/* 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);

Page 70: Zppls11 prednaska 2014

do { vypis(kniznica, n); printf("p: pridanie\nz: zmazanie\nk: koniec\n"); c = tolower(getch()); switch(c) { case 'p': pridaj(kniznica, &n); break; case 'z': n = zmaz(kniznica, n); break; }

} while (c != 'k'); return 0;}

Page 71: Zppls11 prednaska 2014

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)++;}

}

Page 72: Zppls11 prednaska 2014

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;

}

Page 73: Zppls11 prednaska 2014

void vypis(KNIHA kniznica[], int n) { int i;

printf("\nKNIZNICA\n\n"); 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("\n\n");}

Page 74: Zppls11 prednaska 2014

príklad Zlomkyoddelený preklad:

modul zlomky: zlomky.c a zlomky.hmodul hlavny: hlavny.c

Page 75: Zppls11 prednaska 2014

typedef struct { int citatel; int menovatel;} ZLOMOK;

extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b);extern void vypis(ZLOMOK a);

zlomky.h

Page 76: Zppls11 prednaska 2014

#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 / %d\n", a->citatel, a->menovatel); }

static int nsd(int a, int b) { /*... */}

zlomky.c

Page 77: Zppls11 prednaska 2014

#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

Page 78: Zppls11 prednaska 2014

#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 / %d\n", 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

Page 79: Zppls11 prednaska 2014

príklad rozvrh

dvojrozmerné pole práca so súboromštruktúraparametre funkcie main

Program načíta zo súboru údaje o hodinách v rozvrhu

a vypíše rozvrh na obrazovku

PoUtStŠtPiSoNe

MatematikaMrkvička3 hodiny

Page 80: Zppls11 prednaska 2014

Vstupný súbor a štruktúraSúbor:

deň hodinaskratka predmetumeno učiteľapočet hodín

Štruktúra:predmetucitelcast:

-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:

MATMaly0MATMaly1MATMaly1MATMaly1

Page 81: Zppls11 prednaska 2014

ROZVRH

-----------------------------------------------------------------------| Pondelok| MAT, Maly | |-----------------------------------------------------------------------| Utorok| | | FYZ,Velky | |-----------------------------------------------------------------------| Streda| | ANG,Pekna| TEL,Vesel |-----------------------------------------------------------------------| Stvrtok| | | | | |-----------------------------------------------------------------------| Piatok| | | SJ,Zelen| | |-----------------------------------------------------------------------| Sobota| | | | | |-----------------------------------------------------------------------| Nedela| | | | | |-----------------------------------------------------------------------

Page 82: Zppls11 prednaska 2014

#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"};

Page 83: Zppls11 prednaska 2014

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]);

elsestrcpy(subor, SUBOR);

inicializuj(rozvrh);if (nacitaj(rozvrh, subor)) {

return 1;}

vypis(rozvrh);return 0;

}

Page 84: Zppls11 prednaska 2014

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;}

Page 85: Zppls11 prednaska 2014

/* 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.*/

Page 86: Zppls11 prednaska 2014

/* 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;}

Page 87: Zppls11 prednaska 2014

void vypis(HODINA rozvrh[][NH], int ND) { int i, j;

printf("\nROZVRH\n\n");

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 */

Page 88: Zppls11 prednaska 2014

/* 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");}

Page 89: Zppls11 prednaska 2014

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.

Page 90: Zppls11 prednaska 2014

#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: %u\n",hodnota);}

Page 91: Zppls11 prednaska 2014

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 vykonat\n");

return a;}

}

Page 92: Zppls11 prednaska 2014

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);}

Page 93: Zppls11 prednaska 2014

else

if (RAD(a,i)>s)

{

x|=VYTVORIT_CISLO(i);

}

}

if (zv==0)

{

return x;

}

else

{

printf("Operaciu nie je mozne vykonat\n");

return a;

}

}

Page 94: Zppls11 prednaska 2014

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 vykonat\n");}

else{ hodnota<<=1;

vypis(hodnota);}

break;

Page 95: Zppls11 prednaska 2014

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}}

return 0;}