Sunteți pe pagina 1din 21

11/9/2016

Programarea Calculatoarelor și CUPRINS


Limbaje de Programare I. Intrare cu format - scanf
II. Ciclul for
CURS 3 III. Constante simbolice
IV. Citirea şi scrierea caracterelor
- suport de curs - IV.1 Copierea fişierelor
IV.2 Numărarea caracterelor
IV.3 Numărarea liniilor
Date și instrucțiuni. Aplicații IV.4 Numărarea cuvintelor
V. Aplicații cu tablouri
VI. Aplicații cu numere
17:50 PCLP CURS 3 2

• Funcţia scanf reprezintă analogul pentru citire


al lui printf ,
 punând la dispoziţie multe dintre aceleaşi
facilităţile de conversie,
 dar în sens opus.

• scanf citeşte caractere de la intrarea standard,


 le interpretează în conformitate cu specificatorul
I. INTRARE CU FORMAT - scanf de format şi
 stochează rezultatele în adresele specificate de
argumentele rămase.
17:50 PCLP CURS 3 4

• Prototipul funcţiei scanf se găseşte în fişierul • Funcţia scanf formatează fiecare câmp
stdio.h şi este: conform formatului specificat în
lista_de_formate.
int scanf(const char *lista_de_formate
[,adresa,..]);
 Din caracterele citite se calculează valori numerice
sau literale,
 conform tipului fiecărei variabile,
• Această funcţie realizează următoarele operaţii :
 dimensiunilor de format specificate şi
 citeşte de la tastatura o secvenţă de câmpuri de  a separatorilor de câmpuri predefiniţi (spaţiu, tab
intrare, şi enter) sau impuşi explicit ;
 caracter cu caracter,
 valorile astfel construite sunt stocate la
 până la terminarea introducerii câmpurilor şi adresele variabilelor specificate ca argumente ;
apăsarea tastei <Enter> : 
17:50 PCLP CURS 3 5 17:50 PCLP CURS 3 6

PCLP CURS 3 1
11/9/2016

scanf • Pentru funcția de citire scanf trebuie folosit


operatorul adresă “&”.
• Ordinea din lista_de_formate a formatelor • Pentru variabilele citite cu această funcție trebuie
variabilelor precizate adresele la care se stochează în
memoria calculatorului valorile variabilelor.
 trebuie să coincidă cu ordinea listei adreselor
variabilelor în care se face citirea. • Funcția va introduce valorile citite direct la acele
adrese.
• Fiecare variabilă care se dorește a fi citită • Singurul caz în care nu este obligatorie folosirea
 trebuie corelată cu un format specific din operatorul adresă pentru citirea valorii unei
lista_de_formate.
variabile cu funcția scanf este
 citirea unui şir de caractere.
17:50 PCLP CURS 3 7 17:50 PCLP CURS 3 8

&i = adresa lui i



#include <stdio.h>
&rd


• Funcţia scanf se opreşte când îşi epuizează şirul
main() 
{ &c
i rd de caractere referitor la format,
int i;
char c;
c
r
 sau când o anumită dată de intrare nu corespunde
float r; Mem. internă specificatorului de control.
double rd;

printf("Introduceti un caracter = "); scanf("%c", &c); • Funcţia returnează ca valoarea a sa numărul de


printf("Introduceti un nr intreg = "); scanf("%d", &i);
printf("Introduceti un nr real = "); scanf("%f", &r); obiecte citite,
printf("Introduceti un nr real dublu = "); scanf("%le", &rd);
 care au fost conforme cu specificatorii şi atribuite
printf("\nVariabilele introduse sunt :\n");
printf("Caracterul = %c\n", c); cu succes.
printf("Nr intreg = %d\n", i);
printf("Nr real = %f\n", r);  Această valoare poate fi folosită pentru a
}
printf("Nr real dublu = %e\n", rd); determina câte obiecte au fost găsite.
17:50 PCLP CURS 3 9 17:50 PCLP CURS 3 10

scanf scanf
• În cazul întâlnirii sfârşitului de fişier (^Z = CTRL+Z), • Specificatorii de format sunt alcătuiţi din
se returnează EOF;  caracterul %,
 reţineţi că acesta este diferit de 0,  un caracter opţional * (asterisc) pentru
suprimarea atribuirii,
 ceea ce înseamnă că următorul caracter de la
intrare nu este conform cu primul specificator din  un număr opţional pentru specificarea
şirul ce conţine formatul. dimensiunii maxime a câmpului,
 un caracter opţional h, H sau L pentru a indica
• Următorul apel către scanf reia căutarea dimensiunea spaţiului de destinaţie şi
imediat după ultimul caracter deja convertit.  un caracter de conversie.
17:50 PCLP CURS 3 11 17:50 PCLP CURS 3 12

PCLP CURS 3 2
11/9/2016

scanf Ușor modificat, programul poate fi folosit


