curs 4 - babeș-bolyai universityphys.ubbcluj.ro/~vasile.chis/cursuri/info/c04ppt.pdfint - tip de...

21
CURS 4 Structura generală a unui program C Program - ansamblu de instrucţiuni incluse în una sau mai multe funcţii, care specifică operaţiile ce trebuie efectuate asupra unor date pentru a fi prelucrate în sensul dorit de către utilizator. Program C 1. Directive de preprocesare a) Includeri de fişiere cu text sursă b) Macrosubstituiri c) Includeri conditionate 2. Sectiunea de declaratii a) variabile b) tipuri utilizator c) functii .... 3. Functia principala int main() { ... return 0; } 4. Definirea functiilor utilizator 0. Documentatie

Upload: others

Post on 10-Jan-2020

11 views

Category:

Documents


0 download

TRANSCRIPT

CURS 4 Structura generală a unui program C Program - ansamblu de instrucţiuni incluse în una sau mai multe funcţii, care specifică operaţiile ce trebuie efectuate asupra unor date pentru a fi prelucrate în sensul dorit de către utilizator.

Program C

1. Directive de preprocesare a) Includeri de fişiere cu text sursă b) Macrosubstituiri c) Includeri conditionate

2. Sectiunea de declaratii a) variabile b) tipuri utilizator c) functii ....

3. Functia principala int main()

{

...

return 0;

}

4. Definirea functiilor utilizator

0. Documentatie

- set de comentarii care conţin numele programului şi alte detalii utile programatorului.

0. Documentatie

//Program: easycalc

//Calculator pentru operatii elementare

//Exemplu de folosire a instructiunii switch

//Introducerea functiei system

//system("C:\\windows\\system32\\calc.exe");

// - apeleaza aplicatia calc.exe

Exemple

1. Directive de preprocesare a) Includeri de fişiere cu text sursă b) Macrosubstituiri c) Includeri conditionate

Preprocesare - prelucrarea unui fişier sursă înainte de a fi supus compilării

=> un fişier temporar care conţine un cod sursă provenit în urma traducerii directivelor

de preprocesare. Preprocesorul C - program separat, invocat de către compilator în prima parte a procesului de compilare

a) Includeri de fişiere cu text sursă - se fac cu directiva # include printr-o construcţie de forma : #include <nume_fisier.h> #include "nume_fisier.c“ nume_fisier = fişier cu text sursă păstrat pe disc

În faza de preprocesare textul fişierului inclus se substituie construcţiei #include şi apoi ia parte la compilare împreună cu textul fişierului în care a fost inclus

#include <nume_fisier.h> - se foloseşte pentru includerea fişierelor standard care conţin prototipuri pentru funcţiile de bibliotecă (librării). - instruiesc preprocesorul să trateze fişierele header ca şi cum ar face parte din codul sursă care se compilează. Librăriile sunt coduri gata compilate care se adaugă programului sursă C la compilarea acestuia. Parantezele unghiulare instruiesc compilatorul să caute fişierele care trebuie incluse în directorul cu fişiere antet (de exemplu, C:\BorlandC\include).

Exemple: #include <stdio.h> #include <math.h>

Construcţia #include "nume_fisier.c" se utilizează la includerea fişierelor nestandard care conţin prototipuri ale eventualelor funcţii definite de către utilizator. Fişierul care trebuie inclus se caută în directorul curent dacă nu este specificată nici o cale.

Exemple: # include "factorial.c" # include "C:\\Dev-Cpp\\PERSLIB\\persmat.c"

b) Macrosubstituiri -substituirea unor nume prin succesiuni de caractere şi se fac cu directiva #define sub forma: #define succesiune_de_caractere (vezi constante simbolice).

Macroprocesorul poate efectua şi substituţii de argumente în macrodefiniţii.

Exemplu: #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define grade_rad (x) ((x)*M_PI/180.0)

#include <stdio.h>

#include<conio.h>

#define max2(a,b) (a>b?a:b)

