Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml


Elemente de baza ale limbajului C

c



+ Font mai mare | - Font mai mic



Elemente de baza ale limbajului C

Scurt istoric al limbajului. Caracteristici generale.

Limbajul C a fost conceput in laboratoarele Bell in anii '70 de catre Dennis Ritchie pentru sistemul de operare Unix. Atat sistemul de operare Unix, cat si unele utilitare din Unix sunt scrise in limbajul C. Dennis Ritchie a scris primul compilator de C pe un PDP-11, urmand ca in curand acesta sa se raspandeasca cu rapiditate si pe alte tipuri de calculatoare. Desi din punct de vedere istoric limbajul C este strans legat de sistemul de operare Unix, C-ul nu depinde de vreun anumit sistem de operare sau de vreo masina anume. Este numit uneori limbaj de sisteme de operare deoarece poate fi folosit cu succes in scrierea sistemelor de operare, dar se poate utiliza la fel de bine si in probleme matematice, in scrierea editoarelor de texte sau la bazele de date.



Limbajul C este un limbaj cu caracter general, caracterizat de compactitate, un set puternic de operatori si portabilitate. Nu poate fi numit limbaj de programare de nivel inalt, si nici nu este creat pentru un anumit domeniu. Totusi, lipsa restrictiilor si caracterul sau general il fac mult mai eficient decat multe alte limbaje de programare de nivel inalt. Limbajul C nu contine operatii asupra obiectelor compuse, cum ar fi sirurile de caractere, multimile, listele sau blocurile. Nu contine nici macar functii de intrare/iesire; acestea sunt incluse in biblioteci din afara limbajului.

Multe dintre ideile limbajului C provin de la mai vechuil limbaj BCPL, dezvoltat de Martin Richards. Influenta directa s-a realizat prin intermediul limbajului B scris de Ken Thompson in 1970 pentru un PDP-7. Desi au cateva caracteristici comune, C-ul nu poate fi in nici un caz numit o varianta a BCPL-ului.

Primii pasi in C

Vom incepe studiul limbajului C prin asimilarea rapida a notiunilor de baza. Scopul este acela de a scrie programe functionale fara insa a acorda atentie regulilor formale, detaliilor neesentiale sau exceptiilor. Nu urmarim deci exhaustivitatea, ba nici chiar exactitatea; trebuie sa se ajunga cat de poate de repede la punctul in care sa se poata scrie deja programe functionale. Din acest motiv, ne vom concentra pentru inceput atentia asupra cunostintelor de baza: variabile, constante, aritemetica, instructiuni, intrari si iesiri.

Singura metoda pentru a invata un nou limbaj de programare este scrierea de programe in acest limbaj. Limbajul C nu are proceduri, ci numai functii; un program C este alcatuit, indiferent de dimensiunea sa, dintr-una sau mai multe functii, dintre care una este principala si poarta numele de main (engl. main = principal, important) . In concluzie, fiecare program contine cel putin o functie, si anume functia main. Iata cum arata cel mai simplu program C (care, evident, nu realizeaza nimic):

void main()

Numele functiilor este in general arbitrar, insa main este un nume special - executia programului incepe intotdeauna cu prima instructiune a functiei main. Rezulta de aici ca in orice program C trebuie sa apara pe undeva functia main. Pentru indeplinirea scopului problemei, functia main va apela in general alte functii, dintre care unele sunt definite in acelasi program, iar altele provin din anumite biblioteci predefinite.

Observam faptul ca dupa cuvantul main urmeaza o pereche de paranteze rotunde. Asa cum este normal, o functie are parametri formali. In cazul de fata lista parametrilor formali este vida, iar perechea de paranteze indica acest fapt. Spre deosebire de limbajul Pascal, in care tipul unei variabile sau functii se preciza dupa numele ei, in C decalrarea unei variabile sau functii incepe chiar cu tipul acesteia.

