Avditorne vaje

Avditorne vaje
Podprogrami v C ju
Podprogrami v C‐ju
• Napišite podprogram v programskem jeziku /
p
C/C++, ki bo vrnil polovico absolutne vrednosti vsote treh celih števil, brez uporabe matematične funkcije abs Rezultat naj bo
matematične funkcije abs. Rezultat naj bo realno število.
Podprogrami v C ju
Podprogrami v C‐ju
• Napišite podprogram v programskem jeziku /
p
C/C++, ki bo vrnil polovico absolutne vrednosti vsote treh celih števil, brez uporabe matematične funkcije abs Rezultat naj bo
matematične funkcije abs. Rezultat naj bo realno število.
Podprogram, ki vrne neko vrednost,
je funkcija Podprogrami v C ju
Podprogrami v C‐ju
• Napišite podprogram v programskem jeziku /
p
C/C++, ki bo vrnil polovico absolutne vrednosti vsote treh celih števil, brez uporabe matematične funkcije abs Rezultat naj bo
matematične funkcije abs. Rezultat naj bo realno število.
Kaj je absolutna vrednost števila?
abs(4) = 4
||X||
abs(‐4) = 4
b( )
Negativne vrednosti postanejo pozitivne.
Pozitivne vrednosti ostanejo pozitivne.
Podprogrami v C ju
Podprogrami v C‐ju
• Napišite podprogram v programskem jeziku /
p
C/C++, ki bo vrnil polovico absolutne vrednosti vsote treh celih števil, brez uporabe matematične funkcije abs Rezultat naj bo
matematične funkcije abs. Rezultat naj bo realno število.
Kakšne parametre potrebujemo?
Tri cela števila.
Podprogrami v C ju
Podprogrami v C‐ju
• Napišite podprogram v programskem jeziku /
p
C/C++, ki bo vrnil polovico absolutne vrednosti vsote treh celih števil, brez uporabe matematične funkcije abs Rezultat naj bo
matematične funkcije abs. Rezultat naj bo realno število.
Kakšne je rezultat funkcije?
Realno število. Ker ni določeno ž l
želena natančnost (ali float
č
( l fl
ali double),
l d bl )
izberemo enega izmed njiju.
Podprogrami v C ju
Podprogrami v C‐ju
• Napišite podprogram v programskem jeziku /
p
C/C++, ki bo vrnil polovico absolutne vrednosti vsote treh celih števil, brez uporabe matematične funkcije abs Rezultat naj bo
matematične funkcije abs. Rezultat naj bo realno število.
Kaj podprogram naj naredi?
1. Izračuna vsoto
2. Določi absolutno vrednost
l č b l
d
3. Vrne polovico te vrednosti
Ime podprograma ni bilo podano,
zato si ga izmislimo sami
Zgled
double
d
bl absvsota2(int
b
t 2(i t a,int
i t b,
b int
i t c))
{
int vsota = a+b+c;
if(vsota<0)
vsota = -vsota;
return vsota/2.0;
}
Parametri so cela števila a,b,c. Rezultat je realno število tipa double.
Zgled
double
d
bl absvsota2(int
b
t 2(i t a,int
i t b,
b int
i t c))
{
int vsota = a+b+c;
if(vsota<0)
vsota = -vsota;
return vsota/2.0;
}
Zgled
Deklaracija pomožne spremenljivke in
Deklaracija
pomožne spremenljivke in
izračun vsote. Lahko bi napisali ločeno.
double
d
bl absvsota2(int
b
t 2(i t a,int
i t b,
b int
i t c))
{
int vsota = a+b+c;
if(vsota<0)
vsota = -vsota;
return vsota/2.0;
}
Zgled
Izračun absolutne vrednosti vsote.
Negativne vrednosti pretvorimo v
pozitivne s spremembo predznaka
pozitivne s spremembo predznaka (ali z množenjem z ‐1).
double
d
bl absvsota2(int
b
t 2(i t a,int
i t b,
b int
i t c))
{
int vsota = a+b+c;
if(vsota<0)
vsota = -vsota;
return vsota/2.0;
}
Zgled
floatt absvsota2(int
fl
b
t 2(i t a,int
i t b,
b int
i t c))
{
int vsota = a+b+c;
if(vsota<0)
vsota = -vsota;
return vsota/2.0;
}
Rezultat je polovica izračunane Rezultat
je polovica izračunane
vsote. Ker želimo kot rezultat realno število, se moramo izogniti celoštevilčnemu deljenju. Zato vsoto
j j
delimo z 2.0 (namesto z 2).
Velikost podatkov sizeof
Velikost podatkov ‐
• Velikost spremenljivk in drugih podatkov nam lik
lji k i d ih d k
pove koliko pomnilniškega prostora računalnika ("spomina") je potrebno za njihovo hrambo • Velikost podatkov je odvisna od načina p
predstavitve teh podatkov v računalniku
p
• Velikost podatkov v programskem jeziku C izvemo z operatorjem (funkcijo ukazom)
izvemo z operatorjem (funkcijo, ukazom) sizeof
sizeof <izraz>
sizeof (<podatkovni tip>)
Velikost podatkov sizeof
Velikost podatkov ‐
• Enostavni podatkovni tipi
char c;
int a;
float x;
double y
y;
1
4
c
a
4
8
• Velikost
Velikost je enaka število zlogov, ki je enaka število zlogov ki
ga zaseda podatek v pomnilniku
x
y
Velikost podatkov sizeof
Velikost podatkov ‐
• Polja
int a[5],b[4][3];
• Podatki si sledijo od nižjih indeksov proti višjim in
indeksov proti višjim in od nižjih dimenzij proti višjim
išji
• Velikost:
<velikost tipa podatka> * <število elementov dimenzije 1> * <število elementov dimenzije 2> * …
j
a[0]
a[1]
a[2]
a[3]
a[4]
b[0][0]
b[0][1]
b[0][2]
b[1][0]
b[1][1]
b[1][2]
b[2][0]
b[2][1]
b[2][2]
b[3][0]
b[3][1]
b[3][2]
Velikost podatkov sizeof
Velikost podatkov ‐
• Strukture
struct datum { int leto, mesec, dan; } d;
• Podatki
Podatki si v pomnilniku sledijo en za drugim v si v pomnilniku sledijo en za drugim v
istem vrstnem redu kot so navedeni v d kl
deklaraciji
iji
d.leto
d
d.mesec
d.dan
• Velikost
Velikost je enaka vsoti velikosti posameznih je enaka vsoti velikosti posameznih
komponent
Velikost podatkov sizeof
Velikost podatkov ‐
• Znakovni
Znakovni nizi
nizi
Če je število elementov polja pri znakovnem nizu podano eksplicitno (neposredno), je d
k l
(
d )
velikost podatka enaka tej dimenziji
Če znakovnemu nizu ne določimo dimenzije in ga inicializiramo s konstantnim nizom znakov ga inicializiramo
s konstantnim nizom znakov
(med dvojnim narekovaji), moramo upoštevati, da prevajalnik avtomatsko doda še št ti d
j l ik t
tk d d š
en znak (oznako konca niza ‐ '\0') Zgled
char niz1[100] niz1[100] = "ABC";
ABC ;
char niz2[] = "ABC";
0
niz1
‘A’ ‘B’ ‘A’ ‘B’ ‘C’ ‘\0’
‘C’ ‘\0’
0
niz2
99
3
‘A’ ‘B’ ‘C’ ‘\0’
…
Velikost podatkov sizeof
Velikost podatkov ‐
• Kaj izpiše naslednji segment programa (1)? p
j
j p
predstavljen z p
j
Predpostavka je, da je tip int
32 biti.
char niz1[] = "ABC";
char niz2[20] = "Pozdrav\n";
int a[10];
printf("%d %d %d %d\n",sizeof niz1,sizeof niz2, sizeof a,
sizeof a[0]);
Zgled
niz1 nima neposredno podane dimenzije zato odloča velikost
dimenzije, zato odloča velikost (število znakov) znakovne konstante (+ znak za konec)
char niz1[] = "ABC"; 3+1=4
char niz2[20] = "Pozdrav\n";
int a[10];
printf("%d %d %d %d\n",sizeof niz1,sizeof niz2, sizeof a,
sizeof a[0]);
Zgled
niz2 ima neposredno podano dimenzijo Konstantni niz ki mu
dimenzijo. Konstantni niz, ki mu ga priredimo, na velikost ne vpliva.
char niz1[] = "ABC";
char niz2[20] = "Pozdrav\n"; 20
int a[10];
printf("%d %d %d %d\n",sizeof niz1,sizeof niz2, sizeof a,
sizeof a[0]);
Zgled
a je polje celih števil z 10 elementi Velikost je torej
elementi. Velikost je torej desetkratnik velikosti celega
števila.
char niz1[] = "ABC";
char niz2[20] = "Pozdrav\n";
int a[10];
10*4 40
10*4=40
printf("%d %d %d %d\n",sizeof niz1,sizeof niz2, sizeof a,
sizeof a[0]);
Zgled
a[0] je prvi element polja celih števil elementi Velikost tega
števil elementi. Velikost tega elementa je enaka velikosti celega
števila.
char niz1[] = "ABC";
char niz2[20] = "Pozdrav\n";
int a[10];
printf("%d %d %d %d\n",sizeof niz1,sizeof niz2, sizeof a,
sizeof a[0]); 4
Zgled
char niz1[] = "ABC";
char niz2[20] = "Pozdrav\n";
int a[10];
printf("%d %d %d %d\n",sizeof niz1,sizeof niz2, sizeof a,
sizeof a[0]);
4 20 40 4
Podatkovne strukture
Podatkovne strukture
• Implementacija kompleksnejših nalog je brez p
p
p
uporabe ustreznih podatkovnih tipov in podatkovnih struktur veliko težja.
• Podatkovne strukture združujejo logično Podatkovne strukture združujejo logično
povezane podatke v celoto in jih povežejo s podprogrami za delo z njimi l
Zgled:
• Naloga: p
Sestavite ustrezne podatkovne strukture, ki bodo omogočale predstavitev podatkov ene igralne karte Izdelajte ustrezne podprograme
igralne karte. Izdelajte ustrezne podprograme za branje in izpis podatkov ene karte in jih preizkusite s testnim programom
preizkusite s testnim programom.
Zgled:
• A
Analiza in (delna) razgradnja problema:
li i (d l )
d j
bl
Igralne karte imajo štiri barve (srce, karo, pik in križ) ter 13 različnih vrednosti (dvojka trojka
ter 13 različnih vrednosti (dvojka, trojka, …, desetka, desetka
fant, dama, kraj in as).
• Barvo bomo predstavili z naštevnim podatkovnim Barvo bomo predstavili z naštevnim podatkovnim
tipom, vrednost pa z celim številom. Oboje bomo povezali v strukturo
povezali v strukturo.
• Branje in izpis vrednosti karte bo potekalo preko zaporedja znakov – prva črka bo oznaka barve, druga zaporedja znakov prva črka bo oznaka barve, druga
črka (oz. drugi dve) pa bo predstavljala vrednost.
Zgled
• Programska koda: Karte1.c
Zgled
• Naloga: p
p j j p
j
Dopolnite prejšnji primer s funkcijo, ki bo za pet kart ugotovila ali predstavljajo poker. Funkcijo preverite s testnim programom ki
Funkcijo preverite s testnim programom, ki vrednosti petih kart prebere preko tipkovnice in izpiše rezultat
in izpiše rezultat.
Zgled
• Analiza in (osnovna) razgradnja: li i (
)
d j
Igralec ima "v roki" poker, če ima 4 karte iste vrednosti. • Več kart bomo predstavili s poljem katerega p
p j
g
elementi so strukture, ki predstavlja karte.
• Pri ugotavljanju ali gre za poker, bomo Pri ugotavljanju ali gre za poker bomo
uporabili števce, ki bodo prešteli koliko kart posamezne vrednosti imamo "vv roki
posamezne vrednosti imamo roki". Na Na
koncu preverimo ali ima kateri od števcev vrednost 4
vrednost 4. Zgled
• Programska koda: Karte2.c
Uporaba programskih modulov
Uporaba programskih modulov
• P
Pri izdelavi drugega programa s kartami smo morali ii d l id
k
i
li
prekopirati večino kode iz prvega.
• Če želimo naknadno kaj spremeniti (npr. uporabiti Č ž li
k d k j
i i(
bi i
posebne grafične znake za izpis barve kart), moramo popravljati oba programa
popravljati oba programa.
• Veliko bolje je, če podatkovne tipe in podprograme povezane z kartami združimo v ločen programski
povezane z kartami združimo v ločen programski modul in ga uporabimo za oba glavna programa (in za morebitne ostale programe s kartami) .
morebitne ostale programe s kartami) .
Zgled
• Programska koda: KarteM.c, KarteM.h, Karte1M.c, Karte2M.c, Karte3M.c
Nizi znakov
Nizi znakov
• Enodimenzionalno polje znakov
char <ime spremenljivke>[<dimenzija>];
• Skoraj vsi podprogrami za delo z nizi znakov v C‐ju predpostavljajo, da se niz konča z znakom '\0' (koda 0)
a b c d e f g \0
• V
Vsak znak zaseda en zlog (byte –
k
k
d
l (b t 0..255)
0 255)
• C pozna tudi konstantne nize znakov (v dvojnih narekovajih)
Nizi znakov
Nizi znakov
• Polja znakov lahko ob dekraraciji inicializiramo s konstantnim nizom znakov:
char niz1[10];
char niz2[10] = "abc"; /* inicializira prve 4 znake */
char niz3[] = "defgh"; /* velikost polja je 6 */
niz1
i 1 = niz2;
i 2
/* napaka
k */
niz3[0] = niz2[0];
printf("%s\n",niz3);
Nizi znakov
Nizi znakov
• Nize znakov lahko navedemo tudi kot parametre podprogramov – prevajalnik ne preverja ali se dimenzije polj dejanskih in formalnih parametrov ujemajo.
int fun1(char niz[]);
int fun1(char niz[10]);
Zgled
• N
Naloga: l
Izdelajte podprogram, ki bo preveril ali se
nek znak nahaja v podanem nizu znakov
• Analiza in razgradnja:
Znak bomo primerjali po vrsti s
posameznimi znaki iz niza. Iskanje
zaključimo ko bodisi najdemo znak ali pa
zaključimo,
naletimo na kodo konca niza (znak '\0').
• Predpostavili bomo
bomo, da indeksi polja niza
znakov tečejo od 0 naprej.
Zgled
• Psevdokod:
// ZnakJeVNizu(znak,niz[0..n])
//
(
, [
])
// Začnemo pri prvem znaku
set i=0
// postopek ponavljamo, dokler ne pridemo do konca niza
//
postopek ponavljamo, dokler ne pridemo do konca niza
while niz[i]<>''\0' do
if niz[i]=znak then // Znak niza je enak iskanemu
return True // Znak je v nizu
//
j
end if
set i=i+1 // Premik na naslednji znak
end while
return False // Znaka ni v nizu
Zgled
• Programska koda: ZnakJeVNizu.c
Najprej je potrebno v kodi popraviti eno
• Najprej je potrebno v kodi popraviti eno logično napako!
Zgled - nadgradnja
• Vč
Včasih
ih jje ugodneje,
d j čče poleg
l ttega alili se
znak nahaja v določenem nizu, ugotovimo
še na kateri poziciji (indeksu) se nahaja.
• Prejšnji
j j p
postopek
p (p
(program)
g
) dopolnimo
p
tako, da namesto vrednosti True/False
ača indeks
de s mesta
esta na
a katerem
ate e se znak
a
vrača
niza ujema z iskanim. V primeru, če znaka
ni v nizu, vrnemo neko posebno vrednost
(npr. -1), ki je indeks ne more zavzeti.
• Programska koda: KateriZnak.c
KateriZnak c
Zgled – štetje črk (1)
• Naloga: l
Izdelajte program, ki bo v podanem nizu
znakov preštel koliko plusov in koliko
minusov se v njem nahaja.
• Analiza in razgradnja:
ot ebuje o dva
d a števca,
šte ca, e
enega
ega za
ap
pluse
use
Potrebujemo
in enega za minuse. Po vrsti pregledamo
vse znake niza. Če naletimo na plus ali
minus, povečamo ustrezni števec. Na
koncu izpišemo vrednosti števcev.
Zgled
• Programska koda: StetjeCrk1.c
Zgled – štetje črk (2)
• Naloga: l
Izdelajte program, ki bo v podanem nizu
znakov preštel kolikokrat se pojavlja prvih
pet črk angleške abecede 'a', 'b', 'c', 'd', 'e'.
• Analiza in razgradnja:
a esto da za
a vsako
sa o črko
č ou
uvedemo
ede o ssvoj
oj
Namesto
števec, raje uporabimo polje števcev. Pri
računanju indeksa polja števcev
upoštevamo dejstvo, da si kode podanih
znakov sledijo ena za drugo.
Zgled
• 'b' = 'a'+1, 'c'='b'+1, …
• Indeks polja dobimo tako
tako, da od kode
znaka niza odštejemo kodo znaka 'a'.
– 'a'-'a'
' '' '=0
– 'b'-'a' = 1
– 'c'-'a' = 2
– 'e'-'a'
e a =4
• Programska koda: StetjeCrk2.c
Zgled – štetje črk (3)
• N
Naloga: l
Izdelajte program, ki bo v podanem nizu
znakov preštel kolikokrat se pojavljajo
znaki a,b,c,+,-,*.
• Analiza in razgradnja:
Analiza in razgradnja:
Tudi tu bomo uporabili števce. Vendar si
tokrat znaki ne sledijo en za drugim
drugim.
Potrebujemo funkcijo, ki določa indeks
števca za posamezni znak. Pomagali si
bomo z prej izdelano funkcijo
KateriZnakVNizu.
Zgled – štetje črk (3)
Zgled –
Zgled • Programska koda: StetjeCrk3.c, StetjeCrk4.c
Povezava med polji in kazalci na znake
Povezava med polji in kazalci na znake
• Podobno kot velja za vsa polja v C‐ju, obstaja d b k
lj
lj
j
b j
tesna zveza med kazalci in polji
• Imena polj so dejansko kazalci na prvi element p j
polja => priredimo jih lahko drugemu kazalcu
p
j
g
• Kazalec lahko uporabimo tudi kod polje –
kazalčna aritmetika
kazalčna aritmetika
• Same kazalce lahko povečujemo ali zmanjšujemo kar ustreza pomikanju po polju z jš j
k
t
ik j
lj
indeksom.
Povezava med polji in kazalci na znake
Povezava med polji in kazalci na znake
polje
≡ &polje[0]
*polje
≡ polje[0]
polje+n ≡ n+polje ≡ &polje[n]
*(polje+n)
(polje+n) ≡ *(n+polje)
(n+polje) ≡ polje[n]
char niz[] = "abcdef";
char *pa,*pb;
*pa *pb;
pa = niz;
pa++;
niz++;
pb = niz;
/*
/*
/*
/*
pa kaže na 'a' */
pa kaže na 'b' */
napaka */
pb kaže na 'a' */
printf("%d\n" pb pa); /* vrne razliko indeksov = 1 */
printf("%d\n",pb-pa);
Zgled
• Naloga: l
Preoblikujte podprogram ZnakJeVNizu
tako, da bo uporabljal kazalce.
• Analiza in razgradnja:
g
j
Gre dejansko za drugačno implementacijo
podporama.
podpo
a a Vd
drugih
ug p
programskih
og a s
je
jezikih
(ki ne izhajajo iz C-ja) takšne povezave
običajno ni.
• Programska koda: KateriZnakVNizu2.c
Zgled – iskanje besed (1)
Zgled –
Zgled • Naloga: j p
program,
g
, ki bo p
po vrsti izpisal
p
vse
Izdelajte
besede nekega niza. Besede predstavlja
vsako zaporedje znakov
znakov, ki ni presledek ali
ločilo.
Zgled – iskanje besed (1)
Zgled –
Zgled • Analiza in razgradnja:
Besede so nizi znakov med posameznimi
presledki ali ločili. V nizu po vrsti iščemo znake,
ki predstavljajo začetek besede. Ko smo tak
znak našli, poiščemo konec besede in izpišemo
vse znake od začetka do konca. Nato se
premaknemo za tekočo besedo in postopek
ponovimo.
• Potrebujemo funkcijo, ki pove ali je podani znak
ločilo in proceduro za izpis posamezne besede.
Zgled – iskanje besed (1)
Zgled –
Zgled • Programska koda: Besede1.c, Besede2.c
Zgled – iskanje besed (2)
Zgled –
Zgled • Ali so številke besede? Da in ne. Če
Č
pri rešitvi p
problema upoštevati
p
želimo p
"človeško" pojmovanje besed, moramo
nekoliko obrniti pogoje
pogoje.
• Programska koda: Besede3.c
Zgled – iskanje besed (3)
Zgled –
Zgled • Kaj pa "besede" v C-ju? Besede v C-ju so
j
imena spremenljivk
p
j in ukazov.
dejansko
Ime "besede" v C-ju se mora začeti s črko,
ki ji sledi zaporedje črk in cifer.
cifer
• Programska koda: Besede4.c
Zgled – iskanje besed (4)
Zgled –
Zgled • G
Gremo še
š en korak
k k naprej.j Denimo,
D i
d
da bi
radi nekatere besede obravnavali drugače
od ostalih (npr
(npr. pri izpisu bi radi izpustili
rezervirane besede C-ja). V ta namen
potrebujemo funkcijo NizaStaEnaka,
NizaStaEnaka ki
preverja enakost dveh nizov. Ta funcija
mora
oap
primerjati
e jat črko
č o po črko
č od
dveh
e nizov,
o ,
dokler ne naletimo na razliko ali pa ne
pridemo do konca katerega
p
g od nizov.
• Programska koda: Besede5.c, Besede6.c
Standardne rezervirane besede
Standardne rezervirane besede
auto
double
int
struct
break
else
long
switch
case
enum
register
typedef
char
extern
return
union
const
fl
float
short
h
unsigned
i
d
continue
for
signed
void
default
goto
sizeof
volatile
do
if
static
while
Delo s tekstovnimi datotekami
Delo s tekstovnimi datotekami
• Tekstovne datoteke lahko obravnavamo kot p
j
j
zaporedje vrstic, ki jih lahko beremo samo eno za drugo. FILE *fopen(char * filename, char *mode);
int fclose(FILE *fp);
(
p)
int feof(FILE *fp);
Delo s tekstovnimi datotekami
• Nalogo, ki obdeluje ene niz znakov lahko
preuredimo v nalogo
g s
enostavno p
tekstovno datoteko tako, da obdelavo niza
preselimo v ločen podprogram
podprogram. Potem pa
pa,
ko beremo datoteko, za vsako vrstico
kličemo ta podprogram
podprogram.
• Namesto g
gets, uporabimo
p
fgets.
g
char *fgets( char *str, int n, FILE *fp ); Zgled
• Programska koda: StetjeCrk5.c, StetjeCrk6.c