#define min2(a,b) (a<b?a:b)

#define max3(a,b,c)(MAX2(a,b)>c?MAX2(a,b):c)

#define schimb(a,b) {t=a;a=b;b=t;}

#define moddif(a,b) ((a>b)?(a-b):(b-a))

#define suma(a,b) (a+b)

int main()

{

int a,b,t;

printf("a= ");

scanf("%d",&a);

printf("b= ");

scanf("%d",&b);

printf("\nMaximul este %d",max2(a,b));

printf("\nMinimul este %d",min2(a,b));

printf("\nModulul diferentei este %d",moddif(a,b));

printf("\nSuma numerelor este %d",suma(a,b));

schimb(a,b);

printf("\nDupa schimbare valorile a si b sunt %d si %d",a,b);

while(!_kbhit());

return 0;

}

Program exemplu: macrodefiniţii

c) Includeri condiţionate - se folosesc pentru includerea unor fişiere numai atunci când este îndeplinită o anumită condiţie

Exemplu:

#if SYSTEM == MSDOS // daca sistemul de operare este MS-DOS

#include <dos.h> // se foloseste headerul <dos.h>

#else

#include <windows.h> // altfel, se foloseste headerul <windows.h>

#endif

Includerile condiţionate se mai pot folosi pentru construirea grupurilor condiţionate sub forma: #ifdef MACRO text controlat #endif /* MACRO */ Textul controlat va fi inclus numai dacă este definită macrocomanda MACRO şi acest text poate include directive de preprocesare.

Exemplu: #ifdef TURBOC // in TurboC valorile intregi #define INT_SIZE 16 // se stocheaza pe 16 biti iar in SO Unix #else // acestea se stocheaza pe 32 biti #define INT_SIZE 32 #endif // orice includere condiţionată se încheie cu #endif.

2. Sectiunea de declaratii a) variabile b) tipuri utilizator c) functii ....

În această secţiune se stabilesc numele şi atributele variabilelor, a tipurilor de date utilizator sau ale funcţiilor

3. Functia principala int main()

{

...

return 0;

}

4. Definirea functiilor utilizator

Tipuri de date în C

-descriu tipurile valorilor diverselor variabile, constante, funcţii, etc. ale unui program. - fiecare variabilă folosită într-un program C trebuie să fie declarată compilatorului.

- declaraţia va conţine numele variabilelor şi tipul acestora.

Exemplu: ........... int zi,luna,an: .......... zi = 27; luna = 3; //variabilele zi, luna şi an au valori diferite dar au acelaşi tip an = 2019; float medie; .......... medie = 3; //variabilele luna şi medie au aceeaşi valoare dar tipuri diferite

1) Fiecărui tip de dată îi corespunde o denumire (un cuvânt cheie) care este utilizată pentru crearea în memorie a obiectelor ce vor conţine valori corespunzătoare tipului respectiv.

2) Fiecărui tip de date îi corespunde o anumită mărime a zonei de memorie în care se

păstrează valoarea unei date de tipul respectiv.

3) Fiecărui tip de date îi corespunde o anumită gamă de valori, determinată de mărimea locaţiei de memorie corespunzătoare datelor de tipul respectiv.

Tipuri de date de bază (tipuri predefinite) - puse la dispozitie de catre limbajul de programare Tipuri de date derivate (tipuri utilizator) - se construiesc cu ajutorul tipurilor de bază

char - tip de date ale căror valori sunt reprezentate pe un singur octet (byte) int - tip de date ale căror valori sunt reprezentate pe 2 octeţi float - tip de date reale reprezentate în virgulă mobilă, în simplă precizie double - tip de date reale reprezentate în virgulă mobilă, în dublă precizie În plus, există câţiva calificatori care pot fi aplicaţi acestor tipuri de bază: unsigned, short şi long

Tipuri de date de bază

- tipurile predefinite in C:

Structura functiilor