Functia main neintorcand nici o valoare, va fi de tip void (engl. void = vid).

Perechea de acolade cuprinde instructiunile din care este formata functia. Ele corespund perechii begin end din Pascal. In cazul de fata, functia nu contine nici o instructiune si perechea de acolade este vida.

Programul de mai jos tipareste clasicul "Hello, world!".

#include <stdio.h>

void main()

Asa cum am precizat deja, limbajul C nu contine instructiuni de citire/scriere. Linia

printf("Hello, world!n") ;

este un apel de functie, in care functia printf se apeleaza cu argumentul "Hello, world!". printf este o functie de biblioteca al carei rezultat este scrierea textului pe ecran (in lipsa specificarii unui alt terminal). Pentru a putea utiliza functia printf     compilatorul trebuie sa stie prototipul ei. Prototipul functiei printf se afla in fisierul antet (header) stdio.h (de la STanDard Input Output Header) alaturi de prototipurile altor functii de citire/scriere pe care le vom invata in curand; deci directiva de precompilare

#include <stdio.h>

precizeaza fisierul in care se afla aceste prototipuri.

Caracterul 'n' care apare la sfarsitul sirului de caractere afisat reprezinta modul prin care se indica in C trecerea la linie noua (are acelasi efect ca si writeln-ul din Pascal). Daca omitem 'n'-ul (merita incercat) vom constata ca dupa rularea programului cursorul ramane la sfarsitul sirului afisat, deci nu se mai realizeaza trecerea la linie noua.

Functia printf nu realizeaza niciodata trecerea la linie noua, deci putem afisa caractere pe o singura linie folosindu-ne de apeluri multiple ale ei. Secventa de program urmatoare afiseaza sirul identic cu programul anterior:

printf("Hello, ");

printf("world!");

printf("n");

Mai trebuie sa observam faptul ca 'n' reprezinta un singur caracter. Asemanatoare cu n-ul sunt si alte caractere escape; ele reprezinta un mecanism general utilizat pentru reprezentarea caracterelor netiparibile. In limbajul C mai intalnim t pentru tabulare, b pentru backspace, " pentru ghilimele, iar reprezinta chiar caracterul backslash.

Exercitiul I.2. Incercati ce se petrece daca in sirul de caractere afisat de printf introduceti caracterul x, unde x este un caracter ce nu figureaza in lista de mai sus.

Variabile si aritmetica

Programul de mai jos tipareste urmatorul tabel de conversie de la grade Fahrenheit la grade Celsius conform urmatoarei formule:

C = (5/9)(F-32).

Iata si programul:

/* Program de conversie a gradelor Fahrenheit in grade Celsius

pentru f = 0, 20, ., 300 */

void main()

Primele doua linii:

/* Program de conversie a gradelor Fahrenheit in grade Celsius

pentru f = 0, 20, ., 300 */

reprezinta un comentariu care in cazul nostru informeaza pe scurt despre ceea ce realizeaza preogramul. Compilatorul C nu ia in seama caracterele cuprinse intre /* si */; putem deci cuprinde intre ele diferite texte care pot fi de folos in intelegerea programului. Comentariile pot aparea oriunde poate aparea un spatiu sau o linie noua.

In limbajul C (la fel ca in Pascal) toate variabilele trebuie declarate inainte de a fi utilizate; declararea se realizeza de obicei la inceputul functiei, inainte de orice instructiune. Daca uitam aceasta la compilare vom primi mesaje de eroare. O declaratie consta in specificarea unui tip si enumerarea in continuare a variabilelor de acel tip. In acest sens, putem lua ca exemplu doua linii ale programului:

int liminf, limsup, pas ;

float fahr, celsius ;

