Zppls11 prednaska 2014
-
Upload
thebugerror -
Category
Technology
-
view
73 -
download
4
description
Transcript of Zppls11 prednaska 2014
Oddelený preklad, opakovanie v príkladoch
Anna Bou Ezzeddine
Obsahoddelený prekladopakovanie v príkladoch
Oddelený preklad
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
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:
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
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
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á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.
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)
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.
Pamäťové triedyurčujú v ktorej časti pamäte bude premenná
umiestnená a kde bude viditeľnáautoexternstaticregister
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;}
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
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
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;
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ášť
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:constvolatile
static const unsigned int j = 5;
napríklad:
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:
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 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
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
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; ...}
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)
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)
Rozšírenie platnosti globálnej premennejglobálna premenná:
definovaná v jednom súboredeklarovaná 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 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
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
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 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"
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ú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!)
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
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)
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
#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 %.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
#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 %.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
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
Opakovanie
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.
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.
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
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úryskrátené vyhodnocovanie zložených výrazovif (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ú 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)
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; }
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);
....
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;
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; }
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; }
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 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
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á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)
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: 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;}
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("\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");}
príklad Zlomkyoddelený preklad:
modul zlomky: zlomky.c a zlomky.hmodul 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 / %d\n", 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 / %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
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
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
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]);
elsestrcpy(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("\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 */
/* 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: %u\n",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 vykonat\n");
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 vykonat\n");
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 vykonat\n");}
else{ hodnota<<=1;
vypis(hodnota);}
break;
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;}