- încapsulează una sau mai multe instrucţiuni, variabile şi parametri într-un pachet unificat care poate fi apelat din interiorul programului - împart sarcinile mari de calcul ale unui program în sarcini de complexitate mai mică

Functii in C

tip nume (listă parametri formali) { declaraţii instrucţiuni }

Definirea functiilor

tip = tip de baza sau tipul void

Funcţiile pot returna valori având ca tip: tipuri de bază pointeri structuri pointeri la structuri pointeri la tablouri

Funcţiile nu pot returna: tablouri

-o funcţie poate avea unul sau mai mulţi parametri, dar poate de asemenea să nu aibă nici un parametru. - sunt folosiţi pentru a face transferuri de date între funcţii - sunt de două feluri: a) parametri formali - nu reprezintă valori concrete ci ţin doar locul unor valori pentru a se putea exprima procesul de calcul realizat de către funcţie în momentul apelului ei - vor fi înlocuiţi de către cei actuali în momentul apelului funcţiei. b) parametri actuali - parametrii transmişi unei funcţii şi care reprezintă valori concrete cu care sunt apelate funcţiile. - pot fi constante, variabile, expresii - nu este obligatoriu ca numele parametrilor actuali să fie identice cu cele ale parametrilor formali.

Parametrii functiilor

Transmiterea parametrilor între funcţii

Exemple:

char ascii (int valoare)

{

char c;

c = (char) (valoare)

return c;

}

int cod (char c)

{

int codc;

codc = (int) (c)

return codc;

}

int cod (char c)

{

return (int) (c);

}

Variabilele din interiorul unei funcţii se numesc variabile locale şi aparţin clasei automatic. - sunt "vizibile" numai în corpul funcţiei în care au fost declarate şi există doar atâta timp cât funcţia în care au fost declarate se află în execuţie - la ieşirea din funcţie valorile lor sunt şterse din memorie (sunt volatile)

Exemple:

Variabile c este de tip automatic şi va fi alocată în memorie de fiecare dată când se execută funcţia suma. Compilatorul va crea un cod pentru alocarea dinamică a variabilei, pentru iniţializarea ei şi pentru eliminarea ei din memorie la încetarea execuţiei funcţiei suma.

- variabile locale care nu se alocă pe stivă ci într-o zonă specială de memorie, rezervată acestui tip de variabile - trebuie să fie precedate la declarare de cuvântul cheie static - spre deosebire de variabilele automatic ele există tot timpul şi nu numai atunci când este executată funcţia (nu îşi pierd valoarea între două apeluri ale funcţiei în care sunt declarate)

static int c;

Exemplu:

- variabile declarate în afara oricărei funcţii a programului - sunt iniţializate automat cu zero şi pot fi utilizate de către orice funcţie a programului - sunt variabile externe, adică pot fi utilizate într-o anumită funcţie a programului chiar dacă nu au fost declarate în funcţia respectivă - au tipul static automat.

Variabilele globale

Recomandare: 1. Este recomandabilă folosirea variabilelor locale deoarece acest lucru conduce la urmărirea mai uşoară a codului unei funcţii particulare. 2. Dacă folosirea variabilelor locale conduce la transmiterea multor parametri sau la reproducerea inutilă a mai multor variabile, atunci este recomandabil să fie folosite variabile globale.

Variabile statice

Apelul funcţiilor

O funcţie se apelează printr-o construcţie de forma: nume (listă parametri efectivi)

Parametrii efectivi - argumentele funcţiei (adică parametrii cu care se apelează funcţia) - trebuie să corespundă cu cei formali (folosiţi la declararea funcţiei) în ordine şi tip. - sunt pasati funcţiilor prin valoare, astfel încât funcţia primeşte o copie a argumentului şi deci ea poate modifica argumentul său fără a modifica originalul. Pentru ca o funcţie să poate modifica argumentul original i se va transmite un pointer la acesta.

# include <stdio.h>

int f(int n)

{

return 2*n;

}

int g(int n)

{

return n*n;

}