Cuvantul rezervat int indica faptul ca variabilele care-i urmeaza sunt de tip intreg (integer) si este echivalent cu integer din Pascal. float reprezinta variabilele in virgula mobila (floating point), adica acele numere care au si parte fractionara si este echivalent cu real din Pascal. Precizia tipurilor int, si float depinde de masina pe care lucram. Pentru calculatoarele compatibile IBM-PC precizia este de 16 biti (de la -32768 la 32767) pentru tipul int, respectiv 32 biti (3.4 * 10-38 pana la 3.4 * 1038) pentru tipul float.

Pe langa int si float in C mai exista si alte tipuri de baza:

char - caracter, un singur octet

short - intreg scurt

long - intreg lung

double - virgula mobila in dubla precizie

Dimensiunea obiectelor de acest tip depinde de asemeni de masina, le vom discuta in detaliu mai tarziu.

In programul de nostru de conversie calculul efectiv incepe odata cu instructiunile de initializare:

liminf = 0 ;

limsup = 300 ;

pas = 20 ;

Se observa ca unele instructiuni sunt despartite de ";".

Fiecare linie a tabelului se calculeaza in mod identic, de aceea vom folosi un ciclu care se a repeta pentru fiecare linie a tabelului; acesta este rolul instructiunii while:

while(fahr <= limsup)

In timpul rularii, masina verifica daca se respecta conditia dintre paranteze. Daca valoarea ei este adevarata (fahr este mai mic sau egal cu limsup) atunci va executa instructiunile dintre acolade (numite si corpul ciclului). Apoi verifica din nou conditia, iar daca valoarea ei este adevarata va executa din nou corpul ciclului. Daca in urma verificarii conditiei se obtine o valoare logica falsa (fahr devine mai mare decat limsup), ciclul se incheie iar executia se continua cu urmatoare instructiune dupa ciclu. Programul de mai sus nu mai contine alte instructiuni, deci executia lui se incheie.

In corpul while-ului pot aparea mai multe instructiuni intre acolade sau o singura instructiune fara acolade, ca in exemplul de mai jos:

while(i<j)

i = 2*i ;

In cazul in care ciclul nu contine nici o instructiune (pare paradoxal, dar vom intalni multe exemple in acest sens) se pune ";" dupa while.

Constante simbolice

se inlocuieste 0,20 si 300 cu directiva #define

modificarea programului a.i. sa fie mai scurt

posibilitatea initializarii la declarare

Cateva programe utile

In cele ce urmeaza vom prezenta cateva programe legate unul de altul care realizeaza operatii simple asupra unor date de tip caracter. Vom observa ca multe programe sunt doar o varianta mai complexa a prototipurilor prezentate aici.

Citirea si scrierea caracterelor

In biblioteca de intrare iesire standard ni se pun la dispozitie functii cu care se poate scrie sau citi un singur caracter la un moment dat. Functia getchar() citeste la fiecare apel al sau urmatorul caracter de la intrare si va returna acest caracter. Deci dupa un apel de forma:
c = getchar()
variabila c va contine urmatorul caracter de la intrare. In general caracterele sunt citite de la terminal (tastatura), dar despre acest lucru vom discuta mai tarziu.

Opusul functiei getchar() este functia putchar. Un apel de forma
putchar(c)
are ca efect scrierea continutului variabilei c la un periferic de iesire care este din nou un terminal (monitorul).

Copiere de caractere

Flosindu-ne de fucntiile getchar si putchar putem scrie surprinzator de multe programe utile, fara a sti nimic altceva despre citire si scrirere. Cel mai simplu exemplu in acest sens este un program care copiaza intrarea la iesire caracter cu caracter. Schita programului este:

Citeste un caracter

Cat_timp(caracterul citit nu indica sfarsitul intrarii)

Scrie caracterul citit la iesire

Citeste un nou caracter

Exprimat in C acest lucru devine:

#include <stdio.h>

void main()

}

Simbolul != inseamna in C "diferit".