#include <stdio.h> pentru extragerea părții întregi și părții
• Un specificator de format controlează conversia zecimale a unui număr real (TEMĂ).
main()
următorului câmp de la intrare. {
int a, b;
• În mod normal rezultatul este stocat în variabila spre
printf("introduceti doua numere intregi separate
care indică argumentul corespunzător. printr-un caracter = ");
%*c: suprimă citirea caracterului
scanf("%d%*c%d",&a,&b); dintre cele două numere întregi.
• Cu toate acestea, dacă prin caracterul * se indică
printf("primul numar = %d\n", a);
suprimarea atribuirii (vezi programul următor în care se printf("al doilea numar = %d\n", b);
suprimă - %*c - citirea unui caracter aflat între două numere întregi), }

 se sare peste acel câmp (este ignorat);


 nu se efectuează nici o atribuire.
17:50 PCLP CURS 3 13 17:50 PCLP CURS 3 14

#include <stdio.h> • Un câmp de la intrare este definit ca un şir de


main() caractere care nu sunt spaţii albe;
{
int zi, luna, an;  acesta se întinde până la următorul caracter care
printf("data calendaristica = "); Programul citește o dată este un spaţiu alb sau
scanf("%2d%2d%4d", &zi, &luna, &an); calendaristică (zi, lună, an)
în care cele trei numere  atât cât indică dimensiunea câmpului (dacă este
printf("ziua = %d\n", zi); întregi corespunzătoare specificată).
printf("luna = %d\n", luna); zilei, lunii și anului sunt
printf("anul = %d\n", an); scrise fără separație între Caracterele de tip spaţiu alb
} ele.
spaţiul caracterul retur de car
tabulatorul tabulatorul vertical
scanf permite citirea unor valori de dimensiune fixă ( în cazul
nostru 2 cifre, 2 cifre, 4 cifre: %2d%2d%4d ), oprind citirea datelor caracterul caracterul pentru saltul la
chiar dacă următorul caracter corespunde formatului datei curente. rând nou pagină nouă la imprimantă
17:50 PCLP CURS 3 15 17:50 PCLP CURS 3 16

scanf Caracter Date citite; Tip argument

• Caracterul de conversie (vei tabelul următor) indică caractere; char *. Următoarele caractere de la intrare (în
mod implicit 1) sunt stocate în spațiul indicat. Regula
c
 modul de interpretare a câmpului de la intrare. obișnuită de salt peste spațiile albe este eliminată; pentru a
citi următorul caracter diferit de spațiu alb, folosiți %1s.
Caracter Date citite; Tip argument
d întreg zecimal; int * șir de caractere (care nu se află în ghilimele); char *,
indicând spre un tablou de caractere suficient de mare pentru
întreg; int *. Întregul poate fi în octal (cu 0 în față) sau în s
i a stoca șirul și un caracter terminator '\0' care va fi
hexazecimal (fiind precedat de 0x sau de 0X)
adăugat. Citirea se oprește la primul spațiu alb întâlnit.
o întreg octal (cu sau fără un zero în faţă); int *
e, f, număr în reprezentare virgulă mobilă cu semn opțional, punct
întreg zecimal fără semn; unsigned int * g zecimal opțional și exponent opțional; float *.
u
întreg hexazecimal (cu sau fără 0x sau 0X în faţă); int * % caracterul % ; nu se efectuează nici o atribuire.
x

17:50 PCLP CURS 3 17 17:50 PCLP CURS 3 18

PCLP CURS 3 3
11/9/2016

Ce afișează programul următor ... Ce afișează programul următor ...

dacă se tastează 011 ? dacă se tastează 011 ?


#include <stdio.h> #include <stdio.h>
main() main()
{ {
int t; int t;
scanf("%i", &t); dacă se tastează 0XA ? scanf("%o", &t); dacă se tastează 11 ?
printf("%d", t); printf("%d", t);
} }

17:50 PCLP CURS 3 19 17:50 PCLP CURS 3 20

Ce afișează programul următor ... Ce afișează programul următor ...


#include <stdio.h>

dacă se tastează 0xA ? main()


#include <stdio.h> {
char sir[10]; /* se declara un sir de caractere */
main() printf("Dati un sir de caractere = ");
{ scanf("%s", sir);

int t; printf("Sirul de caractere citit a fost = %s\n", sir);


}
scanf("%x", &t); dacă se tastează a ?
printf("%d", t); dacă se tastează șir1 șir2 șir3 ?
}

17:50 PCLP CURS 3 21 17:50 PCLP CURS 3 22

Ce afișează programul următor ... scanf - caracterele opționale


#include <stdio.h> • Caracterele de conversie d, i, o, u şi x
main()
{  pot fi precedate de caracterul opțional h
float r = 2.3131318;
 pentru a arăta că în lista de argumente apare o
printf("Dati un numar real = "); adresă (un pointer) spre tipul short şi
scanf("%%", &r);
 nu unul spre tipul int,
printf("%f", r);
}  sau de caracterul opțional l (litera el)
dacă se tastează 123.123 ?
 pentru a arăta că în lista de argumente apare o
adresă (un pointer) spre tipul long.

17:50 PCLP CURS 3 23 17:50 PCLP CURS 3 24

PCLP CURS 3 4
11/9/2016

#include <stdio.h>
scanf - caracterele opționale Programul implementează un
main() calculator rudimentar care
{ adună la suma anterioară
• Caracterele de conversie e, f şi g double suma, v; valoarea reală curent citită.
 pot fi precedate de caracterul opțional l
suma = 0;
 pentru a arăta că în lista de argumente se află while (scanf("%lf", &v) == 1){
suma = suma + v;
 o adresă (un pointer) spre tipul double şi printf("\t%.2f\n", suma);
}
 nu spre tipul float.
}
La întâlnirea sfârşitului de fişier (^Z), se returnează EOF
acesta este diferit de un număr real dublu, deci citirea nu se
mai efectuează și scanf returnează 0 care este diferit de 1,
deci condiția lui while() devine falsă și ciclul se termină.

17:50 PCLP CURS 3 25 17:50 PCLP CURS 3 26

