Limbajul de programare C / C++
Limbajul C - creat in 1972 la Bell Laboratories , avand ca obiectiv principal dezvoltarea unui limbaj care sa fie utilizat pentru implementarea sistemului de operare UNIX.
Caracteristici:
- produce programe eficiente
- portabil
- set puternic de operatori
- flexibilitate in programare
- ofera facilitati specifice limbajelor de asamblare
- limbaj de programare structurat
Limbajul C++ - extensie a limbajului C -permite programarea orientata spre obiecte (obiectuala)
Obiect - entitate ce cuprinde datele
procedurile ce opereaza cu ele
programele sunt create ca o colectie de obiecte ce
interactioneaza, in loc de liste de instructiuni sau apeluri de proceduri.
Structura programelor C++
Program C++ contine una sau mai multe functii.
Functie - sectiune de program construita folosind: declaratii de variabile
instructiuni de prelucrare
poate intoarce un rezultat sau nu.
de tip intreg, real, etc tip void
main( )-functia radacina, este prezenta in orice program C si executia programului incepe automat cu ea. Ea poate intoarce un rezultat intreg (int) sau nici un rezultat (void).
Programul este corect, desi nu executa nimic. Pornind
de la el, scriem orice program, adaugand instructiuni intre cele doua
acolade (corpul functiei). Cele doua paranteze rotunde () se ataseaza
oricarei functii. Intre ele se scriu optional anumiti parametrii.
Cel
mai simplu program C++ :
void main()
Obs:
Este permis ca tipul functiei sa lipseasca:
main( )
In acest caz se presupune ca functia intoarce un rezultat intreg si la compilare, deoarece ea nu intoarce nici un rezultat, se va primi un avertisment.
In exemplul urmator:
Main( )
programul va da eroare de sintaxa deoarece limbajul face distinctie intre litere mari si mici.
Urmatoarele exemple sunt corecte si identice (nu are importanta nici plasarea cuvintelor pe linie, nici spatiile dintre ele):
main( )
main ( )
main
Vocabularul limbajului C++
Setul de caractere - ansamblul de caractere cu ajutorul carora se poate realiza un program C++. Acestea sunt:
. litere mici si mari ale alfabetului englez (A - Z, a - z )
. cifrele sistemului de numeratie in baza 10 ( 0 - 9)
. caractere speciale ' # % & ' ( ) * + , - . / : ; _ < = > ? [ ] ^ | ~ @ blank (spatiu)
Identificatori si cuvinte cheie (rezervate) - o succesiune de litere, cifre sau caracterul underscore ( ) cu restrictia ca primul caracter sa nu fie cifra. Cu ajutorul lor se asociaza nume constantelor, variabilelor, functiilor, etc.
Exemplu: i, j1, un_numar, _id Contraexemplu: a#b, 1ab, xy&, -plus
Separatori si comentarii
( )
Citirea datelor de la tastatura si afisarea lor pe ecran
In C++, pentru a efectua afisari pe ecran si citiri de la tastatura, inaintea functiei main, trebuie inclus fisierul antet <iostream.h> prin directiva:
#include<iostream.h>
se solicita ca programul sa includa provine de la: i - input
un fisier antet (header) numit iostream, o - output
cu informatii referitoare la scrieri/citiri. stream - flux de date
.h - fisierele antet au prin conventie extensia .h
Obs:
Dupa editarea fisierului sursa, pentru a obtine un program executabil trebuie parcurse etapele:
editare fisier sursa ----- ----- ------------> fisier
obiect ----- ----- ----- ----- ----> fisier executabil
.CPP
compilare .OBJ linkeditare .EXE
In procesul de compilare se verifica corectitudinea lexicala si sintactica a programului (daca exista erori de sintaxa, acestea se semnaleaza).
realizeaza legatura fisierului obiect cu alte fisiere sau cu bibliotecile de functii. |
Pentru a realiza citirile folosim cin>> . Forma generala este:
cin>>a1>>a2>>>>an;
unde a1, a2, .., an sunt variabile de un tip oarecare.
Pentru realizarea scrierii se utilizeaza: cout<< . Forma generala este:
cout<<a1<<a2<<<<an;
unde a1, a2, .., an sunt variabile sau constante
Obs: cin console input
cout console output.
Ex nr.1:
#include<iostream.h>
/* functia main este functia
principala, cu care
incepe executarea programului */
void
main( )
//
sfarsitul functiei main
Ex nr.2 (Program care citeste un numar intreg si-l tipareste) :
#include <iostream.h>
void main()
Tipuri de date
Orice variabila, inainte de a fi utilizata, trebuie declarata prin precizarea tipului ei.
tip de date o multime de valori pe care sunt definite anumite operatii.
O declaratie de variabile are formatul:
tip lista_de_nume ;
unde lista_de_nume se compune din unul sau mai multe nume de variabile separate prin virgula.
Limbajul C++ contine urmatoarele tipuri standard (cunoscute de catre limbaj fara a fi definite in cadrul programului):
Tipuri intregi:
1. unsigned char - caracter fara semn - ocupa 8 biti si ia valori intre 0 si 28 - 1
2. char -caracter - ocupa 8 biti si ia valori intre -27 si 27 - 1
3. unsigned int - intreg fara semn - ocupa 16 biti si ia valori intre 0 si 216 - 1
4. int - intreg scurt - ocupa 16 biti si ia valori intre -215 si 215 - 1
5. unsigned long - intreg lung fara semn - ocupa 32 de biti si ia valori intre 0 si 232 - 1
6. long - intreg lung cu semn - ocupa 32 de biti si ia valori intre - 231 si 231 - 1
Tipuri reale:
Variabilele de tip real retin numere cu zecimale. In locul virgulei, in C++ se foloseste punctul.
1. float - ocupa 32 de biti si ia valori intre 3.4 x 10-38 si 3.4 x 1038
2. double - ocupa 64 de biti si ia valori intre 1.7 x 10-308 si 1.7 x 10308
3. long double - ocupa 80 de biti si ia valori intre 3.4 x 10-4932 si 1.1 x 104932
Exemple de declaratii de variabile:
char a, b=25, c='x';
int d=21, e;
float f ;
Obs
la tiparirea unei variabile de tip caracter se tipareste caracterul si nu codul sau, desi la atribuire se poate atasa fie codul caracterului, fie caracterul.
Ex: in urma executiei secventei de mai jos, se va tipari de doua ori caracterul d:
char a = 100, b = 'd' ;
cout << a << " " << b ;
In urma executiei urmatorului program:
#include <iostream.h>
void main()
se va afisa 'n' si numarul 130 deoarece se aduna codul caracterului 'n', care este 110, cu numarul.
In C++ nu exista tipul logic. In C++, o variabila care retine o valoare diferita de 0 este TRUE (adevarata), iar una care retine valoarea 0 este FALSE (falsa).
4) In C++ este admis tipul void, cu semnificatia de "nimic" sau " orice tip",in functie de context.
Constante
Pentru a defini
o
const [tip] nume = valoare ;
tipul constantei numele constantei valoarea constantei
(daca e absent, tipul e int);
Ex: const int v1= 8;
const float v2 = 8.8;
const v3 = 12;
Obs: Atat variabilele cat si constantele pot primi ca valori expresii constante:
Ex: const int a
int b = (3+2*4)-1;
1. Constante intregi
- zecimale (in baza 10). Exemple: 5, 345, 32, -12
- octale (in baza 8). O succesiune de cifre octale 0 - 7 precedata de un 0 nesemnificativ.
Exemple: 0345 retine numarul 345(8) .
- hexazecimale (in baza 16). O succesiune de cifre hexazecimale precedata de 0x sau 0X.
Exemple: 0x2B3 retine numarul 2B3(16) .
Cifrele hexazecimale se obtin extinzand cifrele zecimale cu literele mici sau mari de la A la F:
Litera care reprezinta o cifra hexazecimala |
Valoare |
a sau A b sau B c sau C d sau D e sau E f sau F |
Obs: o
2. Constante caracter:
Acestea se trec intre doua caractere
apostrof: 'a', 'A', '3' .O
De exemplu pentru 'a' se memoreaza 97, iar pentru 'A' se memoreaza 65.
O alta modalitate de declarare a constantelor caracter este sub forma de secvente escape. O secventa escape incepe cu caracterul backslash (
Fie, de exemplu, constanta caracter 'c' care are codul 99(10) = 143(8) = 63(16) .
Aceasta poate fi scrisa echivalent : '143' sau 'x63' . In cazul reprezentarii in baza 16 se foloseste precedata de caracterul 'x'.
Ex:
Programul urmator va tipari de 4 ori caracterul ´c´ :
#include <iostream.h>
void main()
Rolul secventelor escape este acela de a da posibilitatea declararii caracterelor care nu se pot tasta. De exemplu, caracterul backspace (codul 8(10)) poate fi declarat '10' sau 'x8' , iar caracterul newline (codul 10(10)) poate fi declarat '12' sau 'xa' .
Obs Dat fiind un numar intreg (scris intr-o baza oarecare b1), pentru scrierea lui intr-o alta baza (b2) se imparte succesiv numarul scris in baza b1 la noua baza pana cand se obtine catul 0; Reprezentarea in noua baza se obtine prin scrierea resturilor (reprezentate in noua baza) in ordinea inversa obtinerii lor si multiplicarea cu puterea corespunzatoare a bazei care este egala cu rangul operatiei.
In multimea caracterelor cu rol special pentru citire/scriere se situeaza caracterele albe (whitespaces): blank (' '), tab orizontal (t), tab vertical (v), newline (n), cr (r).
Ex:
#include <iostream.h>
void main()
Programul tipareste bbbbbbbbi
tab
3. Constante reale:
- au o parte intreaga (ce poate fi
vida); in acest caz devine o
- au o parte fractionara (ce poate fi vida numai daca partea intreaga este prezenta); aceasta este formata din: caracterul '.' (punct) urmat de o succesiune de cifre zecimale.
- au un exponent (poate lipsi); incepe cu E sau e, apoi + sau - (optional) urmat de un sir de cifre zecimale; E sau e exprima o putere a lui 10.
Ex:
Constanta reala Valoare Constanta reala Valoare
12. 12 25e4 25x10^4
123.4 123.4 .1E-5 0.1x10^(-5)
.67 0.67 -123.456e2 -123.456x10^2=-12345.6
Obs: Implicit acestea sunt memorate utilizand tipul double. Se poate forta ca acestea sa fie memorate sub tipul float adaugand sufixele f sau F sau sub long double adaugand l sau L.
Ex: -144.5 se memoreaza sub forma double
-144.5f se memoreaza sub forma float
-144.5L se memoreaza sub forma long double
4. Constante sir de caractere:
Se declara intre doua caractere ". Functiile de prelucrare sunt in biblioteca string.h.
Ex: "acesta este un text"
Obs: Pe langa mecanismul cunoscut de declarare a constantelor (cu ajutorul lui const) in C++ mai avem posibilitatea de declarare cu ajutorul directivei preprocesorului, #define:
#define nume expresie
Aceste constante raman valabile pana la sfarsitul programului, pana la redefinirea lor sau pana la intalnirea directivei #undef.
Ex:
#include <iostream.h>
#define pi 3.14
#define text "valoarea aproximativa a lui pi este"
main()
Rolul preprocesorului este de a inlocui fiecare aparitie a numelui constantelor cu constantele respective. Astfel, dupa preprocesare, vom avea:
cout<<"valoarea aproximativa a lui pi este"<<3.14;
Se poate defini o
#include <iostream.h>
#define pi 3.14
#define alt_pi pi
main()
Expresii
expresie - formata dintr-un operand sau mai multi, legati prin operatori.
Pot fi grupati in mai multe clase: aritmetici, relationali, de egalitate, de incrementare si decrementare, logici, logici pe biti, de atribuire, etc.
constante, variabile sau functii.
La scrierea unei expresii se pot folosi operatori din aceeasi clasa sau din clase diferite. La evaluarea expresiilor trebuie sa se tina seama de prioritatile operatorilor care apartin diferitelor clase de operatori, de asociativitatea operatorilor de aceeasi prioritate (ordinea aplicarii operatorilor consecutivi de aceeasi prioritate) si de regula conversiilor implicite.
In functie de prioritate ,de la maxim la minim, operatorii se clasifica astfel:
prioritate |
operatori |
semnificatie |
asociativitate |
-> |
apel de functie expresie cu indici selector de membrii la structuri |
s d |
|
& sizeof (tip) |
negare logica negare bit cu bit plus unar sau minus unar incrementare si decrementare obtinerea adresei indirectare dimensiune operand (in octeti) conversie explicita de tip |
d s |
|
inmultire impartire restul impartirii intregi |
s d |
||
plus binar (adunare), minus binar (scadere) |
s d |
||
<< >> |
deplasare la stanga deplasare la dreapta |
s d |
|
<, <= >, >= |
mai mic si mai mic egal mai mare si mai mare egal |
s d |
|
egal, diferit |
s d |
||
& |
Si logic pe biti |
s d |
|
Sau exclusiv pe biti |
s d |
||
Sau logic pe biti |
s d |
||
&& |
Si logic |
s d |
|
Sau logic |
s d |
||
operatorul conditional |
d s |
||
&= <<=, >>= |
atribuire simpla atribuire produs, atribuire impartire atribuire rest atribuire suma, atribuire diferenta atribuire Si (bit) atribuire Sau exclusiv (bit) atribuire Sau (bit) atribuire cu deplasare stanga, respectiv dreapta |
d s |
|
virgula |
s d |
Operatori aritmetici sunt in ordinea descrescatoare a prioritatii):
a. Unari: + , - (asociativitate dreapta -stanga);
b. Binari multiplicativi: *, /, % (asociativitate stanga - dreapta);
c. Binari aditivi: + , - (asociativitate stanga - dreapta).
Obs:
Operatorul ' / ' actioneaza in mod diferit in functie de operanzi:
a) daca ambii sunt de tip intreg, rezultatul este intreg si are semnificatia de impartire intreaga
b) daca cel putin unul din operanzi este de unul din tipurile reale, rezultatul este real, deci se
efectueaza impartirea obisnuita.
Ex: Fie declaratia int a
Expresia 2*a/5 este de tip int si la evaluare se obtine 5.
Expresia 2*(a/5) este de tip int si la evaluare se obtine 4.
Fie declaratia float a
Expresia 2*a/5 are ca rezultat 5.6
Expresia 2*(a/5) are ca rezultat tot 5.6
Operatorul ' % ' (restul impartirii intregi) actioneaza numai asupra operanzilor de tip intreg.
Ex: Expresia 7%3 are ca valoare 1.
Expresia -7%3 are ca valoare -1. deoarece -7 = (-2)*3 + (-1)
La evaluarea expresiilor, in cazul in care un operator se aplica la doi operanzi de tipuri diferite, se aplica urmatoarea regula (a conversiilor implicite):
- orice operand de tipul char si unsigned char este convertit catre tipul int.
- daca un operand este de tipul unsigned long, atunci si celalalt se converteste catre tipul unsigned long.
- daca un operand este de tipul long, atunci si celalalt se converteste catre tipul long.
- daca un operand este de tipul float, atunci si celalalt se converteste catre tipul float.
- daca un operand este de tipul double, atunci si celalalt se converteste catre tipul double.
daca un operand este de tipul long double, atunci si celalalt se converteste catre tipul long double
Ex:
Fie declaratiile:
int a = 5; char b = 6; float c = 9;
Atunci expresia a + b + c are rezultatul 20.0
Programul urmator va tipari 97:
#include <iostream.h>
void main()
Exercitii:
Realizati rularea urmatoarelor programe:
#include <iostream.h>
void main()
#include <iostream.h>
void main()
#include <iostream.h>
void main()
Operatori relationali
<, >, <=, >=
Deoarece in C++ nu exista valorile logice TRUE si FALSE, rezultatul unei operatii logice este 1 in cazul in care inegalitatea e respectata si 0 in caz contrar.
Ex:
> 5 rezultatul este 0
3 < 5 rezultatul este 1
Operanzii pot fi constante, variabile, functii.
Operatori de egalitate
Ca si in cazul operatorilor relationali, se returneaza 0 sau 1 in functie de modul in care este respectata sau nu egalitatea .
Operanzii pot fi constante, variabile, functii.
Obs: Deoarece rezultatul operatiilor logice este 1 sau 0, se pot gasi ca operanzi in cadrul unor expresii aritmetice.
Ex:
a = ((1<2)+(3!=5))*2 dupa aceasta a
a = (2<3) = = (2!=8) dupa aceasta a = (1) = = (1) deci a = 1
a = 5= =6 dupa aceasta a = 0 deoarece 5 este diferit de 6
Operatori logici
negare logica : daca operandul este o valoare ¹ 0, rezultatul este 0, altfel este 1
&& si logic: daca ambii operanzi sunt ¹ 0, rezultatul este 1, altfel este 0
êê sau logic: daca cel putin unul din operanzi este o valoare ¹ 0, rezultatul este 1, altfel este 0
Ex:
(2+3*3)&&(!0) rezultatul este 1 pentru ca ambii operanzi sunt ¹
êê rezultatul este 0 pentru ca nici un operand nu este ¹
rezultatul este 0 pentru ca operandul este ¹
rezultatul este 1
!(3>4) rezultatul este 1 pentru ca operandul este 0
Obs: Deoarece operatorii logici aplicati unor operanzi produc valorile 0 sau 1, apelul lor poate apare ca operanzi in cadrul unor operatii aritmetice:
Ex:
a = (!(3 < 4) + (3 && 4 ) * ( !0 )+( 3 êê
Operatori logici pe biti actioneaza numai asupra operanzilor de tip intreg
~ negare pe biti (unar) & si pe biti (binar)
ê sau pe biti (binar) ^ sau exclusiv pe biti (binar)
<< deplasare stanga (binar) >> deplasare dreapta (binar)
Operatorul unar ~ Operatorul binar & Operatorul binar ê Operatorul binar ^
0 & 0 | |
0 & 1 | |
1 & 0 | |
1 & 1 |
ê | |
ê | |
ê | |
ê |
Ex:
7 & 3 = 3 deoarece: 7 0 0 0 0 0 1 1 1 &
ê deoarece: 7 0 0 0 0 0 1 1 1 ê
deoarece: 7 0 0 0 0 0 1 1 1 ^
Operatorul << deplaseaza catre stanga continutul tuturor bitilor operandului din stanga sa, cu un numar de pozitii egal cu valoarea retinuta de al doilea operand. Pozitiile ramase libere in dreapta, vor retine valoarea 0.
Obs: a << n este echivalent cu a * 2n
Ex:
8 << 3 = 64 deoarece: 8 0 0 0 0 1 0 0 0
deplasare cu 3 pozitii la stanga
Operatorul >> deplaseaza catre dreapta continutul tuturor bitilor operandului din stanga sa, cu un numar de pozitii egal cu valoarea retinuta de al doilea operand. Pozitiile ramase libere in stanga, vor retine valoarea 0.
Obs: a >> n este echivalent cu a / 2n
Ex:
7 >> 2 = 1 deoarece: 7 0 0 0 0 0 1 1 1
deplasare cu 2 pozitii la dreapta
Operatorul de atribuire
- atriburi simple - sintaxa v = expresie
compuse - sintaxa: v = v1 = v2 = .. = vn = expresie
vn = expresie; vn-1 = vn; vn-2 = vn-1;.. v1 = v2; v = v1
Ex: declaratiile: atribuirile:
int a, b; a = c = b = (11 + 8) * 2; // b va fi egal cu 38, c cu &, a cu 38
char c; c = a = f = 37.67; /* f va fi egal cu 37.67, a cu 37(conversie),
double f; c cu 'a'(conversie) */
c = 'f' ; // c devine egal cu 'f'
Obs : Pentru atribuiri se pot folosi si operatorii *=, /=, %=, +=, -=, <<=, >>=, &=, ^=,
in expresii de forma: v op expresie echivalent cu v = v op expresie
Ex:
declaratia: atribuirile:
int a; a *= 2 este echivalent cu a = a * 2
a %= 4 este echivalent cu a = a % 4
Operatorul virgula
se utilizeaza in situatii in care intr-un anumit punct al unui program este necesar sa se realizeze un calcul complex exprimat prin mai multe expresii.
formatul: exp1 , exp2 , .., expn;
Expresiile se evalueaza pe rand, de la stanga la dreapta. Intreaga expresie (care cuprinde cele n expresii separate prin virgula ) va avea ca rezultat si tip valoarea si respectiv tipul, obtinute in urma evaluarii ultimei expresii.
Ex: declaratiile: expresia c = a = b + 3 , a = c + 2, b = b + 3 se evalueaza astfel:
int a , b = 7; b + 3 = 10; a = 10 ; c = 10.0 ;
float c; a = 10 + 2 = 12;
b = 7 + 3 = 10 ;
expresia in ansamblu este de tipul int si produce valoarea 10
Operatorul conditional
se utilizeaza in situatia in care exista doua variante de obtinere a rezultatului in functie de indeplinirea unei conditii.
formatul: exp1 ? exp2 : exp3;
- Se determina valoarea expresiei exp1.
- Daca aceasta este diferita de 0, se evalueaza exp2, iar exp3 este ignorata.
- Altfel, se evalueaza exp3 si exp2 este ignorata.
In ansamblu, expresia este de tipul lui exp2 sau exp3 si produce valoarea exp2 sau exp3.
Ex:
1) int a, b, max
max = (a>b) ? a : b; max primeste ca valoare maximul dintre a si b
2) Programul urmator citeste a de tip float si tipareste a
#include <iostream.h>
void main()
Operatori de incrementare si decrementare
incrementeaza (aduna 1) si respectiv decrementeaza (scad 1) continutul unei variabile. Operatorii sunt: ++ pentru incrementare prefixat (in fata operandului): ++a
postfixat (dupa operand): a++
pentru decrementare prefixat (in fata operandului): --a
postfixat (dupa operand): a--
Obs: Daca operatorul este prefixat, variabila este incrementata / decrementata inainte ca valoarea retinuta de ea sa intre in calcul.
Daca operatorul este postfixat, variabila este incrementata / decrementata dupa ce valoarea retinuta de ea intra in calcul.
Operatorii de incrementare/ decrementare prefixati si postfixati se aplica numai variabilelor. Exemple de expresii incorecte: ++4; 4--; (5+a)++; (5+a)--; ++(10+b); --(10+b)
Ex: int a=5, b, c; b=5+(++a); // b=5+(6)=11 si dupa aceasta atribuire a devine 6
c=++b*++a; // c=12*7=84 si dupa aceasta atribuire a devine 7 si b 12
b=5+(a++); // b=5+(5)=10 si dupa aceasta atribuire a devine 6
c=b++*a++; // c=10*6=60 si dupa aceasta atribuire a devine 7 si b 11
b=5+(--a); // b=5+(4)=9 si dupa aceasta atribuire a devine 4
c=--b*--a; // c=8*3=24 si dupa aceasta atribuire a devine 3 si b 8
b=5+(a--); // b=5+(5)=10 si dupa aceasta atribuire a devine 4
c=b--*a--; // c=10*4=40 si dupa aceasta atribuire a devine 3 si b 9
Operatorul sizeof (dimensiune)
folosit pentru a determina dimensiunea in octeti a unui tip de date sau a rezultatului unei expresii.
Forme: sizeof (expresie)
sizeof (tip)
Ex: int a, b, c, d; a = sizeof(float); a = 4 // float ocupa 4 octeti
float e; b = sizeof(e); b = 4
c = sizeof(int); c = 2 // int ocupa 2 octeti
d = sizeof(3 + 2*4); d = 2 // rezultatul e de tip int
Operatorul de conversie explicita (cast) sau de fortare a tipului
folosit, atunci cand e nevoie, in cadrul unor expresii, pentru ca anumiti operanzi sa intre in calcul convertiti asa cum dorim si nu implicit.
Forma: (tip_conversie) operand
astfel, valoarea operandului se converteste spre tip_conversie .
Ex: float a; a = (float) 5; a = 5.000000
int b; b = (int) 5.35; b = 5
int c; c = (int) (3.78 + 7); c = 10
float d; d = (float) (1/2) d = 0.000000
float d; d = 1/(float) 2 d = 0.500000
float d; d = 5+((float)3+4) d = 12.000000
Instructiuni
Instructiunea expresie
Forma: expresie;
expresie atribuire apel de functie
instructiune expresie instructiune de atribuire instructiune de apel a functiei respective
Ex: a+3; a++; Ex: x=4; a=a-5; Ex: randomize( );
Instructiunea compusa
succesiune de instructiuni incluse intre acolade, precedate eventual de declaratii de variabile locale.
Forma:
Obs: dupa executia ultimei
instructiuni a
instructiunii compuse, variabila aux
nu mai este definita
Ex: presupunem ca intr-un punct al programului trebuie
permutate valorile variabilelor a si b:
Instructiunea IF
Forme: if (expresie) instructiune;
if (expresie) instructiune1;
else instructiune2;
Functionare: se evalueaza expresia din paranteze. Apoi, in primul caz, daca expresia are valoarea diferita de 0 (adevarat) se executa instructiune. Altfel, se trece la instructiunea urmatoare instructiunii if. In al doilea caz, daca expresia are valoarea diferita de 0 (adevarat) se executa instructiune1 si apoi se trece la instructiunea urmatoare instructiunii if; altfel, se executa instructiune2 si apoi se trece la instructiunea urmatoare instructiunii if.
Obs:
Inainte de cuvantul cheie else nu se pune ';' daca instructiune1 este o instructiune compusa, altfel se pune obligatoriu.
Ramurile instructiunii if pot contine la randul lor alte instructiuni if (se numesc if-uri imbricate).
Exemple de secvente scrise corect d.p.d.v. sintactic:
k=3; if (1) cout<<"da" k=3; if (0);
if (!0) k++; else cout<<"nu"; if (!k); else cout<<"nu";
else k--; else;
Exemplu de program ce exemplifica folosirea unei instructiuni if in corpul altei instructiuni if.
Se citesc trei variabile reale x, y , z. Sa se calculeze:
x+y, z>0
e = x*y, z=0
x-y, z<0
#include <iostream.h>
void main()
Instructiunea SWITCH
permite selectia unei variante din mai multe posibile.
Forma: switch (expresie)
unde: expresie este o expresie de tip intreg
c1, c2, .., cn sunt constante de tip intreg
instructiuni1, instructiuni2,, instructiunin sunt secvente oarecare de instructiuni
Functionare: se evalueaza expresia. Daca aceasta produce o valoare egala cu ci, se executa secventa instructiunii si se trece la instructiunea urmatoare instructiunii switch, altfel se executa secventa instructiunin+1.
In absenta alternativei default, daca valoarea expresiei nu coincide cu valoarea nici uneia dintre constantele c1, c2, .., cn , instructiunea switch nu are nici un efect si se trece la executia instructiunii urmatoare.
Exemple de secvente scrise corect d.p.d.v. sintactic:
k=2; k=2;
switch ((k-1)*3)) switch(3<4)
default: : cout<<"10";
k='a'; k='a';
switch (k+1) switch(k<'4')
Exemple de secvente scrise incorect d.p.d.v. sintactic:
k=2; k=2;
switch ((k/2.1)) switch((k<4)+3.5)
Exemplu de program care citeste un numar natural si precizeaza daca el reprezinta codul ASCII al unui caracter alfanumeric (litera mica, litera mare, cifra), in acest caz afisandu-se si caracterul:
#include <iostream.h>
void main()
Instructiunea WHILE
instructiune ciclica ce defineste o structura repetitiva conditionata anterior.
Forma: while(expresie)
instructiune;
Functionare: se evalueaza expresie; Daca valoarea obtinuta este diferita de 0, se executa instructiune si se revine la pasul anterior, iar daca se obtine o valoare egala cu 0, se trece la urmatoarea instructiune din cadrul programului.
Obs: 1) Instructiunea care depinde de expresia de la while poate sa nu se execute niciodata. Aceasta se intampla atunci cand dupa evaluarea expresiei se obtine valoarea 0.
Ex: a
Inca de la inceput conditia este falsa si deci
expresia avand valoarea 0, instructiunea nu se executa niciodata.
b=a+1;
while(a>=2)
2) Instructiunea care depinde de expresia de la while poate sa se execute de o infinitate de ori. Aceasta se intampla atunci cand expresia are valoarea diferita de 0 intotdeauna.
Conditia nu devine falsa niciodata si deci
instructiunea se executa de o infinitate de ori.
Ex: a=1; b=b+1;
while(a<=2)
3) Daca dupa expresie se pune ';', avem doua situatii :
- daca conditia este adevarata, se intra in ciclu infinit
- daca conditia este falsa se executa urmatoarea instructiune din program
Ex: a
ciclu infinit
b=b+1;
while(a<=2);
se executa urmatoarea instructiune din program
Ex: a=1; b=b+1;
while(a>=2);
Exemplu de secvente echivalente scrise corect:
secventele urmatoare calculeaza suma primelor n numere naturale, n se citeste de la tastatura.
#include <iostream.h> #include <iostream.h> #include <iostream.h>
main() main() main()
Obs: datorita multiplelor
posibilitati de lucru cu expresii, s-au folosit mai multe expresii separate
prin virgula. Valoarea produsa de expresie este data de ultima din sirul
lor.
i++; }
cout<<"varianta 1"<<" "<<s;
secventele urmatoare calculeaza nr. obtinut prin inversarea cifrelor unui nr. n citit de la tastatura.
#include <iostream.h> #include <iostream.h>
main() main()
cout<<"numarul inversat"<<ninv;
Instructiunea DO WHILE
instructiune ciclica ce defineste o structura repetitiva conditionata posterior.
Forma: do
instructiune
while(expresie);
Functionare: Se executa instructiunea subordonata. Apoi se evalueaza expresie; Daca valoarea obtinuta este diferita de 0, se revine la pasul anterior si se executa instructiune, iar daca se obtine o valoare egala cu 0, se trece la urmatoarea instructiune din cadrul programului.
Exemplu de secvente echivalente scrise corect:
secventele urmatoare calculeaza suma primelor n numere naturale, n se citeste de la tastatura.
#include <iostream.h> #include <iostream.h>
main() main()
cout<<"varianta 2"<<" "<<s;
while(i<=n); }
cout<<"varianta 1"<<" "<<s;
Instructiunea FOR
instructiune ciclica ce defineste structura repetitiva conditionata anterior, cu numar cunoscut de pasi.
Forma: for (exp1;exp2;exp3)
instructiune;
unde exp1, exp2, exp3 sunt expresii: exp1 initializare, exp2 testare, exp3 reinitializare (incrementare)
Functionare: - se executa secventa de initializare definita de exp1.
- se evalueaza exp2. Daca e adevarata se executa instructiune, altfel se termina
executia instructiunii for si se trece la executia instructiunii urmatoare instructiunii for.
- se executa secventa de reinitializare definita de exp3 si se trece la pasul anterior.
Obs: 1) In sectiunea de initializare, exp1, se pot declara si initializa variabile.
2) In cadrul instructiunii for, variabila de ciclare poate fi si de un tip real.
3) daca trebuie folosite mai multe instructiuni in cadrul celor trei sectiuni, exp1, exp2, exp3,
in cadrul fiecarei sectiuni, acestea se separa prin virgula.
4) instructiunea poate fi instructiune compusa sau repetitiva sau de decizie.
Exemple de instructiuni definite corect d.p.d.v. sintactic:
for (float i=1;i<=10.5;i=i+0.5) j=5;
cout<<i<<" "; for(int i=5,j++;i<=10;i++,j++)
cout<<i<<" "<<j;
for(int i=1;i<=10;i++); /* deoarece dupa for am pus ';' in ciclu nu se va executa nici o*/
cout<<i<<" "; /* instructiune, iar valoarea tiparita pentru i va fi 11 */
Instructiunea BREAK
produce iesirea fortata din cel mai interior ciclu while, do-while, for, care o contine sau din instructiunea switch.
Forma: break;
Ex: Programele urmatoare determina, folosind instructiunile for, respectiv while, primul numar divizibil cu 11:
#include <iostream.h> #include <iostream.h>
main() main()
} cout<<m;
i++; }
cout<<m;
Instructiunea CONTINUE
produce saltul la testul de continuare in cazul instructiunilor while si do-while sau saltul la expresia de incrementare, in cazul instructiunii for.
Forma: continue;
Ex: Programul urmator realizeaza descompunerea in factori primi ai unui numar natural n citit de la tastatura, sub forma factor exponent:
#include <iostream.h>
main()
Programul urmator afiseaza, folosind instructiunea for, elementele impare dintre 1 si 100:
#include <iostream.h>
main()
Instructiunea GOTO
produce saltul la instructiunea prefixata de eticheta al carei nume se afla dupa cuvantul cheie go to.
Forma: goto eticheta;
unde eticheta este un identificator al instructiunii cu care se continua executia programului. Ea are forma:
eticheta: instructiune;
Obs: 1) instructiunea goto se utilizeaza rar deoarece incalca principiile programarii structurate.
etichetele sunt locale in corpul functiei in care sunt definite si astfel o instructiune goto poate realiza un salt numai la o instructiune din corpul aceleiasi functii in care ea este utilizata. Deci o instructiune goto nu poate face salt din corpul unei functii la o instructiune din corpul altei functii.
3) in absenta instructiunii goto, se poate realiza acelasi lucru folosind un indicator (semnal) si efectuand o serie de teste asupra lui.
Ex: 1) Ex 2) Exemplul de mai jos modeleaza un ciclu
de incrementare a unei variabile de la 1
for ()
stop: /* codul special pentru tratarea situatiei*/
Functii matematice
In matematica definirea unei functii presupune definirea domeniului de definitie, al codomeniului si a legii de corespondenta pentru functia respectiva. In C++ o astfel de definitie se realizeaza prin definirea prototipului functiei respective.
Exemplu de prototip: int f (int, float);
(codomeniul) rezultatul numele parametrii (domeniul de definitie)
intors functiei functiei
Functiile sunt apelate cu un numar de parametrii efectivi. Parametrii de apel ai unei functii si tipul ei (natura rezultatului intors) sunt continuti de prototipul functiei respective.
Prototipurile functiilor din acelasi domeniu se gasesc grupate intr-un fisier header. Astfel, pentru folosirea functiilor matematice, trebuie inclus in fisierul sursa al programului fisierul math.h.
Functia abs - intoarce |x| (modulul lui x).
forma: int abs(int x);
Functia fabs - intoarce |x| (modulul lui x), unde x este un numar real.
forma: double fabs(double x);
Functia labs - intoarce |x| (modulul lui x), unde x este un intreg lung
forma: long int labs(long int x);
Functia sin - calculeaza valoarea functiei sin(x): R [-1,1]
forma: double sin(double x);
Functia cos - calculeaza valoarea functiei cos(x): R [-1,1]
forma: double cos(double x);
Functia tan - calculeaza valoarea functiei tg(x): R
Obs: Daca in program inlocuim randomize() cu srand(n), pentru valoarea fixata a lui n, la rulari succesive ale programului, seria celor 10 numere va fi intotdeauna aceeasi.
Ex 2): Programul urmator tipareste 10 numere aleatoare cuprinse intre doua valori intregi citite:
#include <iostream.h>
#include <stdlib.h>
main( )
Tablouri
Tabloul reprezinta o colectie de variabile de acelasi tip referite prin acelasi nume.
pot fi unidimensionale
multidimensionale
la declarare trebuie precizate tipul datelor din tablou
numele tabloului
numarul de componente ale tabloului declarat
ocupa o zona contigua de memorie, primul element se afla la adresa mai mica
Obs: Deoarece in limbajul C nu exista un tip predefinit string (sir de caractere) ca in alte limbaje de programare, eventuale variabile de acest tip vor fi tablouri de caractere.
Tablouri unidimensionale
Se declara dupa structura: Selectarea unui element de tablou:
tip_baza nume_tablou[dimensiune]; nume_tablou[indice],
tipul datelor numele dimensiunea (nr. de componente) expresie intreaga cu
din tablou tabloului expresie intreaga constanta valori dimensiune -1
Obs : - Un element de tablou poate fi prelucrat ca orice variabila.
- Memoria ocupata de tablou este: dimensiune*sizeof(tip_baza)
- Daca la initializarea tablourilor de tip numeric, dimensiunea declarata este mai mica decat
numarul valorilor folosite, calculatorul da eroare, iar daca e mai mare, restul componentelor
vor fi initializate cu 0
- Pentru a realiza o prelucrare asupra tuturor elementelor tabloului se foloseste instructiunea
for cu o variabila contor care sa ia toate valorile indicilor ( intre 0 si dimensiune -1 )
Ex :
#include <iostream.h>
- am declarat un tablou
unidimensional cu numele v - datele din tablou vor fi
de tipul int - tabloul are 10 de componente : v[0], v[1], ..v[9] - tabloul ocupa 20 de octeti - efectul
rularii programului este aparitia liniei: 0 2 4
6 8 10
12 14 16 18
main( )
Obs la declarare vectorii pot fi initializati. Valorile cu care se initializeaza sunt valori ale tipului de baza tip_baza si sunt trecute intre acolade si separate prin virgule.
Ex:1) int v
float u[3]=;
#include <iostream.h>
main( )
;
for(i=0;i<=3;i++)
cout<<v[i]<<" ";
Tablouri multidimensionale
Tablourile cele mai des utilizate sunt tablourile cu un indice si cele cu doi indici. Se pot defini insa si tablouri cu mai mult de doi indici.
Forma generala de declarare a unui tablou cu n indici este:
tip_baza nume_tablou[dimensiune1] [dimensiune2 ].[dimensiunen];
tipul datelor numele dimensiunile (nr. de componente)
din tablou tabloului expresii intregi constante
Selectarea unui element de tablou:
nume_tablou[indice1] [indice2] [indicen] ,
unde indicei - expresie intreaga cu valori dimensiunei -1
Obs: 1) Indicele din dreapta este cel care variaza primul iar cel din stanga ultimul pentru ca elementele din lista sa ocupe, unul cate unul, pozitiile componentelor din tablou.
2) Tablourile cu mai multi indici nu sunt eficiente la utilizare din cauza memoriei pe care o necesita (si care se aloca odata cu declararea lor). Memoria ocupata de tablou este: dimensiune1* dimensiune2*. dimensiunen*sizeof(tip_baza).
3) Logica in care este memorat un tablou t cu n dimensiuni este urmatoarea:
tabloul n-dimensional se memoreaza ca un vector alcatuit din dimensiune1 componente, fiecare dintre acestea fiind un tablou cu n-1 dimensiuni;
fiecare tablou (n-1)-dimensional se memoreaza ca un vector alcatuit din dimensiune2 componente, fiecare dintre acestea fiind un tablou cu n-2 dimensiuni, etc.
Ex: fie tabloul: int t[2][3][4]. Acest tablou tridimensional se memoreaza ca un vector cu doua componente, fiecare dintre acestea fiind un tablou cu doua dimensiuni. Fiecare astfel de tablou e memorat ca un vector cu 3 componente, fiecare dintre ele fiind un vector cu 4 componente de tip int.
Obs la declarare tablourile multidimensionale pot fi initializate. Valorile cu care se initializeaza sunt valori ale tipului de baza tip_baza si sunt trecute intre acolade si separate prin virgule.
Ex:1) int a[2][3]=; a[0][0]=1; a[0][1]=2; a[0][2]=3;
a[1][0]=4; a[1][1]=5; a[1][2]=6;
int a[2][3]=,}; a[0][0]=1; a[0][1]=2; a[0][2]=3;
a[1][0]=4; a[1][1]=5; a[1][2]=6;
#include <iostream.h>
main( )
for(int i=0;i<=3;i++)
Obs Un tablou poate fi definit ca o constanta astfel:
const tip_baza nume_const[dimensiune1] [dimensiune2 ].[dimensiunen]
unde c1,.cn - constante de tipul tip_baza , cel mult atatea cate elemente are tabloul, adica
dimensiune1*. *dimensiunen
Ex: const int a[2][3]=; a[0][0]=1; a[0][1]=2; a[0][2]=3;
a[1][0]=4; a[1][1]=5; a[1][2]=6;
Dar dupa aceasta instructiune nu pot exista instructiuni de forma:
a[2][2]=10 (deci componentele nu-si pot modifica valoarea)
Tablouri bidimensionale(matrice)
Limbajul C++ contine tipuri standard (predefinite): intregi, reale
definite de utilizator prin utilizarea declaratiei typedef:
typedef tip nume;
cu maxim 20 linii si 20 coloane de elemente intregi
Ex: typedef int mat [20][20];
mat a;
m linii si n coloane, cu elemente intregi
int i,j,n,m;
mat a;
Secventa de citire a unei matrice a Secventa de afisare a unei matrice a
cu m linii si n coloane: cu m linii si n coloane:
cout<<"m="; cin>>m; cout<<"n="; cin>>n; for(i=1;i<=m;i++)
for(i=1;i<=m;i++) ;
Secventa de parcurgere deasupra diagonalei Secventa de parcurgere sub diagonala
principale a matricei a cu n linii si n coloane: principala a matricei a cu n linii si n coloane:
for(i=1;i<=n-1;i++) for(i=2;i<=n;i++)
for(j=i+1;j<=n;j++) for(j=1;j<=i-1;j++)
.(.a[i][j]..) a[i][j]..)
Secventa de parcurgere deasupra diagonalei Secventa de parcurgere sub diagonala
secundare a matricei a cu n linii si n coloane: secundara a matricei a cu n linii si n coloane:
for(i=1;i<=n-1;i++) for(i=2;i<=n;i++)
for(j=1;j<=n-i;j++) for(j=n+2-i;j<=n;j++)
.(.a[i][j]..) a[i][j]..)
diagonala principala a matricei a diagonala secundara a matricei a
cu n linii si n coloane: a[i][i], i=1,,n cu n linii si n coloane: a[i][n+1-i], i=1,,n
Subprograme
Definitie: Un subprogram este o secventa de instructiuni care rezolva o anumita sarcina si care poate fi descrisa separat. Ea poate fi repetata in cadrul unui program de un numar de ori si executata numai in functie de anumite conditii.
Subprogramele in limbajul C++ se numesc functii.
Un program scris in limbajul C/C++ este un ansamblu de functii, fiecare dintre acestea efectuand o activitate bine definita.
Obs: functia main( ) este tot un subprogram si se executa prima.
Avantaje modularizarea problemei (descompunerea in subprobleme)
reutilizarea unei sevente de instructiuni de mai multe ori in diferite contexte
economie de memorie
depanarea si actualizarea programului se face mai usor
Clasificare in functie de modul de definire create de utilizator
predefinite(Ex: pow, log, abs, etc)
in functie de valoarea returnata returneaza o valoare in punctul de apel la
revenirea din ele
nu returneaza o valoare in punctul de apel la
revenirea din ele, deci nu au valoare de retur;
ele returneaza rezultatul prin intermediul parametrilor
Functiile comunica prin argumente: ele primesc ca parametri (argumente) datele de intrare, efectueaza prelucrarile descrise in corpul functiei asupra acestora si pot returna o valoare (rezultatul, datele de iesire).
In limbajul C/C++ se utilizeaza definitii si declaratii de functii.
Definitia functiei (cuprinde antetul si corpul functiei):
tip nume (lista parametrii formali) antetul functiei
tip - este tipul functiei. Daca functia nu intoarce nici o valoare, in locul sau se specifica void.
Daca tip ≠ void, deci functia intoarce o valoare prin numele sau, corpul functiei trebuie sa
contina obligatoriu instructiunea return expresie; expresia de la return este chiar valoarea
returnata de functie si trebuie sa aiba acelasi tip cu tipul returnat de functie.
nume - este un identificator (numele functiei).
lista parametrii formali - enumerare ce contine tipul si numele fiecarui parametru cu care functia lucreaza formal; ei nu reprezinta valori concrete; se concretizeaza la executie, prin apelurile functiei.
declaratii variabile locale
instructiuni implementeaza algoritmul de calcul al functiei
return[expresie] - se foloseste daca functia intoarce o valoare. La executie, la intalnirea acestei instructiuni, se revine in functia apelanta.
Obs: 1) In C++ nu se pot defini functii imbricate, adica definirea unei functii in corpul altei functii.
2) De obicei, orice functie se apeleaza dupa ce a fost definita. Daca definirea se face dupa apel, inaintea apelului trebuie sa existe declaratia functiei (prototipul functiei).
Declaratia functiei (cuprinde antetul functiei) si informeaza compilatorul asupra tipului, numelui functiei si a listei parametrilor formali. Declaratiile functiilor se numesc prototipuri si sunt constituite din antetul functiei:
tip identificator (lista parametrii formali);
Apelul functiei: se realizeaza printr-o instructiune de apel de forma:
identificator (lista parametrii efectivi);
La apel, se atribuie parametrilor formali valorile parametrilor efectivi, dupa care se executa instructiunile din corpul functiei. La revenirea din functie, controlul este redat functiei apelante, si executia continua cu instructiunea urmatoare instructiunii de apel, din functia apelanta.
Parametrii declarati in antetul unei functii sunt numiti formali, pentru a sublinia faptul ca ei nu reprezinta valori concrete, ci numai tin locul acestora pentru a putea exprima procesul de calcul realizat prin functie. Ei se concretizeaza la executie prin apelurile functiei.
Parametrii folositi la apelul unei functii sunt parametri reali, efectivi, concreti, iar valorile lor vor fi atribuite parametrilor formali, la executie.
Utilizarea parametrilor formali la implementarea functiilor si atribuirea de valori concrete pentru ei, la executie, reprezinta un prim nivel de abstractizare in programare - abstractizare prin parametrii. Acest mod de programare se numeste programare procedurala .
Obs: 1) in cazul in care functia returneaza o valoare, apelul functiei poate constitui un operand intr-o expresie (apelul functiei intervine intr-o expresie)
intre parametrii formali si cei efectivi(actuali) trebuie sa existe o bijectie care sa pastreze ordinea si tipul.
3) parametrii actuali trebuie sa fie variabile declarate sau constante.
4) lista parametrilor formali este vida atunci cand nu se face schimb de informatie cu restul programului sau cand acest schimb se face cu ajutorul variabilelor globale.
Vriabile globale si variabile locale
Conceptual, memoria alocata unui program este impartita in patru segmente:
De asemenea, variabilele pot fi memorate intr-un anumit registru al microprocesorului - caz in care timpul de acces la aceste variabile este foarte mic.
■ segmentul corespunzator codului executabil contine bitii corespunzatori instructiunilor programului si functiile de biblioteca ce sunt adaugate programului.
■ segmentul corespunzator variabilelor globale - segment de date statice, folosit pentru stocarea variabilelor globale.
■ segmentul de memorie stiva - pastreaza variabilele locale si parametrii unei functii.
La fiecare apel al unei functii, variabilele sale locale si parametrii sai sunt depuse in memoria stiva.
La iesirea din functie, aceste variabile si parametri sunt eliminati din stiva.
■ segmentul memoriei heap - disponibila programelor de aplicatii in timpul executiei acestora folosind anumitefunctii ce permit ca unui program sa i se aloce memorie exact atunci cand este nevoie in timpul executiei programului.
In general, o variabila se caracterizeaza prin 4 atribute:
Tipul variabilei
Clasa de memorare - locul unde este memorata variabila respectiva
liniile textului sursa din care variabila poate
fi accesata
Vizibilitatea la nivel de bloc (instructiune compusa)
la nivelul intregului program
la nivel de clasa (in programarea orientata obiect)
Durata de viata statica - are alocat spatiu in tot timpul executiei programului
timpul in care variabila respectiva are alocat
spatiu in memoria interna
locala are
alocat spatiu in timpul in care se executa instructiunile
blocului respectiv
dinamica - alocarea si dezalocarea spatiului necesar variabilei respective
se face de catre programator (prin operatori sau functii speciale)
Astfel, in C++ , in functie de atributele pe care le au, variabilele pot fi impartite in:
- locale
- globale
- dinamice
Variabile
locale - Se
declara in corpul functiilor: in orice bloc (instructiune compusa) a acestora -
Atribute: 1) clasa de memorare: segmentul de stiva 2) vizibilitatea: la nivelul blocului la care au fost declarate 3) durata de viata: atata timp cat dureaza executia blocului respectiv globale - Se declara in afara corpului oricarei
functii - Atribute: 1) clasa de memorare: segmentul de date 2) vizibilitatea: pot fi utilizate de toate functiile care
urmeaza in textul sursa declaratiei variabilei respective 3) durata de viata: statica
Exemplul urmator foloseste variabila cu numele Exemplul urmator ilustreaza faptul ca dupa
nr. Fiind accesibila din oricare din 2 functii fiecare apel, variabilele locale sunt dezactivate:
prezente in program, valoarea variabilei globale
nr este schimbata pe rand din ambele functii:
#include<iostream.h>
void f ( )
cout<<"nr="<<nr; main ( )
nr*=2; f( ); //3 3
} f( ); //3 3
void f2 (void) }
niul de vizibilitate al unei variabile locale
void main (void) este blocul in care se gaseste declaratia sa:
cout<<a<<" "<<b<<endl;
cout<<a<<" "<<b<<endl;
se va
afisa: 1 1 2 1 1
main( )
Obs: 1) In blocuri diferite se pot declara variabile cu acelasi nume.
2) Daca o variabila locala are acelasi nume cu o variabila globala, atunci se va lua in considerare declararea cea mai apropiata de locul utilizarii.
Transmiterea parametrilor
Transmiterea parametrilor este o modalitate prin care un subprogram comunica cu exteriorul.
Transmiterea parametrilor efectivi se face :
prin referinta: sunt precedati de &; se pot modifica in corpul
functiei, dar dupa terminarea apelului functiei au valoarea pe care au
primit-o in timpul apelului functiei prin valoare: se pot modifica in corpul
functiei, dar dupa terminarea apelului functiei au aceeasi valoare pe care
au avut-o inainte de apel.
#include<iostream.h> #include<iostream.h>
int a, b; int a, b;
void interschimb(int x, int y) void interschimb(int& x, int& y)
void main( ) void main( )
Obs: La transmiterea parametrilor prin valoare, ca parametrii efectivi pot apare expresii sau nume de variabile.
La transmiterea parametrilor prin referinta, ca parametri efectivi nu pot apare expresii, ci doar nume de variabile.
Transmiterea prin valoare a tablourilor permite ca functiile sa intoarca noile valori ale acestora (care au fost atribuite in functii) - deoarece numele tabloului este un pointer catre componentele lui. Prin valoare se transmite acest nume si cu ajutorul acestuia accesam componentele tabloului.
Exemplu: in programul urmator, functia vector initializeaza vectorul transmis ca parametru, iar in functia main( ) se va afisa rezultatul.
#include<iostream.h>
void vector(int a[10])
main( )
Exemplu: Ce apare afisat pe ecran in urma executiei programului urmator?
#include<iostream.h>
int a; float b;
int f(float & x)
Valoarea variabilei a devine 12+4=16;
void main()
Exemplu: calculul c.m.m.d.c. a doua numere:Exemplu: Se citeste un vector cu n componente numere intregi. Se cere sa se tipareasca c.m.m.d.c. al valorilor retinute de vector.
Algoritmul de calcul:
Calculam c.m.m.d.c. pentru primele doua componente ale vctorului - valoare ce va fi retinuta de variabila cm.
Apoi, pentru fiecare componenta i, cu i =2, , n-1 se va calcula c.m.m.d.c. intre valoarea retinuta de cm si cea retinuta de componenta i. c.m.m.d.c. va fi retinut din nou de cm.
#include <iostream.h> void main( )
#include <conio.h> }
Exemplu: Se citeste un vector cu n componente numere intregi. Se cere sa se tipareasca vectorul sortat.
#include <iostream.h> main( )
#include <conio.h> scriere(v,n);
} getch( );
void sortare (int x[10], int n) }
void scriere (int x[10], int n)
Aplicatii propuse:
Sa se scrie o functie care simplifica o fractie si o alta care calculeaza suma a doua fractii. Sa se calculeze suma a n fractii, afisand rezultatul sub forma de fractie ireductibila.
Dat fiind un numar natural n, sa se afiseze:
a. cel mai apropiat numar care este patrat perfect. (Ex: pentru n=13 se va afisa 16)
b. cel mai apropiat numar care este cub perfect. (Ex: pentru n=25, se va afisa 27)
c. cel mai apropiat numar care este numar prim. Daca exista doua astfel de numere, se vor afisa amandoua. (Ex: pentru n=27, se va afisa 29, pentru n=15 se vor afisa 13 si 17)
Operatii cu numere complexe (suma, produsul, inversul).
Fie o matrice avand mxn componente intregi. Sa se afiseze acele elemente ale matricii (valoarea si coordonatele) pentru care suma elementelor pe linia pe care se gasesc este egala cu suma elementelor pe coloana pe care se gasesc.
Fie sirul 1,2,3,4. O permutare circulara la dreapta este:2,3,4,1. Sa se permute circular un sir de k ori si sa se afiseze de fiecare data.
Sa se afiseze elementele sa dintr-o matrice (minime pe linie si maxime pe coloana pe care se gasesc) si pozitia lor.
Functii de intrare/iesire standard
Operatiile de intrare/iesire sunt operatii care permit schimbul de date intre un program si un dispozitiv periferic.
Functiile din biblioteca compilatorului C/C++ utilizate mai frecvent pentru operatiile de I/E sunt: - pentru intrare: getch, getche, gets, scanf, sscanf ;
pentru iesire: putch, puts, printf, sprintf.
la care se mai adauga macrourile getchar pentru intrare si putchar pentru iesire.
Functiile getch si getche au prototipuri in <conio.h> si sunt folosite pentru preluarea unui singur caracter din codul ASCII, de la tastatura. Ambele sunt functii fara parametri, iar getch() preia caracterul fara ecou (fara tiparirea lui pe ecran), in timp ce getche() preia caracterul cu ecou; ambele functii returneaza caracterul citit de la tastatura. Caracterele citite cu aceste functii sunt preluate imediat dupa apasarea tastei corespunzatoare caracterului respectiv.
Apelul functiilor getch si getche conduce la asteptarea apasarii unei taste. Apelul acestor functii se face sub forma:
getch( ); sau getche( );
Obs: Functia getch() este frecvent folosita in programele C pentru a bloca fereastra utilizator pana la apasarea unei taste.
Functia putch afiseaza pe ecranul terminalului un caracter corespunzator codului ASCII transmis ca parametru. Caracterele imprimabile au codul ASCII in intervalul [32,126]. Pentru coduri in afara acestui interval se afiseaza diferite imagini. Functia returneaza valoarea parametrului de la apel.
Prototipurile acestor trei functii se gasesc in fisierul conio.h si sunt:
int getch(void); int getche(void); int putch(int ch);
Ex 1:
#include <conio.h>
main() /* citeste fara ecou un caracter imprimabil ASCII, il afiseaza si asteapta actionarea unei taste;
programul se termina dupa actionarea unei taste*/
Ex 2:
#include <conio.h>
main() /* citeste fara ecou un caracter imprimabil ASCII, il afiseaza, trece cursorul pe linia
urmatoare si asteapta actionarea unei taste; programul se termina dupa actionarea unei taste*/
Functia gets are prototip in stdio.h si are ca efect citirea cu ecou de la terminalul standard a unui sir de caractere ale codului ASCII, la adresa specificata drept parametru al functiei. Din functie se revine la:
citirea caracterului 'n' (newline), caracter care este transformat in caracterul '0' (null). In acest caz functia returneaza adresa de inceput a zonei de memorie in care se pastreaza caracterele;
citirea sfarsitului de fisier (CTRL/Z), functia returnand valoarea zero.
Functia puts are prototip in stdio.h si are ca efect afisarea la terminalul standard a unui sir de caractere corespunzand codului ASCII de la adresa transmisa ca parametru. Caracterul '0' este interpretat ca 'n'. Functia returneaza codul ultimului caracter afisat sau -1 in caz de eroare.
Ex 3:
#include <stdio.h>
void main() se tiparesc la iesirea standard siruri de caractere preluate de la tastatura. Terminarea
introducerii datelor se face tastand caracterul EOF prin apasarea simultana a tastelor
Ctrl si Z. *
Obs: In programul de mai sus, NULL este un
nume penru o constanta simbolica folosita adesea in locul intregului zero. In acest
exemplu,
Functia scanf are rolul de a introduce date tastate de la terminalul standard sub controlul unor formate. Datele introduse sunt convertite din formatele lor externe in formate interne si sunt pastrate la adresele specificate la apel. Datele introduse se termina cu apasarea tastei ENTER.
Prototipul functiei scanf se gaseste in fisierul stdio.h si este:
int scanf(const char *format [,adresa,..]);
Ea returneaza numarul de campuri de la intrare introduse corect sau valoarea EOF(-1) in cazul intalnirii sfarsitului de fisier (CTRL/Z).
Formatul este specificat ca un sir de caractere. El contine specificatorii de format, care definesc conversiile din formate externe in formate interne. Un specificator de format este alcatuit din:
caracterul %;
optional caracterul *, care indica faptul ca data prezenta la intrare nu se atribuie nici unei variabile;
optional un numar zecimal, care defineste lungimea maxima a campului controlat de format;
1 sau 2 litere, care definesc tipul conversiei.
Campul controlat de format incepe cu primul caracter curent care nu este alb si se termina, dupa caz:
a) la caracterul dupa care urmeaza un caracter alb;
b) la caracterul care nu corespunde tipului de conversie;
c) la caracterul la care se ajunge la lungimea maxima a campului.
Datele se citesc efectiv dupa apasarea tastei ENTER. Adresa unei variabile se specifica prin &nume_variabila.
Literele care definesc tipul conversiei sunt:
Litera |
Tipul datei citite |
c |
char |
s |
sir de caractere |
d |
intreg zecimal |
o |
intreg octal |
x, X |
intreg hexazecimal |
u |
unsigned |
f |
float |
ld, lo, lx, lX |
long |
lu |
unsigned long |
lf/ Lf |
double/long double |
Functia printf are prototip in stdio.h si este folosita pentru afisarea unor date pe ecranul terminalului standard sub controlul unor formate. Datele sunt convertite din format intern in formatul extern specificat.
Apelul functiei printf se face printr-o constructie de forma:
printf('control',arg1,arg2,..,argn);
unde arg1, arg2,,argn sunt variabile sau expresii ale caror valori se tiparesc in conformitate cu specificatorii de format prezenti in parametrul 'control' al functiei.
Parametrul control este un sir de caractere care defineste textele si formatele datelor care se scriu. In mod concret, acest sir precizeaza transformarile (conversiile) datelor care se afiseaza pe monitor si se reprezinta o succesiune de caractere, inclusiv secvente escape si specificatori de format.
Numarul specificatorilor din parametrul control trebuie sa fie egal cu numarul argumentelor functiei, adica cu numarul variabilelor si/sau expresiilor ale caror valori se tiparesc si trebuie de asemenea sa corespunda tipului acestora.
Un specificator de format contine:
caracterul %;
optional caracterul minus -, care specifica incadrarea datei in stanga campului (datele tiparite se incadreaza intr-un camp - un anumit numar de caractere ; implicit incadrarea se face in dreapta);
optional un numar zecimal, care defineste dimensiunea minima a campului in care se afiseaza data;
optional un punct urmat de un numar zecimal, care specifica precizia de afisare a datei, adica numarul de cifre zecimale sau numarul de caractere care se scriu daca data este un sir de caractere;
una sau doua litere, care definesc tipul conversiei.
Litera c este folosita pentru afisarea unui caracter.
se afiseaza valoarea lui c
(caracterul a) fara nici un fel de
formatare
Ex 4:
char c;
c ='a'; a
se tipareste valoarea lui
c (caracterul a) intr-un camp de 4
caractere, alinierea facandu-se la dreapta
campului
a
printf('%c',c);
printf('n%4c',c);
Litera s este folosita pentru afisarea unui sir de caractere.
se afiseaza sirul
'Ionescu' fara nici un fel de
formatare
Ex 5:
char nume [20]='Ionescu'; Ionescu
Georg
se afiseaza primele 5
caractere ale sirului 'Popescu'
intr-un camp de 15 caractere, alinierea facandu-se la dreapta campului
printf('
%s', nume);
printf('n%15.5', 'Georgescu');
Litera d se foloseste pentru afisarea valorilor variabilelor de tip intreg, in sistemul de numeratie zecimal.
Ex 6:
int a;
a = 46;
printf('%d',a); 46
printf('n%8d',a); 46
printf('n%-8d',a); 46
printf('n%05d',a); 00046
printf('n*%-6d*',a); *46 *
printf('n%d',a/7); 6
printf('n%10.3f',a/7.0); 6.571
Litera o se foloseste pentru afisarea valorilor variabilelor de tip intreg, in sistemul de numeratie octal.
5910
= 738 si 17510 = 2578
Ex 7:
int a = 59; 59
printf('%d',a); 257
printf('n%o',a);
printf('n%9o',175);
Literele x si X se folosesc pentru convertirea si afisarea valorilor unor variabile de tip intreg in sistemul de numeratie hexazecimal. Daca se foloseste litera x in specificatorul de format, atunci pentru afisarea numarului hexazecimal vor fi folosite cifrele 0,1,,9,a,b,c,d,e,f, iar daca se foloseste litera X, atunci pentru afisarea numarului hexazecimal se vor folosi cifrele 0,1,,9,A,B,C,D,E,F, cu observatia ca in zecimal, A=10, B=11, C=12, D=13, E=14 si F=15.
Ex 8:
3310
= 2116 si 7410 = 4a16
printf('%x',33); 21
printf('n%X',33); 21
printf('n%x',74); 4a
printf('n%X',74); 4A
printf('%6x',74); 4a
Ex 8:
int a = 1234, b = 345;
printf('nzecimal: %-10d%10Xhexa',a,a); 1234 4D2hexa
printf('n%-6x',2345); 929
printf('n%-9s%-9s%-9sn','zecimal','octal','hexa'); zecimal octal hexa
printf('%-9d%-9o%-9X',b,b,b); 345 531 159
Litera f este folosita pentru conversia la tipul float si afisarea valorilor cu 6 cifre zecimale.
Ex 9:
float a = 1.234 1.234000
printf('%f',a);
printf('n%-10.3f',a);
Ex 10:
#include <stdio.h>
#include <conio.h>
main( )
RECURSIVITATE
Un obiect este recursiv daca este definit prin el insusi.
O functie este recursiva daca ea se autoapeleaza.
Recursivitatea poate fi:
- directa - cand functia contine un apel direct la ea insasi;
- indirecta - cand functia contine un apel al altei functii, care la randul sau o apeleaza pe prima.
La fiecare apel al unei functii, parametrii si variabilele sale se aloca pe stiva intr-o zona independenta. Acest lucru se intampla la fiecare apel sau autoapel al functiei. Revenirea dintr-o functie se face in punctul urmator celui din care s-a facut apelul. Adresa de revenire se pastreaza tot in stiva. La revenire, stiva se reface la starea ei dinaintea apelului, deci variabilele automatice si parametrii vor reveni la valorile lor dinaintea reapelului respectiv.
O problema importanta este stoparea autoapelului. De aceea trebuie sa existe o conditie de terminare, fara de care un apel recursiv ar conduce la o bucla infinita. In aplicatiile practice este necesar nu numai ca adancimea recursivitatii sa fie finita, ci sa fie relativ mica, deoarece fiecare apel recursiv necesita alocarea pe stiva a zonei de memorie pentru:
- parametrii functiei;
- variabilele automatice locale functiei;
- adresa de return (revenire in punctul de apel).
Ca urmare, stiva poate creste foarte mult si repede se ajunge la ocuparea intregului spatiu de memorie alocat ei.
Un exemplu clasic de proces recursiv este calculul factorialului definit astfel:
1.Factorial
n! = 1*2*3*..*n => n! = (n-1)!*n
definim functia fact(n)= fact(n-1)*n, n>=1
1, n=0
int n; }
int fact(int n) void main()
2. Sa se implementeze urmatoarele relatii de recurenta:
a) progresia aritmetica: an = an-1 + r
definim functia: pa(n) = pa(n-1)+r, n>=1
a0 ,n=0
int n, a0, r;
int pa(int n)
void main()
b)progresie geometrica: bn = bn-1 *q
definim functia pg(n) = pg(n-1) *q, n>=1
b0 ,n=0
int n,b0,q;
int pg(int n)
void main()
3. Sirul lui Fibonacci : 1,1,2,3,5,8,13,21, .....
iterativ:
a=1;b=1;i=3;
cin>>n;
while(i<=n)
cout<<c;
recursiv:
definim functia: fib(n) = 1, n=1
1, n=2
fib(n-1) +fib(n-2), n>=3
int n;
int fib(int n)
void main()
4.Sa se calculeze Ckn in 2 moduri:
a)
int n,k,c;
int fact(int n)
void main()
b)
int n,k;
int cmb(int n,int k)
void main()
Sa se afle c.m.m.d.c. a doua numere a si b:
a) cmmdc(a,b) = cmmdc(a-b,b) , daca a> b
cmmdc(a,b-a) , daca a< b
a, daca a =b
int cmmdc(int a, int b)
void main()
b) cmmdc(a,b) = cmmdc(b, a %b) , daca b¹
a, b =0
int cmmdc(int a, int b)
void main()
6. Sa se afle:
a) suma cifrelor unui numar natural n:
definim functia: suma(n) = 0, daca n = 0
n%10 + suma(n/10), altfel
int n;
int suma(int n)
void main()
b) produsul cifrelor unui numar natural n:
definim functia: prod(n) = 1, daca n = 0
n%10 * prod(n/10), altfel
int n;
int prod(int n)
void main()
c) numarul de cifre al unui numar natural n:
definim functia: nr(n) = 0, daca n = 0
1+nr(n/10), altfel
int n;
int nr(int n)
void main()
7. Sa se calculeze functia lui Ackermann ( cu m si n citite) :
ack(m,n) = n+1, m=0
ack(m-1,1) , n=0
ack(m-1, ack(m,n-1)) , altfel
int m, n;
int ack(int m, int n)
void main()
8. Sa se calculeze functia lui Manna-Pruelli ( cu x citit):
f(x) = x -1, x >= 12
f(f(x+2)), x < 12
int x;
int f(int x)
void main()
9. Cautarea binara: se cauta un element x intr-un vector v ordonat crescator:
Fie v (2, 3, 5, 8, 9, 12) n=6 limita superioara, ls=6
li=1 ls=6 limita inferioara, li=1 m = mijlocul = (li + ls) /2
void cb(int li, int ls)
void main()
10. Sa se afle sumele:
a) S = 1 +2 + 3 + .... +n
fie S(n) = 1 +2 + 3 + .... +(n-1) + n
S(n -1)
definim S(n) = 0, daca n = 0
S(n -1) + n, daca n > 0
int n;
int S(int n)
void main()
b) S = 1 + 1/2 + 1/3 + ... + 1/n
definim S(n) = 0, daca n = 0
S(n -1) + 1/n, daca n > 0
int n; void main()
float S(int n)
c) S = 1*2 + 2*3 + ..... +(n-1)*n
int n;
int S(int n)
void main()
d) S= 1/ (2*3) + 2/(3*4) + ....... + n/ ((n+1)*(n+2))
int n;
int S(int n)
void main()
|