Principala problema este sesizarea sfarsitului intrarii. S-a convenit ca atunci cand functia getchar() ajunge la sfarsitul intrarii (marcata de ^Z) sa intoarca o valoare ce nu reprezinta codul nici unui caracter; astfel vom putea sesiza in program momentul in care toate caracterele au fost citite. Problema oarecum neplacuta este ca exista doua tipuri de conventii uzuale referitoare la valoarea returnata la sfarsitul intrarii. Am evitat aceasta problema folosind in loc de o valoare numerica o constanta predefinita: EOF. In practica, EOF este 0 sau -1, functie de compilator. Variabila c a fost declarata int si nu char pentru a putea retine in ea si valoarea EOF returnata la sfarsitul intrarii.

Un programator C experimentat, ar scrie mai compact programul de mai sus. In limbajul C atribuirile de genul

c = getchar()

se pot folosi si in expresii; valoarea expresiei de mai sus este pur si simplu valoarea atribuita membrului din dreapta. Introducand atribuirea referitoare la caracterul c in capul ciclului while, programul se rescrie astfel:

#include <stdio.h> /*copierea intrarii la iesire, var. a doua*/

void main()

explicarea programului

parantezele din while sunt absolut necesare; precedenta lui != este mai mare decat a lui =

Numarare de caractere

Programul urmator, obtinut prin modificarea programului de copiere, numara caracterele citite de la intrare:

#include <stdio.h> /*numarare de caractere*/

void main()

Comentarii:

operatorul ++; exista si -- ; poate fi prefix si postfix

am folosit long pentru a retine mai multe caractere; se tipareste cu %ld

Se poate folosi si double pentru o precizie mai buna. Vom folosi for in loc de while     pentru a exemplifica un alt mod de organizare a ciclului:

#include <stdio.h> /*numarare de caractere*/

void main()

Comentarii:

%0.f pentru a elimina zecimalele inexistente

corpul ciclului for     este gol; scrierea lui ; pe o linie noua pentru a fi remarcat.

verificarea conditiei se face in capul ciclului, deci programul functioneaza si pentru intrare vida

Numarare de linii

Urmatorul program numara liniile introduse la intrare. Presupunem ca fiecare linie se incheie cu n.

#include <stdio.h> /*numarare de linii*/

void main()

if-ul

== pentru comparare. Atribuirile apar de doua ori mai des.

orice caracter cuprins intre ' ' se numeste constanta caracter si reprezinta codul sau numeric (ASCII la noi). De exemplu, codul numeric al lui 'A' este 65 in ASCII. Evident, este mai comod sa scriem 'A' in loc de 65, programul fiind si mai portabil. Se permite ca o constanta caracter sa contina si un caracter escape ( de exemplu 'n'). Sa nu uitam ca 'n' reprezinta un singur caracter.

Exercitiul I.2 Scrieti un program care numara spatiile, tab-urile si newline-urile de la intrare.

Exercitiul I.3. Scrieti un program care copiaza intrarea la iesire, inlocuind sirurile de caracrere formate din unul sau mai multe spatii cu un singur spatiu.

Blocuri

Sa scriem un program care numara de cate ori apare fiecare cifra, de cate ori apar delimitatorii (spatiu, t sau n) si cate caractere de alt tip apar la intrare! Acest exercitiu pare putin cam artificial, dar ne ofera posibilitatea de a studia cateva caracteristici ale limbajului C intr-un singur program.

Trebuie sa deosebim douasprezece tipuri de caractere, deci merita sa stocam numarul de aparitii al diverselor cifre intr-un vector (bloc) decat sa lucram cu douasprezece variabile diferite. Iata una dintre variantele posibile ale programului:

void main()

Declaratia

int ndigit[10]

exprima faptul ca ndigit este un bloc format din 10 numere intregi. Indexul unui bloc incepe in C intotdeauna cu 0 (nu ca in Fortran, sau cum se obisnieste in Pascal cu 1), astfel elementele blocului vor fi ndigit[0], ndigit[1], ., ndigit[9]. Acest lucru este evidentiat si in ciclurile for: unul initializeaza, iar celalalt afiseaza sirul.

