1
Programski jezik C - 1. deo
(materijal sa predavanja D. Vitasa)
Struktura C-programa
• Struktura programa• Promenljive i ključne reči• Adresiranje
Struktura programa u C-u
• Program se sastoji od funkcija. • Sve funkcije imaju istu strukturu:povratni_tip ime( tipovi i imena parametara){ // početak bloka
deklaracije;iskazi;
} // kraj blokaGlavna funkcija ima ime main
2
Promenljive
• Promenljiva u C-u je označena imenom. Ime je niz karaktera koji počinje slovom i koje se još naziva identifikator.
• Promenljiva ima adresu, tip i vrednost!!!ime → adresa → vrednost
• Primer: int n; n = n* n;ime n, adresa ..., vrednost pre n = 12, posle n = 144
Promenljive
SintaksaIme promenljive (identifikator) u C-u je niska koja počinje slovom ili _, a zatim sledi bilo koji niz slova, cifara ili _.
[A-Za-z_][A-Za-z0-9_]*• razlikuju se mala i velika slova• dužina imena nije ograničena• broj značajnih karaktera zavisi od
implementacije, ali najmanje 31 za unutrašnje identifikatore (bar 6 za spoljašnje)
Ključne reči
U C postoje rezervisane (ili ključne) reči koje se ne mogu koristiti kao imena promenljivih:
Npr. int, float, char, void, long, ...struct, union, enum, ...while, if, for, break, continue, ...switch, default, goto, ...register, static, extern, ...
3
Unutrašnja memorija
• Podatak = 1 adresa + 1 niz bitova• Bitovi su okupljeni u grupe po 8 (bajt), a
zatim, u zavisnosti od mašine, u reči od 16, 32, 64 bita
• Svaka memorijska reč ima svoj broj: adresu u memoriji
• Sadržaj bajtova se kodira ASCII-kodom.
Promenljive
• Operator adresiranja &Ako je x ime promenlljive, &x je memorijska
adresa te promenljive (početak memorisjke zone koja je dodeljena promenljivoj x)
• Operator indirekcije (sadržaja) *Ako je (vrednost) promenljive p memorisjka
adresa, onda je *p promenljiva koja je pridružena toj memorisjkoj adresi.
• Tada: x je *&x p je &*p
Primeri strukture programa na C-u
4
Uvodni primer
Potrebno je napisati program u C-u koji izračunava tablicu konverzije evra u RSD:
1 802 1603 2404 3205 400, itd.
sve do 10 evra. Evro je ~ 85 (oktobar 2005!), ali ga zaokružujemo na 80 dinara.
Kako?
Počinjemo tako što izračunamo koliko je dinara jedan evro, zatim dva, itd. sve do deset. Evro uzima vrednosti 1, 2, ..., 10, a vrednost u dinarima se izračunava prema formuli
dinar = evro * 80
Program#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */int evro, dinar; int pocetak, kraj, korak;
pocetak = 1; kraj = 10; korak = 1; evro = pocetak; while( evro <= kraj ) {
dinar = evro * 80; printf( "%d\t%d\n", evro, dinar); evro = evro + korak;
}return 0;
}
5
Program#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */ KOMENTARint evro, dinar; int pocetak, kraj, korak;pocetak = 1; kraj = 10; korak = 1; evro = pocetak; while( evro <= kraj ) {
dinar = evro * 80; printf( "%d\t%d\n", evro, dinar); evro = evro + korak;
}return 0;}
Program#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */int evro, dinar; DEKLARACIJEint pocetak, kraj, korak;pocetak = 1; kraj = 10; korak = 1; evro = pocetak; while( evro <= kraj ) {
dinar = evro * 80; printf( "%d\t%d\n", evro, dinar); evro = evro + korak;
}return 0;}
Program#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */int evro, dinar; int pocetak, kraj, korak;pocetak = 1; kraj = 10; INICIJALIZACIJE; ISKAZI DODELEkorak = 1; evro = pocetak; while( evro <= kraj ) {
dinar = evro * 80; printf( "%d\t%d\n", evro, dinar); evro = evro + korak;
}return 0;}
6
Program#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */.....while( evro <= kraj ) { PETLJA ITERACIJE
dinar = evro * 80; printf( "%d\t%d\n", evro, dinar); TELO PETLJEevro = evro + korak;
}return 0;}Svaki red tablice se dobija na isti način --> ITERACIJASmisao: ispitamo najpre uslov. Ako je tačan, izvršava se telo petlje (između {}), pa
se opet ispituje uslov. Ako uslov nije tačan, prelazimo na sledeći iskaz (ovde kraj).
printf
Iskazprintf( "%d\t%d\n", evro, dinar);
se naziva funkcija printf. Njen prvi argument je format u kome će ispisati podatke.
• %d ukazuje da se ispisuje sledeći argument• d ukazuje da će to biti ceo (decimalni) broj • \t je escape-sekvenca za tabulator• \n je escape-sekvenca za novi red.
printf("%3d\t%6d\n", evro, dinar);je zapis brojeva fiksiranim brojem karaktera, poravnat
nadesno.
A pare (delovi dinara)?#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */float evro, dinar, kurs; int pocetak, kraj, korak;pocetak = 1; kraj = 10; korak = 1; evro = pocetak; kurs = 85.50;while( evro <= kraj ) {
dinar = evro * kurs; printf( "%6.2f\t%6.2f\n", evro, dinar); evro = evro + korak; }
return 0;}
7
Rezultat
printf( "%3.0f\t%6.2f\n", evro, dinar);1 85.502 171.003 256.50 ...
• Ako int kurs; ... kurs = 85.50; => kurs = 85!!!• Inverzno: kurs = 1/85.50 => kurs = 0!!!• %6.2f znači: realan broj zapisan sa 6 karaktera
na dve decimale. %3.0f bez decimala i bez decimalne tačke
Alternativa - petlja for#include <stdio.h>int main(void) {/* Tablica konverzije dinara u evre */int evro;
for( evro = 1; evro <= 10; evro = evro + 1 )printf( "%d %6.2f\n", evro, evro*85.50);
return 0;}
evro = 1 - inicijalizacijaevro <= 10 - uslovevro = evro + 1 - povećavanje brojača petlje
Simboličke konstante#include <stdio.h>#define POCETAK 1#define KRAJ 10#define KORAK 1
int main(void) {/* Tablica konverzije dinara u evre */int evro;
for( evro = POCETAK; evro <= KRAJ; evro = evro + KORAK )printf( "%d %6.2f\n", evro, evro*85.50);
return 0;}
8
Drugi primer• Program koji čita ceo broj i ispisuje njegov kvadrat:
#include <stdio.h>int main(void) {int n, m;
scanf("%d", &n );m = n * n; printf("Kvadrat broja %d je:"); printf("%d\n", m );
return 0;}
• Za n = 12, program ispisuje Kvadrat broja 12 je 144
Novi element#include <stdio.h>int main(void) {int n, m;
scanf("%d", &n );m = n * n; printf("Kvadrat broja %d je:"); printf("%d\n", m );return 0;}
&n - adresa promenljive n
Treći primer
Zadatak: Prebrojati slova u tekstu.
Tekst - sekvencija ASCII-karaktera - stiže, karakter po karakter, sa standardnog ulaznog uređaja (stdin). Ulazna funkcija koja omogućava čitanje jednog karaktera je
getchar( void )
9
Treći primer
Sekvenca char c; c = getchar( );
karakterskoj promenljivoj c dodeljuje vrednost pročitanog karaktera sa ulaza. Npr. ako pritisnemo dirku A (veliko A) na tastaturi, a u programu su gornji redovi, promenljiva c će sadržati vrednost 'A' (ASCII-karakter 65)
Treći primer
Program treba da broji karaktere sve do kraja teksta. Neka karakter '.' (tačka) označava kraj teksta. Takođe, neka program pravi razliku između blanko-karaktera (razmak, ' ') i ostalih karaktera.
Broj blanko-karaktera će biti upamćen u promenljivoj blanko, a broj ostalih karaktera u promenljivoj ostalo.
Treći primer/* Brojanje.c - Program prebrojava karaktere */ #include <stdio.h>#define BLANKO ' '#define TACKA '.'
main(){int blanko = 0, ostali = 0; char c; c = getchar(); while( c != TACKA ) {
if( c == BLANKO ) blanko = blanko + 1; else ostali = ostali + 1; c = getchar(); }
printf("Tekst sadrzi %d blanko i %d ostalih karaktera\n",blanko,ostali);}
10
Treći primer/* Brojanje.c - Program prebrojava karaktere */ ---> komentar #include <stdio.h>#define BLANKO '_' ---> makro-definicija za razmak (blanko)#define TACKA '.' ---> makro-definicija za tacku
main(){int blanko = 0, ostali = 0; ---> deklaracije sa inicijalizacijomchar c; ---> deklaracija karakterske promenljivec = getchar(); ---> ucitavanje karaktera sa tastaturewhile( c != TACKA ) { ----> sve dok nije TACKA
if( c == BLANKO ) blanko = blanko + 1; ---> ako je BLANKO ...else ostali = ostali + 1; ---> ako nijje BLANKO ..c = getchar(); } ---> procitajmo sledeci karakter
printf("Tekst sadrzi %d blanko i %d ostalih karaktera\n",blanko,ostali);}
Treći primerUnosimo sledeći tekst:
Ovo je tekst.
Program čita prvi karakter O, koji nije ni tačka, ni blanko, pa će povećati promenljivu ostali za 1. Slično i za karaktere v i o, pa promenljiva ostali dobija vrednost 3. Sledeći karakter je blanko, pa će i promenljiva blanko dobiti vrednost 1. Proces se nastavlja sve dok se ne pročita karakter opisan kao TACKA. Tada se izlazi iz while-petlje i program ispisuje rezultat:
Tekst sadrzi 3 blanko i 10 ostalih karaktera
Varijacije• Iskaz dodele
blanko = blanko + 1; se može zapisati i drukčije:
(a) blanko++; (b) blanko += 1;
Slično i za promenljivu ostali. • Kako iskaz dodele ima vrednost, vrednost iskaza
c=getchar() će biti pročitani karakter. Zbog toga, se učitavanje može potisnuti u uslov petlje:
while( ( c = getchar() ) != TACKA ) ...
11
VarijacijeSada se program može zapisati i na sledeći način: /* Brojanje.c - Program prebrojava karaktere */ #include <stdio.h>#define BLANKO ' '#define TACKA '.'
main(){int blanko = 0, ostali = 0; char c; while( ( c = getchar() ) != TACKA ) {
if( c == BLANKO ) blanko++; else ostali++;
printf("Tekst sadrzi %d blanko i %d ostalih karaktera\n",blanko,ostali);}
Primer za & i * • (primer03.c) /* x = *&x; p = &*p */
main(){int x, *p;p = &x;/* format %p je za adresu */printf("Adresa od x = %p = %p = %p\n", p, &x, &*p );/* Dodela vrednosti = konstanta */x = 1;printf("Vrednost od x = %c = %c = %c\n", x, *p, *&x );
}Rezultat: Adresa od x = 001D17 = 001D17 = 001D17
Vrednost od x = 1 = 1 = 1
Elementarni tipovi
• Šta je tip?• Celobrojni tip• Realni tip• Karakterski tip• Logički tip - neekspliciran u C-u
12
Tipovi
• Svaka promenljiva ima svoj tip. • Promenljiva se deklariše sa svojim tipom:npr. int n; float evro;• Osnovni (elementarni) tipovi su: char - karakterski tip int - celobrojni tip float - realni (u pokretnom zarezu)double - realni dvostruke tačnosti• Postoje i složeniji tipovi (nizovi, strukture).
Celobrojni tip
• Tip int se predstavlja sa 16 ili 32 bajta (u zavisnosti od mašine <limits.h>)
• Sa 16 bitova, vrednosti idu od -215 = 32768 do 215 - 1 = 32767
• Sa 32 bita, vrednosti idu od -231 do 231 - 1• Operacije su +, -, *, / (celobrojno deljenje),
% (ostatak pri deljenju).
Celobrojni tip (nastavak)
• Operatori+ : N × N → N <= : N × N → {⊥,T}
• Uslovi( a + b ) + c = a + ( b + c ) , ... a ≤ b i b ≤ c ⇒ a ≤ c, ...
• Implementacija x = 54710 BIN(547)= 0000001000100011-x = -54710 BIN(216+547) = 1111110111011101
13
Celobrojni tip (nastavak)
• a ∈ Na + ( - a ) = 0 = 2n (n - broj bitova)
jer onda-a = 2n - a= 20 + 21 + ...+ 2n-1 - a + 1
= (11....1111)2 - a + 1
Celobrojni tip
Kako deklarator int zavisi od implementacije, prenosivost programa se obezbeđuje deklaratorima
short, koji se uvek predstavlja sa 2 bajta long, koji se uvek predstavlja sa 4 bajta
Celobroji tip
Modifikacija interne reprezentacije se može postići deklaratorima
signed - binarni sadržaj sadržaj se interpretira kao označeni ceo broj ili
unsigned - binarni sadržaj sadržaj se interpretira kao neoznačeni ceo broj (>=0)
14
Realni tip
• Realni broj x se predstavlja u pokretnom zarezu (zapeta, tačka) pomoću dva cela broja m i e:m (mantisa) m ∈ [-M, M], M > 0e (eksponent) e ∈ [-E, E], E > 0B (osnova) - je 2
x = m * Be
Normalizovana mantisa: M/B < m < M
• Gustina: [0.1, 1] ima isto "realnih" brojeva kao i [104, 105] za osnovu B = 10.
Realni tip (nastavak)
• Operatori su +, -, *, /, ...+ : R × R → R <= : R × R → {⊥,T}
• Uslovi uređeno telo• Postoji konverzija između različitih tipova.
Npr. ako je x float, x + 1 je float.• Opseg: od 10-38 do 10+38
• Karakteristike implementacije
Realni tip (nastavak)
• Tip float se predstavlja sa 32 bita u obliku (normalizovane) mantise i eksponenta.
standard IEEE: x = ( -1 )s . 2 E - 127 . 1,Fs - znak, E - eksponent, 1,F - normalizovana mantisa
• 24 bita za mantisu ==> 6 značajnih cifara (bez obzira na eksponent)
• znak mantise - 1 bit, eksponet - 8 bitova, mantisa - 23 bita
15
Realni tip (nastavak)0,8 = (-1)0 . 2 126-127 . 1,10011001100 … 2
0,75 = (-1)0 . 2 126-127 . 1,100 … 2
0,8 - 0,75
0,05 = (-1)0 . 2 122-127 . 1,10011001100 … 2
0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
0 0 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0
0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
Realni tip (nastavak)
• float x, y; Kada je x == y ?
• epsilon mašine to je najmanji r takav da je
1 + r != 1 • <float.h> - definicija konstanti za realni tip
koje zavise od implementacije (maksimalni eksponent, preciznost, itd.)
Karakterski tip
• Tip char se predstavlja jednim bajtom. • To su karakteri opisani ASCII-kodom.
Svaki karakter je i broj!• Oprezno: '0' je 48, a '\0' je nula!• Neki kontrolni karakteri se zapisuju na
poseban način: '\n' '\r' '\t'• Niske karaktera se pišu kao "Zdravo!\n"
16
Karakterski tip
• ... podskup tipa celih brojeva• ... zavisi od implementacije
(a) {-128, ..., +127} (signed char)(b) {0, ..., +255} (unsigned char)
• Operacije - kao za cele brojeve• Posebne funkcije ( <ctype.h> )
Karakterski tip(primer25.c)
/* Ako se stavi a <= 127, u poslednjem prolazu:* 127 + 1 = -128; pa imamo beskonacnu petlju */char a;for( a = -128; a < 127; a++) printf("%d %c\n", a, a );
? Šta se dešava ako:unsigned char x;for( x = 0; x < 255 ; x++) printf("%d %c\n", x, x ); ?
kod nekih kompilatora
Karakterske konstante
1. karakter pod navodnikom 'A', '1'2. karakter kao ceo dekadni broj: 65, 493. karakter kao oktalni broj: '\101', '\61'4. karakter kao heksadecimalni: '\x41',
'\x31'5. Escape-sekvence za grafičke karaktere
? - '\?' " - '\"' \ - "\\" ' - '\''Primer: '*' = 42 = '\52 ' = '\x2A'
17
Karakterske konstante
int main( void ) {char a, b; a = 'A'; b = 65; printf(" %ch! %ch! \n", a, b ); printf(" %c %d\n", a, a );
}rezultat: Ah! Ah!
A 65
Logički tip
• Ne postoji eksplicitni logički tip kao što je boolean u Paskalu
• vrednost 0 je netačno, a ≠ 0 tačno
Izrazi
• Struktura izraza• Aritmetički izrazi• Logički izrazi
18
Izrazi• Sintaksa izraza ;
izraz;• Izrazi se konstruišu koristeći imena promenljvih i ,
konstanti koristeći operatore i to:– aritmetičke operatore +, *, -, /, ... – relacione operatore >, >=, ==, !=, <, <=, ... – logičke operatore: && (i), || (ili), ! (ne)
• Izraz ima tip: char, int, float... • Izraz ima vrednost: rezultat izračunavanja• Izraz može imati akciju (bočni efekat)
Izračunavanje izraza
Izrazi se izračunavaju primenom1. pravila o prioritetu i asocijativnosti
operatora2. pravila koja definišu tip podizraza3. vrednost izraza zavisi od tipa elemenata
koji u njemu učestvujuPrimer. a = 5; b = a/2;
Ako su a, b int, b = 2; Ako su a, b float, b = 2.5
Primeri
char c;int i, j: float x;
i - j je tipa inti * x je tipa floati + c je tipa int'2' < 'A' je neki ceo broj (1, tačno)
19
Aritmetički izrazi
Primer (K&R): Pretvoriti temperaturu datu u Farenhajtima u Celzijuse. Formula je
C = ( F - 32 ) * 5./9
Npr. 100 F = 37.8 C
Program F -> Cint main(void) { float F, C;
printf("Zadati temperaturu u Farenhajtima: "); scanf("%f",&F); C = (F - 32) * 5. / 9; printf("Vrednost u Celzijusima": %3.1f\n",C);
return 0; } Zadati temperaturu u Farenhajtima: 100
&F <- 100; &C <- (F-32) * 5 / 9 = 37.7777Vrednost u Celzijusima: 37.8 (zaokruženo na jednu decimalu)
Aritmetički izrazi
• Izraz se izračunava prema pravilima o prioritetu i asocijativnosti
C = (F - 32) * 5. / 9;
* i / su istog prioriteta, koji je veći od prioriteta -.
20
Logički izrazi
• Logičke vrednosti se u C-u predstavljaju kao 0 (netačno) i 1 (tačno; zapravo ≠ 0 je tačno)
• Logički izraz se obrazuje od relacionih operatora (>, ==, ...) i logičkih operatora.
• Logički operatori
10100010&&
11110010||
"Lenjo" izračunavanje
• Logički izraz se izračunava "lenjo":
– Ako je A tačno, onda je A || B tačno, a B se ne izračunava;
– Ako je A netačno, onda je A && B netačno, a B se ne izračunava
• Ovo je opasno ako se nema u vidu!
Primer
main() { boolean x,y,z;int a = 1, b = 2, c = 3;
x = 1; y = 0;z = x && !y;printf(" %d\n", z ); /* Izlaz je 1 *//* Lenjo izracunavanje logickog izraza */x = !(a >= b); y = b == c;z = x || !y;printf(" %d\n", z ); /* Izlaz je 1 */
}
21
Pregled iskaza u C-u
• Blok • Izraz dodele, slaganje (kompozicija)
iskaza • Uslovni iskazi i izrazi; složeno grananje• Iterativni iskazi
Deklaracije• U C-u se deklaracije i iskazi okupljaju u blokove oblika:
{lista deklaracja
lista iskaza BLOK}
Deklaracija je oblika: tip ime; npr. int a; ili oblika tip ime = vrednost; (inicijalizacija), npr. int a = 1;
Izraz dodele
... je osnovni mehanizam u programiranju koji dopušta da se promeni vrednost neke promenljive:
x = e;dodeljuje promenljivoj x vrednost izraza e.S leve strane iskaza dodele mora biti
adresa (L-value).
22
Lvalue i Rvalue
Ako jedan izraz ima tip i vrednost, ali mu nije pridružena adresa, on predstavlja Rvalue (desna strana, npr, dodele)
Ako izraz ima tip, vrednost i adresu onda on može biti Lvalue (npr. leva strana dodele)
Na primer, u izrazu x = y = 2*x+y, izraz 2*x+y će imati vrednost i tip (u zavisnosti od vrednosti i tipa x i y), ali ne i adresu, pa ne može biti Lvalue
Sekvencije iskaza
• Iskazi se dopisuju jedan na drugi, a razdvaja ih simbol ;
iskaz1; iskaz2; iskaz3;
Primeri iskaza dodele1. i = i + 1; /* povećava vrednost i za 1 */
Alternativno: i++;2. Swap (trampa)
int x, y, temp; // x = 1, y = 2temp = x; // temp = x = 1x = y; // x = 2 y = temp; // y = 1
3. Alternativa:x = x + y; // x = 2 + 1 = 3y = x - y; // y = 3 - 2 = 1 x = x - y; // x = 3 - 1 = 2
23
Uslovni iskaz
• Kratki (nepotpuni) oblik if( uslov )
iskaz• Puni oblik
if( uslov )iskaz
elseiskaz
Uslov je logički izraz (izraz celobrojnog tipa)!
Primer
• Minimum dva brojaint x, y, min; // x = 2, y = 3 if( x < y ) { // x < y ? da
min = x; // min = 2 }else { // ne izvršava se
min = y; }• Skraćeno: min = ( x < y ) ? x : y
Primer• Minimum tri cela broja ( int, a, b, c, min;)
if( a < b && a < c) // Ako nije, min je b ili cmin = a;
else if( b < c ) // b < c, b < a min = b;
else // c < b, c < amin = c;
• Zagrade se izostavljaju ako je u bloku jedan iskaz!• Kako u skraćenoj notaciji?
24
Uslovni izrazimain() { // primer27.c
int x = -7, y = 6, z = 9;int abs, max, n;
/* Apsolutna vrednost */abs = x >= 0 ? x : -x;printf("%d\n", abs ); // abs = 7
/* Maksimum tri broja */max = x > y ? x > z ? x : z : y > z ? y : z;printf("%d\n", max ); // max = 9
/* Niske u uslovnom izrazu */for( n = 1; n < 7; n ++ )printf("Ima %d elemen%s\n", n, n > 1 ? n > 4 ? "ata":"ta" :"t" );
}
Složeno grananje: switch
Ako x uzima više vrednosti, onda se može koristiti switch-iskaz, npr. switch (x){ case 0: printf("nula"); break; case 1: printf("jedan"); break; case 2: printf("dva"); break; ... case 9: printf("devet"); break; default: printf("greska"); }
• Uloga iskaza break! Ako x = 0, bez break: nulajedandva...
ITERACIJE (PONAVLJANJE) - PETLJE
Tri moguća oblika za izražavanje ponovljenog izračunavanja su:
petlja za (ključna reč for)petlja sve dok - radi (while)petlja radi - dok nije (do-while)
25
Petlja for
Sintaksa:for(inicijalizacija; uslov; korak){
lista iskaza }Značenje: izvršava se
inicijalizacija, (ispitivanje uslova, lista iskaza, korak)(ispitivanje uslova, lista iskaza, korak)...
Primeri
1. for( i = 1; i <= n; i++) {x = x + 1; }
znači da će se vrednost promenljive xuvećati za 1 n puta.
2. for ( i = 0; i <= 10; i++) printf("%d ", i);
ispisuje 0 1 2 3 4 5 6 7 8 9 10
Primer
3. int p, i, n = 3; for( p = 1, i = 0; i < n; i++, p = p * x );
Dvostruka inicijalizacija!Na mestu koraka, može se naći i lista iskaza!
4. Zbir prvih n prirodnih brojeva:for( s = 0, i = 1; i <= n; s = s + i, i++ );
26
Petlja while
Sintaksa while( uslov ) {
lista iskaza }Značenje
Ispitati da li je uslov pre nego što se izvrši lista iskaza. Ako je uslov ispunjen, izvršiti listu iskaza. Inače, završiti sa izvršavanjem. Lista iskaza se ne mora izvršiti nijednom.
Primeri
1. Izračunati prvi stepen broja 2 koji je veći od zadatog N. p = 1; while( p < N ) {
p = 2 * p; }Za N = 100, p = 128, a za N = 200, p = 256...
Primeri
2. Vreme izračunavanja - petlja može da se izvršava (ponekada) vrlo dugo!
int main( void ) {while( 1 ); return 0;
}se nikada ne zaustavlja!
27
Petlja do - while
Sintaksa do {
lista iskaza} while( uslov );
ZnačenjeIspitati da li važi uslov pošto se izvrši
lista iskaza. Lista iskaza se izvršava bar jednom!
Razlika između while i do-while
while( i <= n ) i = i + 1;Ako je i <= n pre izvršananja while, posle
izvršavanja će biti i = n + 1. Ako je i > n, posle izvršavanja, i očuvava svoju vrednost.
do { i = i + 1; } while( i <= n );Ako i <= n pre, posle i = n + 1. Inače, vrednost i uvećana je za 1!
Primeri
1. Proveriti da li je dati broj n prost.int main(void){ int d = 1, n, r; printf("Uneti ceo broj: "); scanf("%d", &n); do { d = d+1;
r = n % d; // r - ostatak pri deljenju n sa d } while (r >= 1 && d*d <= n); // ako r == 0, deljive je sa d
if (r == 0) printf("Broj %d je deljiv sa %d\n",n, d); else printf("Broj %d je prost\n", n);
return 0; }
28
Primeri
2. ......do {
printf("Ceo broj između 0 i 10? "); scanf("%d", &a ); printf("Broj je %d\n", a );
} while( a < 0 || a > 10 ); ......
Prekidanje iteracije
• continue odnosi se na najbližu petlju, a izaziva prelaz na sledeći korak
• breakodnosi se na najbližu petlju ili grananje, a izaziva prekid petlje ili grananja
• return - odnosi se na prekid funkcije
Primer
int x, zbir = 0; ......while( 1 ) {
scanf("%d", &x ); if( x == 0 ) break; // izlaz iz petljeelse if( x < 0 ) continue; // čita sledećielse zbir = zbir + x; }
printf("Suma pozitivnih brojeva: %d", zbir );
29
Bezuslovno grananje
Sintaksa goto etiketa;......etiketa: iskaz;
Prenos izračunavanja na tačku programa obeleženu etiketom. Etiketa mora biti unutar funkcije u kojoj je definisana. Nema skoka iz jedne funkcije u drugu. OPASNO!
Prevođenje iteracija
Na nivou asemblera, iteracije se prevode na niz instrukcija koristeći iskaz GOTO.
Npr. while( i <= n ) iskaz; se prevodi na 1: IF i > n GOTO 2
iskazGOTO 1
2: ...
Prevođenje
for( i = 1; i <= n; i++ ) iskaz; se prevodi u:
i = 1; 1: IF i > n GOTO 2
iskaz; GOTO 1
2: ...
30
Iteracija i rekurentne formule
Iterativni programi omogućavaju da se implementiraju veze zadate rekurentnim formulama.
Primer. Fibonačijev niz je definisan sa: f0 = f1 = 1fn = fn-1 + fn-2
ili niz: 1, 1, 2, 3, 5, 8, 13, 21, ...
Prvih 20 u Fibonačijevom nizuint main(void) { int i,u,v,w;
u = 1; v = 1; // inicijalizacijafor (i = 1; i <= 20; i++) {
w = u + v; // novi članprintf("%d ",w); u = v; v = w; // reinicijalizacija
} return 0;
}Rezultat: 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
10946 17711
Invarijanta petlje
Zaključivanje o tome šta jedan iterativni program radi se zasniva na principu indukcije.
Da bi to bilo moguće, koristi se neko svojstvo koje je tačno prilikom svakog prolaska kroz petlju, a koje nazivamo invarijanta petlje.
31
Primer invarijante
U programu za Fibonačijev niz, sledeće svojstvo je tačno prilikom svakog prolaska kroz petlju:
P(i): u = fi-1, v = fiDa bi se ovo dokazalo, mora se pokazati: (a) da je tačno P(0) (tj. da je P tačno pri
prvom ulasku u petlju)(b) Ako je P tačno u jednom prolazu (npr. i),
onda je tačno i u sledećem (tj. za i+1).
Još jedan primerFaktorijel izračunava sledeći program:
int main(void) { int i, n, fakt; scanf("%d",&n); fakt=1; for (i=2; i<= n; i++)
fakt = fakt * i; printf("%d!=%d\n", i, fakt); return 0;}
Invarijanta petlje je fakt = (i - 1)!.
Primer: binarni zapis
Binarni zapis celog broja x je niz (bk, ..., b1, b0)
definisan formulom:x = bk 2k + ... + b121+ b0 20
Izračunavanje u dva koraka:1. Izračunava se y = kao najveći ceo broj y koji je
stepen broja 2 i y ≤ x2. Zamenjuje se y sa y/2 oduzimajući y od x svaki
put kada je y ≤ x i ispisuje se 0 ili 1 prema vrednosti uslova.
32
Programint main(void) { int x,y,n; 1 scanf("%d", &n); x = n; y = 1; // inicijalizacija2 while (2*y <= x) y = 2*y; // korak1 formiranje y = 2k ≤ x
// y + y = 2y u svakom koraku3 while (y != 0) { // y - najveći stepen od 2 < x4 if (x < y) printf("0"); // binarna 05 else { 6 printf("1"); // binarno 17 x = x - y; } // sledeće x8 y = y / 2; } // sledeće y
return 0; }
Rezultat(red 1) n = 9, x = 9, y = 1 (red 2) y=8(red 3) y != 0 i ( red 4) y < x --> (red 6) 1(red 6) x = 1, ( red 7) y = 4(red 3) y != 0 i ( red 4) y > x --> (red 4) 0( red 7) y = 2(red 3) y != 0 i ( red 4) y > x --> (red 4) 0( red 7) y = 1(red 3) y != 0 i ( red 4) y < x --> (red 6) 1(red 6) x = 0, ( red 7) y = 0
n = 1 * 23 + 0 * 22 + 0 * 21 + 1 * 20 = (9)10
Još o tipovima
• Modifikatori tipa• Različiti zapisi konstanti • Tip void• Saglasnost tipova• Prioritet i asocijativnost• Podešavanje (koercija, cast)
33
Modifikatori tipa ili još o int
• int se može skladištiti na 2 ili 4 bajta. • funkcija sizeof( tip ) kazuje koliko je
bajtova potrebno za skladištenje tipa. Npr. sizeof( char ) je 1• Celobrojni tipovi mogu da se modifikuju:
– short/long– signed/unsigned
Primenjuju se na int i char (char - "mali" int)
Modifikatori int
1. short int ~ short; sizeof( short ) = 22. long int ~ long; sizeof( long ) = 43. Predefinisani modifikator: signed int
Primenjuje se signed (long |short|ε) int.4. Modifikator: ceo neoznačen broj
unsigned (long |short|ε) intunsigned short int ∈{0, ..., +65535}
Celobrojne konstante
• Oktalna ako je prefiks 0 (nula): npr. (032)8 = (26)10
• Heksadecimalna ako je prefiks 0x:npr. (0x32)16 = (50)10
• Long ima sufiks l ili L:npr. (0xaf9fL)16 = (44959)10
• Unsigned ima sufiks u ili U: npr. (0xffffu)16 = (65535)10
34
Tip void
... je "prazan" tip. Omogućava:• koristi se za funkcije bez parametara ili
vrednostinpr. void main( void) ...
• konverzija izraza u tip void znači da se njegova vrednost ne uzima u obzir
• koristi se kod pokazivača (kasnije!)
Salasnost elementarnih tipova
SVI ARITMETIČKI TIPOVI (celovrojni, karakterski, realni) SU MEĐUSOBNO SAGLASNI
Ovo znači da kompilator dopušta da se u aritmetičkom izrazu koriste objekti ovih tipova, bez eksplicitne naznake konverzije!
Pravila o salasnosti elementarnih tipova
U izračunavanju jednog izraza poštuju se sledeće implicitne konvencije:
1. Ako u izrazu nema promenljivih koje su unsigned, onda se objekti konvertuju u najjači tip prema sledećem redosledu:
long double, double, float, long int, int2. Pravila za unsigned zavise od implementacije!3. Celobrojna promocija: aritmetičke operacije se vrše
najmanje na tipu int, što znači da se char i shortkonvertuju u int
4. U zavisnosti od implementacije, char može biti < 0!
35
Primer (promocija - democija)1. char c; short s; long l; (primer28.c)
float f; long double g; c = s * l; // s=100, l=100L --> c = 16 !f = 2 * g; // g=1.333333331 --> f = 2.666667
// (gubitak decimala)
U izračunavanju s*l, s se konvertuje u long, a rezultat s*l se konvertuje u char u dodeli vrednosti promenljivoj c.
2 se konvertuje u long double u izračunavanju 2*g, arezultat se konvertuje u float prilikom dodele f i gube se
decimale.
Podešavanje tipova (casting)... tip izraza (promenljive) se može forsirati:
(ime_tpa) izraz;
primer29.c
void main( void ) { int i, j; double x, y, z, t;i = 5/2; // 2 x = 5/2; // 2y = (double) (5/2); // 2 j = (double) 5/2; // 2z = (double) 5/2; // 2.5t = 5./2; // 2.5
printf("%d %g %g %d %g %g\n", i, x, y, j, z, t); }/* rezultat: 2 2 2 2 2.5 2.5 */
Oprezno sa podešavanjem!Prilikom dodele, leva strana dodele se pretvara u tip desne strane (tip
rezultata). Ovo može dovesti do neoderđenosti rezultata, gubitka tačnosti (npr. double u float ili float u long int), gubitka bitova veće težine (long int u int). (primer30.c)
char c = -126; short s; s= c; // Promocija0111 1110 = 126
char c (1 bajt) 1000 0010 = - 126 // Dopuna do 2n
short s (2 bajta) 1111 1111 1000 0010 = -126 // Dopuna do 2n
char c; short s = -32767; c= s; // Democijashort s (2 bajta) 1000 0000 0000 0001 = -32767 char c ( 1 bajt) 0000 0001 = 1
36
Oprezno sa podešavanjem!
unsigned char c = 255; short s; c= s; // Democijachar c (1 bajt) 1111 1111 = 255short s (2 bajta) 1111 1111 1111 1111 = -1
unsigned char c; short s = 255; s= c; // Democijashort s (2 bajta) 0000 0000 1111 1111 = 255char c (1 bajt) 1111 1111 = 255
Prenosivost tipova
Neka zaglavlja C-a sadrže karakteristike pojedinih tipova:
<limits.h> - za elementarne tipove (max, min,..)
<float.h> - za realne brojeve (max. eksponent, epsilon mašine,...)
<stdlib.h> - funkcije za konverziju tipova
Prioritet i asocijativnost1. unarni operatori imaju isti prioritet (među najjačim)2. multiplikativni operatori ( * / % ) imaju isti prioritet koji je
veći od prioriteta aditivnih operatora (+ -)Npr. -a*b+c je ((-a)*b)+c3. unutar iste klase prioriteta, operatori asociraju sleva na
desno, osim unarnih operatora i operatora dodele (sdesna na levo)
Npr. a/b*c je (a/b)*c,, a ne a/(b*c)4. Redosled izračunavanja zavisi od implementacije osim
za (a) logičke izraze &&, || (b) uslovni izraz ? : i (c) kompoziciju , (zapeta)
37
PrimeriSvaki izraz koji zavisi od redosleda izračunavanja se
smatra neispravnim!!!
Korektni izrazi: Nekorektni izrazi:x*y+z/4*7 i = i++'A' + 32 (x = 3) * x (int) 'A' - 20x = 1, y = 3 * x
Ali i x = y = z = 32 * ( x = 3 ) + 1
Operatori ++ i --• Primenjuju se na celobrojni i realni tip• Vrednost je definisana sa:
• ++ i -- se primenjuju na izraz koji označava objekat u memoriji, npr, na identifikator, ali ne na konstantu ili aritmetički izraz (++5 ili (i+j)-- nemaju smisla).
i-1
i-1
--i
i+1vrednost i posle
iii+1vrednost
i--i++++iizraz
Primeri i bočni efekatmain() { // (primer26.c)
int i = 0, j = 0,, z;/* Bocni efekti */z = i++ && j ++; // i = 1 j = 0printf( " %d %d %d\n", i, j, z ); // z = 0i = 0; j = 0;z = j++ && i ++; // i = 0 j = 1printf( " %d %d %d\n", i, j, z ); // z = 0z = j++ && i ++; // i = 1 j = 2printf( " %d %d %d\n", i, j, z ); // z = 0z = j++ && i ++; // i = 2 j = 3printf( " %d %d %d\n", i, j, z ); // z = 1
}
38
Dodela
Dodela je izraz.
x = <izraz>
1. tip izraza je tip x2. vrednost izraza (posle izračunavanja)
postaje vrednost x
Primer
• Ako je deklarisano float x; onda je:
x = sqrt(16);izraz tipa float, čija je vrednost 4.
• Promenljiva x, posle izračunavanja izraza, ima vrednost 4.
• Posledica: x = y = z = 4; je izraz koji se interpretira kao x = (y = (z = 4))(asocijativnost sdesna)
Proširena dodela
x op = <izraz>je ekvivalentno sa x = x op (<izraz>)
(osim ako se x ne izračunava samo jednom)op je neki od aritmetičkih operatora:
+= -= *= /= %= &= ...
39
Primer
1. x *=a+b je ekvivalentno sa x = x * (a + b ), a ne sa x = x * a + b!
2. x /= x - 1 je ekvivalentno sax = x / (x -1)
3. Pažnja = je različito od ==!!! r=1; if( r = 0 ) printf("NULA");
else printf("%d", r); ==> 0!!!
Obim tipa - sizeof
• Moguće su dve primene: sizeof( tip )sizeof izraz
... vraća dužinu u bajtovima datog tipa ili tipa izraza
Primer. sizeof( short ) je 2; sizeof( long ) je 4
Povezivanje iskaza zapetom
izraz1, izraz2, ..., izrazn• vrednosti se računaju sleva na desno• vrednost povezanog izraza je vrednost
poslednjeg izračunatog člana
Primer. x = 1, y = 2, z = x * y + 1Vrednost celog izraza je vrednost z (3)