int main()

{

int m;

printf("Introduceti o valoare intreaga: ");

scanf("%d",&m);

printf("f(x)=%d \t f(g(x))= %d", f(m),f(g(m)));

printf("\nf(x)=%d \t g(f(x))= %d", f(m),g(f(m)));

return 0;

}

Valorile returnate de către funcţii pot fi folosite ca şi argumente ale altor funcţii

Program exemplu: calculul mediei valorilor unui şir de elemente

//exemplu functie avand ca parametru un tablou #include<stdio.h> #include<conio.h> float medie (int n, float sir[]) { int i; float m,s=0; for(i=0;i<n;i++) s=s+sir[i]; m=s/n; return m; } int main() { int n,i; float note[10],med; printf("n= "); scanf("%d",&n); for(i=0;i<n;i++) { printf("n%d: ",i); scanf("%f",&note[i]); } med=medie(n,note); printf("\nMedia: %.2f",med);

return 0; }

Dimensiunea şirului poate fi omisă în prototipul funcţiei. De asemenea, valoarea primei dimensiuni a unui tablou multidimensional este opţională deoarece compilatorul nu are nevoie de valoarea primei dimensiuni pentru a calcula adresele elementelor tabloului ci numai de dimensiunile următoare. Astfel, dacă avem declaraţia: char Mat[6][8];

Adresa elementului Mat[2][3] va fi adresa lui Mat+2*8+3 deoarece Mat (numele tabloului) este un pointer având ca valoare adresa primului sau element .

Prototipul funcţiilor

O funcţie poate fi apelată într-un anumit punct al unui program dacă a fost în prealabil definită în acel program. Totuşi, o funcţie poate fi apelată şi în cazul în care corpul de instrucţiuni urmează apelului ei. In acest caz, în secţiunea de declaraţii a programului trebuie declarat prototipul functiei.

Prototipul unei funcţii = antetul ei urmat de ; - se foloseşte pentru declararea unei funcţii înainte de definirea ei - poate conţine doar tipul parametrilor formali ai funcţiei, fără numele lor Compilatorul utilizează datele din prototip pentru a verifica tipul parametrilor de la apel. În cazul în care un parametru efectiv are un alt fel de tip decât cel din prototip compilatorul converteşte automat valoarea parametrului efectiv spre tipul indicat în prototip. Fişierele header sunt fişiere cu astfel de prototipuri de funcţii predefinite ale limbajului.

Exemplu: int main ( )

{

long n, k, cnk ;

double fact (long val); // ← prototip fact

cnk = fact(n)/(fact(k)*fact(n-k)); // ← 3 apeluri ale lui fact

return 0;

}

//exemplu de funcţie factorial mai rapidă decât cele prezentate anterior

double fact (long val) // ← antet fact

{

long rez=val; // ← corp fact

while(--val>1)

rez*=val;

return rez;

}

int decidebisect(...) { int i; ..... i=(an%4==0 && an%100!=0)an%400==0); //un an este bisect dacă este divizibil cu 400 //sau dacă este divizibil cu 4 dar nu şi cu 100 //anii de sfârşit de secol nu sunt bisecţi chiar dacă urmează la 4 ani după un an bisect, //cu excepţia celor care sunt divizibili cu 400 //ani bisecţi "obişnuiţi": 1872, 1912, 1960, 1996, 2008... – anii divizibili cu 4 //excepţii: 1800, 1900, 2100, 2200... – anii de sfârşit de secol divizibili cu 100 //sunt totuşi ani bisecţi: 2000, 2400... – anii de sfârşit de secol divizibili cu 400

int b, an;

FILE *f;

f=fopen("d:\\anibis.dat","w");

for(an=1872;an<=2110;an++)

{

if(an%400==0)

b=1;

else

if(an%100==0)

b=0;

else

if(an%4==0)

b=1;

else

b=0;

fprintf(f,"\nan: %d\tbisect: %s",an,b==1?”DA”:”NU”);