Indexul este o expresie oarecare de tip intreg.

Programul de fata se foloseste din plin de modul in care sunt reprezentate intern caracterele. De exemplu conditia

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

decide daca variabila c contine o cifra sau nu. Daca este, atunci valoarea ei numerica este:

c-'0'.

Aceasta metoda poate fi utilizata doar daca codurile caracterelor '0', '1', . , '9' sunt numere crescatoare si intre '0' si '9' sunt reprezentate numai cifre (codul ASCII respecta aceasta conditie: '0' = 48, iar '9' = 57).

In expresiile ce contin tipurile char sau int, confrom definitiei, inainte de evaluare se convertesc toate valorile la int, deci constantele sau variabilele de tipul char sunt in esenta echivalente cu tipul int. Aceasta rezolvare este pe cat de naturala, pe atat de eficienta: de exemplu c-'0' este o expresie de tip intreg a carei valoare este cuprinsa intre 0 si 9, conform cu indexul cerut pentru ndigit.

Conditiile de genul

if(conditie)

instructiune

else if(conditie)

instructiune

else

instructiune

sunt deseori folosite pentru ramificarile multiple.

atentie la else care este legat de ultimul if

vom vorbi de switch

Exercitiul I.4 Scrieti un program care afiseaza histograma lungimii cuvintelor date la intrare. (orizontal).

Functii C

O functie C este echivalentul subrutinei sau functiei din Fortran sau a procedurilor si functiilor din Pascal. Functia este o modalitate comoda de a incapsula anumite parti ale programului in "cutii negre" pe care le vom putea apoi utiliza fara sa ne pese de continutul ei.

alte detalii

Pana acum nu am folosit decat functii pe care le-am avut la dispozitie gata-facute, cum ar fi putchar sau pritnf; a sosit timpul sa construim si noi propriile noastre functii. Deoarece in C nu exista un operator de ridicare la putere ca ** din Fortran, vom studia tehnica definirii functiilor sciind o functie power(x,n) ce ridica numarul intreg x la puterea intreaga n. Deci power(2,5) va fi 32.

Iata cum se defineste si se utilizeaza functia power:

int power(int x, int n)

void main()

Orice functie are forma:

tip_functie nume_functie( lista optionala de parametri )

Functiile pot aparea in orice ordine si pot aparea si in fisiere sursa diferite.

modul de apelare

declararea parametrilor formali.

Exercitiul I.5 Sa se scrie un program C care transforma textul citit in litere mici utilizand pentru aceasta o functie int lower(int c) ce intoarce valoarea c daca c nu este litera mare si corespondentul mic al lui c daca e litera mare.

Argumente; transmitere prin valoare

O caracteristica a limbajului C considerata -mai ales de programatorii Fortran- neobisnuita: transmiterea parametrilor se face intotdeauna prin valoare. Aceasta inseamna ca functia apelata nu primeste adresa la care se afla parametrii actuali ci o copie (valoarea) a lor in variabile temporare(de fapt, intr-o stiva).

De aici rezulta diferenta principala, si anume ca functia nu poate modifica valoarea parametrilor actuali, deoarece ea lucreaza cu o copie a lor, originalul ramanand neschimbat.

Acesta insa nu este un balast, ci un avantaj. Se pot scrie astfel programe mai compacte, folosind mai putine variabile auxiliare, deoarece putem utiliza parametrii in acelasi mod ca variabile initializate clasic. Iata o varianta a functiei power, care foloseste acest fapt:

int power(int x, int n)

Am folosit aici parametrul m ca pe o variabila auxiliara pe care am decrementat-o pana cand a ajuns la valoarea 0; variabila i devine asrfel inutila. Orice operatie pe care o efectuam asupra variabilei n, nu are nici o repercusiune in programul principal.