• Dacă dorim să citim linii de intrare care conțin date • Pot apărea diferite caractere (chiar litere) în şirul de
de forma: 25 dec 2016, vom scrie cod astfel: caractere ce conţine formatul din cadrul funcţiei
int zi, an;
scanf;
char luna[20];  acestea trebuie să corespundă acelorași caractere din
datele de intrare.
scanf("%d %s %d", &zi, luna, &an);  Deci am putea citi date de forma zz/ll/aa cu
următoarea instrucţiune scanf:
• Nu se foloseşte operatorul & cu luna,
int zi, luna, an;
 deoarece numele unui tablou este un pointer. scanf("%d/%d/%d“, &zi, &luna, &an);

• Temă: scrieți programul complet pentru secvența de • Temă: Scrieți programul complet pentru secvența de cod de
cod de mai sus care să citească și să afișeze o dată mai sus care să citească și să afișeze o dată calendaristică în
forma precizată (zz/ll/aa).
calendaristică în forma precizată (25 dec 2016).
17:50 PCLP CURS 3 27 17:50 PCLP CURS 3 28

• Funcţia scanf ignoră spaţiile şi tabulatorii din


Ideea cu separatorul / între zi, luna,
#include <stdio.h> an poate fi folosită pentru
şirul ce conţine formatul.
separarea părții întregi de partea
main()
fracționară într-un număr real
• scanf sare peste spaţiile albe când caută datele
{
considerând punctul ca separator. de intrare.
int pi, pf;
printf("Introduceti un numar real cu parte • Apelurile către funcţia scanf pot fi alternate
intreaga si parte fractionara = ");
scanf("%d.%d",&pi,&pf);
 cu apelurile către alte funcţii de citire a datelor de
intrare.
printf("partea intreaga = %d\t partea fractionara
= %d\n", pi, pf); • După un scanf următorul apel către orice funcţie
}
de citire a datelor de intrare
 va începe prin citirea primului caracter necitit de
funcţia scanf.
17:50 PCLP CURS 3 29 17:50 PCLP CURS 3 30

PCLP CURS 3 5
11/9/2016

Observație

• Argumentele funcției scanf trebuie să fie pointeri.


• Cea mai des întâlnită eroare este să se scrie
scanf("%d", n);
 în loc de
scanf("%d“, &n); II. CICLUL for
• Această eroare NU este - în general - depistată la
momentul compilării.
17:50 PCLP CURS 3 31

#include <stdio.h> Să ne reamintim ultima


versiune a programului
Rescriem codul folosind ciclul for
main()
{ de conversie între scara #include <stdio.h>
float fahr, celsius; Fahrenheit și Celsius. /* print Fahrenheit-Celsius table */
float lower, upper, step; main()
{ limita de jos limita de sus pasul
lower = 0;
int fahr;
upper = 300;
for (fahr = 0; fahr <= 300; fahr = fahr + 20)
step = 20;
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
fahr = lower;
}
expresia de conversie
while ( fahr <= upper ) {
Deşi arată diferit, programul produce o afişare similară.
celsius = ( 5.0/9.0 ) * ( fahr - 32.0 );
printf("%3.0f %6.1f\n", fahr, celsius); O modificare majoră este reprezentă de eliminarea
fahr = fahr + step; celor mai multe variabile; singura variabilă care
}
} rămâne este fahr de tip int.
17:50 PCLP CURS 3 33 17:50 PCLP CURS 3 34

• limitele de jos şi de sus şi pasul apar numai sub for (fahr = 0; fahr <= 300; fahr = fahr + 20)
forma unor constante literale în instrucţiunea for,
• implementează tot un ciclu
• expresia de conversie a temperaturii din
• reprezintă o generalizare a instrucţiunii while
Fahrenheit în Celsius apare ca al treilea argument
• comparând-o cu while, din programul echivalent,
în printf.
modul său de execuţie pare mai clar
Această ultimă modificare implementează o regulă • în interiorul parantezelor sunt 3 părţi separate prin
generală care spune că: punct şi virgulă
În orice context în care este permisă utilizarea unei 1. Prima parte, iniţializarea
valori a unui anumit tip de dată, se poate utiliza o fahr = 0
expresie complexă de acel tip de dată. este procesată o singură dată, înainte de intrarea în ciclu.
17:50 PCLP CURS 3 35 17:50 PCLP CURS 3 36

PCLP CURS 3 6
11/9/2016

for (fahr = 0; fahr <= 300; fahr = fahr + 20)


for vs. while
2. Partea a doua este testul sau condiţia care controlează • Ca şi la while, corpul ciclului poate fi
ciclul:
 o singură instrucţiune sau
fahr <= 300
Această condiţie este evaluată; dacă este adevărată este  un grup de instrucţiuni incluse între acolade.
executat corpul ciclului (instrucţiunea printf).
• Iniţializarea, condiţia şi incrementarea pot fi
3. Apoi se execută partea a treia, pasul de incrementare: reprezentate de orice expresie.
fahr = fahr + 20
• Alegerea între while şi for este arbitrară,
şi condiţia (partea a doua) este reevaluată.
• Ciclul se termină dacă condiţia a devenit falsă.
 în funcţie de varianta care ni se pare mai clară.
17:50 PCLP CURS 3 37 17:50 PCLP CURS 3 38

for vs. while for vs. while

• for este de obicei adecvată pentru cicluri în care for(expr1;expr2;expr3)


iniţializarea şi incrementarea sunt instr;
expr1;
 instrucţiuni singulare şi
este echivalent cu: while(expr)
 legate din punct de vedere logic. instr;
while(expr2){
instr; este echivalent cu:
• for este mai compactă decât while şi păstrează
expr3; for(;expr;)
împreună în acelaşi loc instrucţiunile de control
} instr;
ale ciclului.
17:50 PCLP CURS 3 39 17:50 PCLP CURS 3 40

Constante simbolice
• Nu se recomandă utilizarea de constante literale:
 300 (pentru valoarea finală a temperaturii) şi
 20 (pentru pas);
ele vor transmite puţină informaţie cuiva care va citi
ulterior programul şi în plus
este greu să le modificăm într-un mod sistematic,
III. CONSTANTE SIMBOLICE dacă dorim alte limite finale şi alţi paşi.

• O soluţie de a lucra cu constante literale este de a


le atribui nume semnificative.
17:50 PCLP CURS 3 42

PCLP CURS 3 7
11/9/2016

Constante simbolice #define nume text_înlocuire


• O linie de program #define defineşte
• nume are aceiaşi formă ca un nume de variabilă:
 nume simbolice sau
 constante simbolice:  o secvenţă de litere şi cifre care începe cu o literă.

#define nume text_înlocuire • text_înlocuire poate fi


• După această definire, orice apariţie a lui nume  orice secvenţă de caractere;
 care nu apare între ghilimele,  nu este limitată doar la numere.
 sau ca parte al unui alt nume
• va fi substituită corespunzător cu text_înlocuire.
17:50 PCLP CURS 3 43 17:50 PCLP CURS 3 44

Rescriem programul înlocuind constantele Constante simbolice vs. Variabile


literale 0, 300 şi 20 cu constante simbolice
#include <stdio.h> • Cantităţile LOWER, UPPER şi STEP
#define LOWER 0 /* lower limit of table */
 sunt constante simbolice,
#define UPPER 300 /* upper limit */
#define STEP 20 /* step size */  nu sunt variabile,
/* print Fahrenheit-Celsius table */  nu apar în declaraţii.
main()
{ • Convenţie:
int fahr;
 numele constantelor simbolice se scriu cu MAJUSCULE
for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)  numele variabilelor se scriu cu minuscule.
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
} • Nu există punct şi virgulă la finalul unei linii #define.
17:50 PCLP CURS 3 45 17:50 PCLP CURS 3 46

Citirea şi scrierea caracterelor

• Modelul citirii (intrării) şi scrierii (ieşirii) suportat


de biblioteca standard este foarte simplu:

 Citirile (intrările) sau scrierile (ieşirile) textelor,


indiferent de unde provin sau unde sunt trimise,
IV. CITIREA ŞI SCRIEREA sunt tratate ca fluxuri de caractere.
CARACTERELOR
 Un flux de text (text stream) este o secvenţă de
caractere separate în linii.
17:50 PCLP CURS 3 48

PCLP CURS 3 8
11/9/2016

Citirea şi scrierea caracterelor getchar şi putchar


• Fiecare linie constă din
• Biblioteca standard furnizează câteva funcţii pentru
 zero sau mai multe caractere urmate citirea sau scrierea unui caracter odată. Cele mai
 de un caracter linie nouă (newline character: <LF> line simple sunt:
feed) : ’\n’(cod ASCII 10)  getchar şi
• Cade în responsabilitatea bibliotecii să aibă grijă ca  putchar.
fiecare flux de intrare sau de ieşire să se conformeze • De fiecare dată când este apelată getchar citeşte
acestui model. următorul caracter de intrare dintr-un flux de text şi îl
returnează ca valoare a sa. Adică după
c = getchar();
 variabila c conţine următorul caracter al intrării.
• Uzual caracterele intrării provin de la tastatură.
17:50 PCLP CURS 3 49 17:50 PCLP CURS 3 50

getchar şi putchar
• Funcţia putchar afişează (scrie) un caracter de
fiecare dată când este apelată:
putchar(c);
 scrie variabila întreagă c ca un caracter,
 de obicei pe ecran.
IV.1 COPIEREA FIŞIERELOR
• Apelurile de putchar şi printf pot fi intercalate;
 ieșirea se va genera în ordinea în care s-au făcut
apelurile.
17:50 PCLP CURS 3 51

IV.1 Copierea fişierelor #include <stdio.h>

• Cu getchar şi putchar, se poate scrie /* copy input to output; 1st version */


main()
surprinzător de mult cod util fără să ştii nimic mai citire cu getchar()
{ afisare cu putchar()
mult despre intrări şi ieşiri. int c; citire cu getchar()
afisare cu putchar()
• Cel mai simplu exemplu este un program care
copiază intrarea sa la ieşirea sa caracter cu c = getchar();
caracter: while (c != EOF) {
Citeşte un caracter putchar(c);
Cât timp (caracterul nu este indicatorul de sfârşit de fişier) c = getchar();
Scrie caracterul tocmai citit } Se generează la finalul introducerii

Citeşte un caracter } caracterelor tastând Ctrl+Z:(^Z)

17:50 PCLP CURS 3 53 17:50 PCLP CURS 3 54

PCLP CURS 3 9
11/9/2016

• operatorul relaţional != înseamnă „diferit de”.


EOF: end of file
• ceea ce apare ca un caracter pe tastatură (sau pe
ecran) este stocat intern ca o secvenţă de biţi (bit • Problema este să distingem între finalizarea
pattern). Ex.: ’A’ se stochează intern: 01000001 introducerii şi datele valide.
 tipul de date char este indicat pentru a memora • Soluţia este dată de faptul că getchar returnează
astfel de date caracter,  o valoare distinctă când nu mai există intrări,
 dar putem utiliza pentru memorarea lor orice tip  o valoare care nu poate fi confundată cu niciun
întreg de date. caracter efectiv.
 Am utilizat tipul int pentru un motiv subtil şi • ea se numeşte EOF (end of file, sfârşit de fişier).
important.
17:50 PCLP CURS 3 55 17:50 PCLP CURS 3 56

EOF: end of file EOF: end of file


• Trebuie să declarăm variabila c de un tip de dată
suficient de mare pentru a memora orice valoare • EOF este o constantă simbolică întreagă definită în
pe care o poate returna getchar. <stdio.h>.

• Nu putem utiliza char deoarece c • utilizând constante simbolice (EOF) ne-am


asigurat că nimic în program nu depinde de valori
 trebuie să fie suficient de mare pentru a memora
numerice specifice
EOF,
 în afară de orice posibil char.  inserarea caracterului EOF, la finalizarea
introducerii caracterelor se face cu combinaţia de
• Prin urmare am utilizat int. taste ^Z.
17:50 PCLP CURS 3 57 17:50 PCLP CURS 3 58

main()
Valoarea expresiei de atribuire {
int c;
c = getchar();
• Putem rafina programul ţinând cont că în C orice while (c != EOF) {
putchar(c);
atribuire, cum ar fi şi: #include <stdio.h> }
c = getchar();

}
c = getchar(); /* copy input to output; 2nd version */
main()
• este o expresie şi {
int c;
• are o valoare,
while ( (c = getchar()) != EOF)
 care este valoarea din partea stângă a
putchar(c);
operatorului de atribuire după finalizarea }
instrucţiunii de atribuire.
17:50 PCLP CURS 3 59 17:50 PCLP CURS 3 60

PCLP CURS 3 10
11/9/2016

• Instrucţiunea while primeşte un caracter, Prioritatea operatorilor != şi =


 îl atribuie lui c, şi apoi
 testează dacă caracterul a fost semnalul de sfârşit • Parantezele din jurul atribuirii
de fişier.
(c = getchar()) != EOF
Dacă nu a fost, este executat corpul ciclului while
din condiţie sunt necesare.
afişând caracterul.
• Prioritatea operatorului != este mai mare decât a
• Apoi while se repetă. operatorului =.
• Când sfârşitul de fişier (EOF) este atins, while se • Adică în absenţa parantezelor testul relaţional !=
termină şi la fel main. s-ar executa înaintea atribuirii =.
17:50 PCLP CURS 3 61 17:50 PCLP CURS 3 62

• Astfel instrucţiunea:

c = getchar() != EOF
!= generează
este echivalentă cu: 0 (fals) sau
1 (adevărat)

c = (getchar() != EOF)

• Aceasta produce efectul nedorit de a atribui lui c


IV.2 NUMĂRAREA CARACTERELOR
valoarea 0 sau valoarea 1,
 după cum apelul lui getchar întâlneşte sau nu
sfârşitul de fişier.
17:50 PCLP CURS 3 63

IV.2 Numărarea caracterelor Instrucţiunea ++nc;


#include <stdio.h>

/* count characters in input; 1st version */


• operatorul ++, înseamnă incrementare cu unu
main()
{   • în locul lui ++nc se putea scrie şi
long nc;
nc = 0; nc = nc + 1
while ( getchar() != EOF )
++nc; /* nc = nc + 1 */
La rulare se introduc câteva
caractere, se dă <Enter>
• expresia ++nc este mai concisă şi mai eficientă
apoi ^Z. <Enter> este un
printf("%ld\n", nc);
}
caracter care se numără.
• există şi operatorul –– pentru decrementarea cu 1
17:50 PCLP CURS 3 65 17:50 PCLP CURS 3 66

PCLP CURS 3 11
11/9/2016

Instrucţiunea ++nc; • Programul stochează numărul de caractere


numărate într-o variabilă de tip de date long în
loc de int.
• operatorii ++ şi –- pot fi operatori
 prefixaţi(++nc) • Întregii de tip long au cel puţin 32 de biţi.
 postfixaţi (nc++) • Deşi pe unele maşini, int şi long au aceiaşi
mărime,
• cele două forme (prefixată şi postfixată) au valori
 pe altele un int are numai 16 biţi, cu o valoare
diferite în expresii
maximă de 32767, şi
 această valoare s-ar putea depăşi uşor de un
• dar atât ++nc, cât şi nc++ incrementează pe nc.
contor de tip int.
17:50 PCLP CURS 3 67 17:50 PCLP CURS 3 68

for în loc de while


• Specificatorul de format %ld spune instrucţiunii #include <stdio.h>
printf că /* count characters in input; 2nd version */
 argumentul la care se referă (nc) este de tipul main() La rulare se introduc câteva caractere, 
long. { se dă <Enter> apoi ^Z. <Enter>
este un caracter care se numără.
double nc;
• Pentru a gestiona situaţii în care contorul trebuie
să ia valori mai mari, for (nc = 0; getchar() != EOF; ++nc)
; ; corpul ciclului for
 putem utiliza pentru nc tipul double (i.e. real
dublă precizie). printf("%.0f\n", nc);
}
17:50 PCLP CURS 3 69 17:50 PCLP CURS 3 70

Observație Corpul ciclului for: nu conține nimic


• Procesările sunt făcute în partea de test şi de
• printf utilizează specificatorul de format %f incrementare ale instrucţiunii for.
 atât pentru float cât şi pentru double; • Regulile de gramatică ale limbajului C cer ca o
instrucţiune for să aibă un corp.
• %.0f elimină afişarea • Semnul punct şi virgulă
 punctului zecimal şi a  numit instrucţiune nulă: null statement
este plasat acolo pentru a satisface această regulă a
 părţii fracţionare, gramaticii C.
care oricum este zero.  Semnul ; este pus pe o linie separată pentru a-l face
mai vizibil.
17:50 PCLP CURS 3 71 17:50 PCLP CURS 3 72

PCLP CURS 3 12
11/9/2016

Caz limită: niciun caracter pe intrare


• În cazul limită în care pe intrare nu avem nici un
caracter
 testul din while sau din for este fals de la primul
apel a lui getchar,

• iar programul afişează zero: răspunsul corect.


IV.3. NUMĂRAREA LINIILOR
• Unul dintre avantajele lui while şi for este că ele
au testul plasat la începutul ciclului,
 înainte de a se intra în corpul ciclului.
17:50 PCLP CURS 3 73

IV.3. Numărarea liniilor while şi if


Numărarea liniilor se reduce la
#include <stdio.h> numărarea caracterelor newline (’\n’).
/* count lines in input */
• Corpul ciclului while constă dintr-un if care, la
main()
La rulare după introducerea fiecărei linii


rândul lui,
{ de caractere se dă <Enter>, la final, 
int c, nl; pentru închiderea fișierului, se dă ^Z.
 controlează incrementarea ++nl.
nl = 0;
• În general, instrucţiunea if testează condiţia pusă
while ((c = getchar()) != EOF)
if (c == '\n')
între paranteze (în cazul nostru c == '\n')
++nl;
 şi dacă condiţia este adevărată,
printf("%d\n", nl);  se execută instrucţiunea (sau grupul de instrucţiuni
} plasate între acolade) care urmează.
17:50 PCLP CURS 3 75 17:50 PCLP CURS 3 76

Operatorul == Constante caracter


• Un caracter scris între apostrofuri ('\n')
reprezintă o valoare întreagă (10 în codul ASCII),
• == este operatorul C pentru “este egal cu”.  egală cu valoarea numerică a caracterului din setul
de caractere al maşinii.

• Simbolul == este utilizat pentru a distinge între: Acesta se numeşte constantă caracter şi este un alt
mod de a scrie un număr întreg mic.
 testul de egalitate (==) şi
• Pentru setul de caractere ASCII
 operatorul de atribuire (=). ’a’ reprezintă valoarea întreagă 97 ’b’ este 98 ’A’ este 65
 97, 98 şi 65 sunt reprezentările interne ale
caracterelor ’a’, ’b’ respectiv, ’A’.
17:50 PCLP CURS 3 77 17:50 PCLP CURS 3 78

PCLP CURS 3 13
11/9/2016

Secvenţele escape Ce afișează programele următoare?


• utilizate în constantele şir de caractere sunt şi ele
constante caracter. #include <stdio.h> #include <stdio.h>
main() main()
• '\n' reprezintă valoarea caracterului line nouă, { {
printf("%d", '\n'); printf("%c", '\n');
care are valoarea 10 în codul ASCII. } }
'\t' reprezintă caracterul
• '\n' : tab orizontal care are
valoarea 9 în codul ASCII.
 este un singur caracter o linie vidă
10
(i.e. caracterul newline)
 în expresii este un număr întreg cu valoarea 10.
17:50 PCLP CURS 3 79 17:50 PCLP CURS 3 80

#include <stdio.h> /* count lines, words, and characters in input */


#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
Programul numără liniile (nl),
main() cuvintele (nw) şi caracterele
{ (nc) introduse.
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0; Prin cuvânt
înţelegem o
while ((c = getchar()) != EOF) { secvenţă de
++nc; caractere care
if (c == '\n') nu conţine
++nl; blank-uri (' '),
if (c == ' ' || c == '\t' || c == '\n') tab-uri ('\t')
state = OUT; A fost întâlnit primul sau caractere
else if (state == OUT) { caracter al unui cuvânt
IV.4 NUMĂRAREA CUVINTELOR state = IN;
newline ('\n').

++nw; 
} 
} 

printf("%d %d %d\n", nl, nw, nc);


}

17:50 PCLP CURS 3 82

• De fiecare dată când programul întâlneşte primul


caracter al unui cuvânt, el incrementează contorul
nl = nw = nc = 0;
numărului de cuvinte (++nw;).
• Linia pune pe zero toate cele trei variabile nl, nw
• Variabila state înregistrează dacă programul este, şi nc.
sau nu este, în acel moment, în interiorul unui
cuvânt. • Este consecinţa faptului că o atribuire este o
expresie
• Iniţial, programul nu este în interiorul unui cuvânt şi
 cu valoarea şi atribuirile asociate de la dreapta la
 variabila state este iniţializată cu valoarea OUT. stânga.
• Preferăm constantele simbolice IN şi OUT
• Este ca şi cum am fi scris:
constantelor literale 1 şi 0
 deoarece ele fac mai lizibil programul. nl = (nw = (nc = 0));
17:50 PCLP CURS 3 83 17:50 PCLP CURS 3 84

PCLP CURS 3 14
11/9/2016

Operatorul SAU logic: || Operatorul SAU logic: ||


if (c == ' ' || c == '\t' || c == '\n')
if (c == ' ' || c == '\t' || c == '\n') • Expresiile conectate prin && sau || sunt evaluate
Adică: dacă c este un blank sau c este un newline de la stânga la dreapta şi
sau c este un tab.  se garantează că evaluarea expresiilor se opreşte
atunci când adevărul sau falsul expresiei este
cunoscut.
• Similar && este operatorul pentru ŞI logic.
 Dacă c este blank (c == ' '), nu mai este nevoie
 Prioritatea && este mai mare decât a ||.
să mai testăm în continuare dacă nu cumva este tab
sau newline,
aşa că următoarele teste (c == '\t‘ și c == '\n')
nu mai sunt evaluate.
17:50 PCLP CURS 3 85 17:50 PCLP CURS 3 86

Forma generală a instrucţiunii if :


• else specifică o acţiune alternativă dacă
condiţia instrucţiunii if este falsă. if (expresie)
• Una şi numai una dintre cele două instrucţiune1
instrucţiuni asociate cu un if-else else
este efectuată. instrucţiune2
 dacă expresie este adevărată atunci
este executată instrucţiune1;
V. TABLOURI
 dacă nu, este executată instrucţiune2.
• Fiecare instrucţiune1/2 poate fi o instrucțiune singură
sau mai multe instrucţiuni incluse între acolade.
17:50 PCLP CURS 3 87

Afișarea unui tablou (array)


unidimensional: vector
v[0] v[1] v[2] v[3] v[4] v[5] v[6]
#include <stdio.h> 4.2 0 -2.2 0.50 12.0 0.33 3.40
main()
{
float v[7] = {4.2, 0, -2.2, 0.50, 12.0, 0.33, 3.40}; Aplicaţie
int i, n = 7;
NUMĂRAREA APARIŢIILOR FIECĂREI
for (i = 0; i < n; i++)
printf("v[%d] = %g\n", i, v[i]); CIFRE, A CARACTERELOR ALBE ŞI A
} TUTUROR CELORLALTE CARACTERE
17:50 PCLP CURS 3 89

PCLP CURS 3 15
11/9/2016

Programul numără apariţiile: #include <stdio.h> /* count digits, white space, others */
main() 
{
1. fiecărei cifre (0, 1, 2, … , 9) int c, i, nwhite, nother;
int ndigit[10];
2. a caracterelor spaţii albe (blank, tab, LF) şi nwhite = nother = 0;
for (i = 0; i < 10; ++i)
3. a tuturor celorlalte caractere. ndigit[i] = 0;
while ((c = getchar()) != EOF)
• Sunt 12 categorii de intrări: if (c >= '0' && c <= '9')
++ndigit[c-'0'];
 utilizăm un tablou (array) unidimensional care să else if (c == ' ' || c == '\t' || c == '\n')
++nwhite;
memoreze numărul de apariţii ale fiecărei cifre else
(ndigit[10]) și ++nother;

 două variabile simple (nwhite, nother) care să printf(" digits =");


for (i = 0; i < 10; ++i)
 memoreze numărul de apariții a caracterelor albe, printf(" %d", ndigit[i]);
printf("\n white space = %d \n other = %d\n",nwhite, nother);
 respectiv numărul de apariții a celorlalte caractere. }

17:50 PCLP CURS 3 91 17:50 PCLP CURS 3 92

• Contorizăm 12 categorii de intrări: Declaraţia: int ndigit[10];


1. fiecare din cele 10 cifre (0..9) cu 10 contoare: • Declară ndigit ca un tablou de 10 întregi.
ndigit[0], …, ndigit[9] • În C indicii tablourilor pornesc de la 0, astfel că elementele sunt:
1. caracterele spaţii albe (blank, tab, LF) cu 1 contor: nwhite  ndigit[0], ndigit[1], ..., ndigit[9].

2. toate celelalte caractere cu 1 contor: nother


• Acest lucru se vede clar în cele două cicluri for care
 iniţializează:
• Utilizăm un tablou: ndigit[10], care
for (i = 0; i < 10; ++i)
memorează numărul de apariţii ale fiecărei cifre:
ndigit[i] = 0;
 ndigit[0] memorează numărul de apariţii ale cifrei 0
 şi afişează tabloul:
… for (i = 0; i < 10; ++i)
 ndigit[9] memorează numărul de apariţii ale cifrei 9 printf(" %d", ndigit[i]);
17:50 PCLP CURS 3 93 17:50 PCLP CURS 3 94

Întrebare Indicele unui tablou


• Indicele unui tablou poate fi orice expresie întreagă
De ce inițializarea elementelor tabloului ndigit[]
 aici incluzându-se
care memorează frecvențele de apariție a fiecărei
 variabile întregi ca i şi
cifre se face cu 0 ?
 constante întregi.
for (i = 0; i < 10; ++i)
 Exemple:
ndigit[i] = 0;  ndigit[i]
 ndigit[7]
0 este elementul neutru la adunare.  ndigit[c - '0'],
 unde int c; este un caracter din codul ASCII.
17:50 PCLP CURS 3 95 17:50 PCLP CURS 3 96

PCLP CURS 3 16
11/9/2016

c-'0' Testul if (c >= '0' && c <= '9')


• c un caracter din codul ASCII are valori între 0…255.
• Determină dacă caracterul memorat de variabila c este o cifră
• Dacă c este un caracter cifră el va avea valori între:
 48 (codul ASCII al lui ’0’) şi • Dacă este cifră, valoarea numerică a acestei cifre este:
c - '0‘
 57 (codul ASCII al lui ’9’)
• Prin definiţie tipul char conţine întregi mici, astfel că
• Dacă scădem din valoarea lui c, valoarea 48, a  variabilele şi constantele de tip char sunt identice cu cele
caracterului ’0’, obţinem exact valoarea numerică de tip int în expresiile aritmetice.
corespunzătoare caracterului cifră c.
• De exemplu, c-'0' este o expresie întreagă cu o valoare
• Exemplu: dacă c este ‘7’ el va avea codul 55, dacă din între 0..9 corespunzând caracterului dintre '0' şi '9' stocat
55 scădem codul ASCII al lui ’0’ (i.e. 48) obţinem 7. în c şi astfel este un indice valid pentru tabloul ndigit.
17:50 PCLP CURS 3 97 17:50 PCLP CURS 3 98

Decizia asupra faptului că un caracter else if


este cifră, spaţiu alb sau altceva if (condiţie1)
instrucţiune1
• Modelul din stânga apare frecvent în
programe ca o modalitate de a exprima
else if (condiţie2) o decizie cu mai multe variante.
if (c >= '0' && c <= '9') instrucţiune2
... • condiţiile sunt evaluate în ordine de sus
++ndigit[c-'0']; ... până o anumită condiţie este
else satisfăcută;
else if (c == ' ' || c == '\n' || c == '\t') instrucţiunen • în acel moment partea de instrucţiune
++nwhite; • Dacă nicio condiţie nu corespunzătoare este executată şi
este satisfăcută, este întreaga construcţie este terminată.
else executată instrucţiunea • Orice instrucţiune poate fi reprezentată
++nother; de după ultimul else, şi de mai multe instrucţiuni incluse
în caz că există. între acolade.
17:50 PCLP CURS 3 99 17:50 PCLP CURS 3 100

• Dacă ultimul else şi instrucţiunea


if (condiţie1)
de după el nu există, nu se face
Instrucţiunea switch
instrucţiune1
else if (condiţie2) nimic. • care va fi discutată ulterior, furnizează un alt mod
instrucţiune2
...
• Pot fi oricâte grupuri de de a scrie o structură decizională cu multe
... else if(condiţie) ramificaţii,
else instrucţiune
instrucţiunen • dar ea este în special adecvată când condiţia caută
între if-ul iniţial şi else-ul final.
 potrivirea unei expresii întregi sau caracter într-un
• Se recomandă respectarea stilului de scriere a construcţiei set de constante.
cum s-a arătat mai sus;
• Altfel dacă fiecare if ar fi fost indentat spre dreapta în
• O versiune cu switch a programului anterior
raport cu else-ul anterior, secvenţa de decizii s-ar fi întins  va fi prezentată când se va discuta instrucţiunea
mult spre marginea din dreapta a paginii. switch.
17:50 PCLP CURS 3 101 17:50 PCLP CURS 3 102

PCLP CURS 3 17
11/9/2016

VI. APLICAȚII CU NUMERE CIFRELE UNUI NUMĂR

Cifrele unui număr Cifrele unui număr


• Pentru determinarea cifrelor unui număr (asupra • Dacă dorim cifrele reprezentării în baza 10 a
cărora se pot executa diverse operații) se folosesc numărului întreg:
operatorii:
 %10 extrage ultima cifră a numărului
 %b pentru extragerea ultimei cifre a numărului
(întreg) din reprezentarea lui în baza b  /10 elimină ultima cifră a numărului
 /b pentru eliminarea ultimei cifre a numărului
(întreg) din reprezentarea lui în baza b
 asigurând astfel accesul la următoarea cifră (de la
dreapta la stânga) din număr.
17:50 PCLP CURS 3 105 17:50 PCLP CURS 3 106

#include <stdio.h>
Cifrele unui număr natural nenul main() /*cifrele unui numar */
{
întreg n, c Se citește un număr n int n, c;
citește n natural nenul. Să se
printf("numarul este = "); scanf("%d", &n);
afișeze cifrele sale
cât timp (n > 0) execută începând cu cifra cea while (n > 0) {
c <- n % 10 mai puțin c = n % 10;
semnificativă (cifra printf("cifra = %d\n", c);
scrie c n = n / 10;
unităților).
n <- n / 10 Exemplu: n = 9301
}
TEMĂ: Se citește n număr natural nenul. Afișați cifrele sale pare începând
}
sfârșit cât timp => 1 0 3 9 cu cifra cea mai puțin semnificativă. Ex: n = 2518 => 8 2.
Indicație: instrucțiunea printf("cifra = %d\n", c); se va înlocui
cu if (c%2 == 0) printf("cifra = %d\n", c);
Același enunț, dar să se afișeze cifrele impare. Ex: n = 2518 => 1 5

17:50 PCLP CURS 3 107 17:50 PCLP CURS 3 108

PCLP CURS 3 18
11/9/2016

#include <stdio.h>
Suma cifrelor unui număr
main() /* suma cifrelor unui numar natural */
{
întreg n, s, c Se citește un număr int n, s, c;
citeşte n n natural. Să se printf("numarul este = "); scanf("%d", &n);
s <- 0 afișeze suma cifrelor
s = 0;
cât timp (n > 0) execută sale.
Exemplu: n = 9201 while (n > 0) {
c <- n % 10 => s = 12 c = n % 10;
s <- s + c (1+0+2+9) s = s + c;
TEMĂ: Se citește un număr n natural. Să
n <- n / 10 n = n / 10; se afișeze produsul cifrelor sale. Exemplu:
sfârşit cât timp } n = 5231 => p = 30(5*2*3*1)

scrie s printf(" suma cifrelor = %d\n", s);


}
17:50 PCLP CURS 3 109 17:50 PCLP CURS 3 110

#include <stdio.h>
Cifra maximă a unui număr natural main()
întreg n, max, c {/* cifra maxima a unui numar natural */
int n, max, c, temp;
citeşte n Aflați cifra maximă a unui
max <- 0 număr n natural dat. printf("numarul este = "); scanf("%d", &n);
temp = n;
cât timp (n  0) execută Exemplu: n = 3901 =>
max = 9 max = 0;
c <- n % 10 while ( temp != 0 ) { De ce folosim - în plus - variabila temp ?
dacă (max < c) atunci c = temp % 10;
if ( max < c )
max <- c TEMĂ: Aflați cifra minimă a unui
max = c;
sfârşit dacă temp = temp / 10; număr n natural dat.
Exemplu: n = 3937 => min = 3
n <- n / 10 }
sfârşit cât timp De ce iniţializăm max cu 0 ? printf("cifra maxima din %d este = %d\n", n, max);
scrie max }
17:50 PCLP CURS 3 111 17:50 PCLP CURS 3 112

#include <stdio.h>
Cifra minimă și maximă a unui număr main() /* cifra minimă si maxima a unui numar natural */
{
int n, cif_max = 0, cif_min = 9, c, max;
Se dă un număr natural n de minim două cifre. Să
printf("n = ");scanf("%d",&n);
se determine cel mai mare număr format din cifra while( n != 0 ){
minimă şi cea maximă a acestuia. c = n % 10;
if(c > cif_max)
TEMĂ: Se dă un număr natural n de
cif_max = c;
minim două cifre. Să se determine cel
if(c < cif_min) mai mic număr format din cifra minimă
Exemplu: n = 2725 => maxim = 72 cif_min = c; şi cea maximă a acestuia.
n = n /10; Exemplu: n = 3931 => minim = 19
(cifra maximă = 7, cifra minimă = 2) }
max = cif_max * 10 + cif_min;
TEMĂ: Redactați algoritmul
în limbajul pseudocod. printf("maxim = %d \n", max);
}
17:50 PCLP CURS 3 113 17:50 PCLP CURS 3 114

PCLP CURS 3 19
11/9/2016

Formarea unui număr din cifrele sale Formarea unui număr din cifrele sale
intreg c, n, x, i
• Pentru a forma un număr din cifrele sale Se citesc pe intrare cele n x <- 0
citeşte n
componente se înmulțește fiecare cifră cu baza în (n  0, natural) cifre ale pentru i <- 1, n execută
care este scris numărul la puterea reprezentată de unui număr de la cifra cea citeşte c
poziţia cifrei. mai semnificativă până la x <- x * 10 + c
sfârşit pentru
 Cifra cea mai puțin semnificativă se înmulțește cu cifra cea mai puţin scrie x
baza la puterea zero ş.a.m.d. semnificativă.
Formaţi numărul din
725(10) =
cifrele sale şi afişaţi-l.
7*102 + 2*101 + 5*100 = 7*100 + 2*10 + 7*1 = 700 + 20 + 5

17:50 PCLP CURS 3 115 17:50 PCLP CURS 3 116

#include <stdio.h> /* formarea unui număr din cifrele sale */


TEMĂ 2: Rescrieți programul cu TEMĂ 3: Rescrieți programul
main() while() eliminând variabila i. anterior cu while() fără variabila
{ i, înlocuind while() cu for().
int c, n, x, i; Indicație: Indicație:
În loc de: În loc de:
x = 0;
i = 1; while ( n-- ){
printf("Cate cifre are numarul? = "); while ( i <= n ){ printf("cifra = ");
scanf("%d", &n); TEMĂ 1: Același enunț, dar scrieți o ... scanf("%d", &c);
implementare echivalentă a
++i; x = x * 10 + c;
for ( i = 1; i <= n; ++i ){ algoritmului în limbajul C folosind
instrucțiunea while() în loc de
} }
printf("cifra %d este = ", i); for(). Se va scrie: Se va scrie:
scanf("%d", &c); Indicație: în loc de: for(i=1; while ( n-- ){ for ( ; n--; ){
i<=n; ++i){...}. Se va scrie:
x = x * 10 + c; printf("cifra = "); printf("cifra = ");
i=1; while(i<=n){... ++i;}
} scanf("%d", &c); scanf("%d", &c);
x = x * 10 + c; x = x * 10 + c;
printf("numarul format din cifrele sale este = %d\n", x); } }
}

17:50 PCLP CURS 3 117 17:50 PCLP CURS 3 118

Inversul unui număr Palindrom


Se citeşte un număr întreg Se citeşte un număr întreg n. Să se verifice dacă
n. Să se afişeze numărul
numărul este palindrom (i.e. este egal cu inversul
intreg n, invers inversat (oglindit).
citeste n Exemplu: n = 174 => său).
invers <- 0 471
Exemple:
cât timp n  0 execută
invers <- invers * 10 + n % 10 n = 174 => nu este palindrom
n <- n / 10
sfârşit cât timp
n = 17471 => palindrom
Temă. Scrieţi programul C
scrie invers corespunzător TEMĂ: Redactați algoritmul
pseudocodului prezentat.
în limbajul pseudocod.

17:50 PCLP CURS 3 119 17:50 PCLP CURS 3 120

PCLP CURS 3 20
11/9/2016

#include <stdio.h> /* verificare palindrom */


main() Bibliografie
{
int n, invers = 0, temp;
printf("Introduceti nr ce trebuie verificat ca e sau nu palindrom\n");
scanf("%d",&n); [1] Kernighan, B., Ritchie, D., The C Programming
temp = n; Language, ediția a II-a, Ed. Prentice Hall, 1988.
while ( temp != 0 ) {
invers = invers * 10 + temp%10;
temp = temp / 10;
} De ce folosim - în plus - variabila temp ?
if ( n == invers )
printf("%d este palindrom\n", n);
else
printf("%d nu este palindrom\n", n);
}
17:50 PCLP CURS 3 121 17:50 PCLP CURS 3 122

PCLP CURS 3 21

S-ar putea să vă placă și