In caz de nevoie se poate face in asa fel incat functia sa poata modifica valoarea variabilei din functia care o apeleaza. Functia apelanta va trebui sa furnize adresa variabilei ce se doreste a fi modificata, iar functia apelata trebuie sa declare parametrul respectiv va fiind un pointer. Variabila efectiva va fi accesata astfel indirect, prin intermediul acestui pointer. (Aceasta problema se rezolva mult mai elegant in C++). ne vom ocupa de aceasta mai tarziu.

Daca folsim ca parametru numele unui bloc, atunci valoarea care este transmisa functiei este de fapt chiar adresa primului element al blocului. Indexand aceasta valoare se poate accesa oricare element al blocului (elementele unui vector nu sunt copiate).

Siruri de caractere

Cel mai des intalnit sir in C este, probabil, sirul de caractere. Vom studia modul in care se folosesc sirurile de caractere si functiile aferente lor cu ajutorul unui program care citeste linii si o afiseaza pe cea mai lunga dintre ele. Structura de baza este foarte simpla:

cat timp(mai exista linii)

daca(e mai lunga decat linia maxima curenta)

stocheaza linia si lungimea ei

tipareste cea mai lunga linie

Aceasta structura pune in evidenta modularea naturala a programului. Prima parte citeste si verifica linia noua, a doua o stocheaza si a treia conduce intregul proces.

Deoarece sarcinile se pot separe asa de natural, este normal sa scriem programul tinand cont de aceasta separare. Deci vom scrie mai intai o functie getline care citeste de la intrare urmatoarea linie; ea este o generalizare a functiei getchar. Functia getline va returna lungimea liniei sau 0 in cazul in care s-a ajuns la sfarsitul intrarii.(chiar si o linie ce contine doar o trecere la linie noua, are lungimea 1).

Daca vom constata ca linia curenta este mai lunga decat cea mai lunga linie de pana acum, ea va trebui undeva stocata. Apare deci naturala necesitatea unei alte functii numita copy care va copia linia noua intr-un loc sigur.

Iata acum programul:

#define MAXLINE    1000

int getline(char s[])

void copy( char dest[], char source[])

void main()

if( max>0 ) /*au fost linii*/

printf("%s", mline) ;

Comentarii:

cum se transmit parametrii de tip sir

se pune 0 la sfarsit

valoare se transmite prin return.

Exercitiul I.6 Sa se scrie un program care tipareste toate liniile mai lungi de 80 de caractere!

Exercitiul I.7 Sa se scrie un program care elimina spatiile sau tab-urile de la sfarsitul liniilor si sterge liinile complet goale!

Exercitiul I.8 Sa se scrie o functie reverse(s) care rastoarna sirul de caractere s! Se va folosi apoi aceasta functie pentru un program care inverseaza intrarea linie cu linie.

Rezumatul capitolului

Am parcurs in acest capitol cele mai importante elemente ale limbajului C. Chiar si cu aceste cateva elemente de baza putem deja construi programe utile de dimensiuni impunatoare. Pentru aprofundarea elementelor prezentate pana aici va propunem spre rezolvare cateva probleme de un nivel ceva mai ridicat decat cele de pana acum:

Exercitiul I.9 Sa se scrie un program care "pliaza" liniile intrarii in jurul primului caracter diferit de spatiu aflat inainte de pozitia a n-a (n este parametru!)! Verificati ca programul functioneaza corect atunci cand sirul de la intrare este foarte lung, dar si atunci cand inainte de pozitia data nu apare nici un delimitator!

Exercitiul I.10 Sa se scrie un program care elimina dintr-un program C toate comentariile! Sa nu uitam de tratarea corecta a sirurilor de caractere cuprinse intre ghilimele!

Exercitiul I.11 Sa se scrie un program care verfica intr-un program C greselile elementare de sintaxa, cum ar fi numarul parantezelor rotunde patrate sau al acoladelor deschise sa fie egal cu cele inchise! Sa nu uitam de apostrofuri, ghilimele si nici de comentarii!



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 1403
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved