Documente Academic
Documente Profesional
Documente Cultură
Tablouri i pointeri
Att tablourile, ct i pointerii reprezint tipuri de date derivate. Tablourile sunt derivate din tipul
de date al elementelor componente, iar pointerii sunt derivai din tipul de date al elementelor spre
care indic. n plus, tablourile reprezint tipuri de date compuse, metoda de structurare a
elementelor componente ntr-un tablou fiind realizat cu ajutorul indexrii. n mod uzual studiul
celor dou tipuri de date se face mpreun, deoarece tablourile sunt tratate de ctre
compilatoarele limbajului C ca nite pointeri constani, la care se adaug anumite metode de
acces la elmentele componente.
8.1 Tablouri
Din punct de vedere al tipurilor de date, tipurile tablou sunt tipuri de date compuse, n sensul c
un element de tip tablou este compus din mai multe elemente aparinnd altor tipuri de date,
numite componentele tabloului. Toate componentele unui tablou trebuie s aparin ns
aceluiai tip de date, numit tip de date de baz, ceea ce face ca tablourile s fie n acelai timp i
tipuri de date derivate.
Structurarea elementelor componente ale tablourilor se face cu ajutorul indicilor:
tablourile cu un singur indice se numesc tablouri unidimensionale, cele cu doi indici sunt tablouri
bidimensionale, iar n general tablourile cu mai muli indici sunt tablouri multidimensionale.
Tablourile unidimensionale sunt tipurile fundamentale, deoarece tablourile multidimensionale se
definesc pe baza celor unidimensionale.
Deoarece tablourile sunt tipuri de date derivate, definirea sau declararea acestora se face
prin declararea tipului de baz utiliznd operatorul de derivare ([]). n cazul tablourilor
multidimensionale, operatorul [] se aplic pentru fiecare indice separat. De exemplu, secvena
de program urmtoare:
double x[5], d[3][4], z[2][4][3];
Pentru referirea componentelor unui tablou se utilizeaz operatorul de indexare (reprezentat tot
de grupul de caractere[]) conform sintaxei:
<tablou>[<indice>]
unde <indice> reprezint o expresie ntreg. O component a unui tablou reprezint o Lvaloare deoarece are asociat o zon de memorie pentru pstrarea valorii curente.
Observaie. n cazul tablourilor multiplu indexate, operatorul de indexare se specific pentru
fiecare indice. De exemplu, pentru un tablou bidimensional cu numele a, elementul de pe linia i
i coloana j se refer a[i][j], deoarece a[i] reprezint el nsui un tablou unidimensional.
Dup cum s-a precizat anterior, indicii elementelor unui tablou sunt numere ntregi pozitive;
indicele primului element este ntotdeauna zero, pe cnd indicele ultimului element este mai mic
cu 1 dect numrul total de elemente pentru indicele respectiv. Dei compilatoarele limbajului C
nu fac o verificare a valorilor pentru indicii tablourilor (i deci nu genereaz mesaje de eroare la
compilare), utilizarea unui element dint-un tablou care are indicele n afara domeniului corect de
valori poate conduce la erori n execuia unui program.
Modul de alocare a memoriei pentru componentele unui tablou este liniar, indiferent de
numrul de indici al acestuia: elementele tabloului se aloc n ordinea natural a creterii
indicilor. De exemplu, alocarea memoriei pentru un tablou tridimensional definit astfel:
int r[2][3][2];
r[0][0][1],
r[1][0][0],
r[1][2][1].
r[0][1][0],
r[1][0][1],
r[0][1][1],
r[1][1][0],
r[0][2][0],
r[1][1][1],
Datorit faptului c alocarea memoriei pentru elementele unui tablou se face liniar, n cazul
expresiilor ce conin referire la componentele unui tablou, compilatorul trebuie s genereze
adresele de memorie asociate componentelor respective. Modul de determinarea a adresei
componentelor tablourilor va fi descris ntr-un paragraf ulterior.
Exemplul 8.1. Se consider o mulime finit de elemente X = {x1, x2, , xn}. O relaie de
compunere algebric pe mulimea X este o funcie p de forma:
p: XX X
S se determine dac o relaie algebric dat este comutativ sau nu.
Descrierea algoritmului. Pentru reprezentarea relaiei de compunere algebric se pot utiliza dou
tablouri: un vector X=(xi), i=1,,n pentru memorarea elementelor mulimii X i o matrice
P=(pij), i=1,,n, j=1,,n pentru reprezentarea elementelor funciei p. Deoarece problema cere
s se determine doar dac relaia este comutativ, mrimile de intrare ale problemei vor fi doar
numrul n de elemente ale mulimii X, precum i matricea P. n aceste condiii, relaia de
compunere p este comutativ dac matricea asociat P este simetric. Se consider c mulimea
X are ca elemente numere reale.
Descrierea programului.
#include <stdio.h>
int main(void) {
int i, j, n, comutativ=1;
float p[20][20];
printf(\nIntroduceti n: );
scanf(%d, &n);
printf(\nIntroduceti elementele relatiei: );
for(i=0; i<n; i++)
for(j=0; j<n; j++) {
printf(\np[%d][%d]= , i, j);
scanf(%f, &p[i][j]);
}
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if(p[i][j] != p[j][i])
comutativ = 0;
if(comutativ)
printf(\nRelatia este comutativa);
else
printf(\nRelatia nu este comutativa);
return 0;
}
Observaie. Din programul anterior se observ faptul tabloul p a fost declarat cu 20 de linii i 20
de coloane, fr s se cunoasc efectiv numrul real de componente al matricii, memorat de
variabila n (acest lucru se poate determina doar n timpul execuiei programului, cnd variabila n
va avea o valoare citit de la terminalul de intrare). ntruct limbajul C impune declararea
tablourilor cu un numr constant de componente, trebuie ca pentru tablourile pentru care nu se
cunosc dimensiunile n etapa de elaborare a programelor, s se declare o dimensiune maxim
suficient pentru fiecare indice.
Un tablou poate fi definit sau declarat incomplet, fr s se specifice dimensiunea sa, dar
asemenea situaii sunt puine, deoarece fr specificarea dimensiunii nu se poate realiza alocarea
de memorie pentru elementele tabloului. Cazurile uzuale n care se poate omite specificarea
dimensiunii unui tablou sunt urmtoarele :
a. declaraia se refer la un tablou extern, pentru care s-a alocat memorie n alt fiier surs ;
b. definiia conine o iniializare, pe baza creia se poate determina dimensiunea tabloului ;
c. tabloul este declarat ca parametru formal ntr-o funcie, caz n care declaraia este
echivalent cu cea a unui pointer.
Observaie. n cazul tablourilor multidimensionale, numai prima dimensiune poate rmne
neprecizat, n caz contrar nu se pot determina adresele de memorie a elementelor componente.
De exemplu, n secvena urmtoar se definesc trei tablouri, a, b i c, dar numai prima definiie
este corect.
int a[][2][3] ;
int b[][][3] ;
int c[][][] ;
Iniializarea tablourilor este o operaie opional i poate nsoi definiia acestora. Specificarea
valorii iniiale a elementelor unui tablou se realizeaz prin specificarea listei valorilor
elementelor componente, separate prin virgule i nchise ntre acolade. Expresiile folosite pentru
iniializare trebuie s fie expresii constante, care se pot evalua la compilare.
Exemple.
int v[6] = {1, 2, 1, 2, 1, 2} ;
double a[2][3] = { {0, 0, 0}, {1, 1, 1} } ;
double b[2][3] = { 0, 0, 0, 1, 1, 1 } ;
float x[] = {1, 1, 1, 1} ;
char t1[] = "Exemplu" ;
char t2[8] = {E, x, e, m, p, l, u, \0} ;
n exemplul anterior, tabloul x are patru elemente, dimensiune determinat din numrul de
elemente iniializate.
Observaii.
1. n cazul tablourilor multidimensionale, fiecare element compus se specific ntre acolade.
Acest lucru nu este obligatoriu, dac elementele componente se specific n ordinea de
stocare n memorie. n exemplul precedent, tablourile a i b au aceeai valoare iniial.
2. n cazul tablourilor de caractere, iniializarea se poate efectua fie prin specificarea fiecrui
caracter ca element de tablou (cazul tabloului t2), fie prin specificarea irului de caractere
drept o constant de tip ir de caractere (cazul tabloului t1) . n al doilea caz se adaug la
sfrit caracterul cu codul zero. n exemplul precedent, tablourile t1 i t2 au aceeai
iniializare.
Definiia pointerilor se poate face mpreun cu definirea altor elemente aparinnd tipului de date
spre care pointerii indic. De exemplu, declaraia:
int *p, k, m;
definete variabila p ca fiind un pointer ca indic spre obiecte de tipul int, iar variabilele k i m
ca fiind de tipul int.
Pentru a atribui unui pointer adresa de memorie a unei variabile, se poate utiliza operatorul de
adresare &, ca n exemplul urmtor:
p = &k;
specificat i returnarea adresei de nceput a acesteia. n cazul acestei funcii apare o problem
referitoare la tipul de date al obiectului care se va reprezenta n respectiva zon de memorie.
ntruct funcia malloc va fi folosit pentru crearea obiectelor dinamice de diverse tipuri,
rezultatul returnat de funcie este de tipul void*. n acest fel, programatorul trebuie s modifice
tipul de date rezultat n funcie de tipul obiectelor dinamice create, folosind un operator de
conversie de tip. Prototipul funciei este:
void* malloc(size_t <numar_octeti>);
Observaie. size_t reprezint o redefinire a tpului ntreg fr semn, fiind tipul rezultatului
returnat de operatorul sizeof.
Exemple. n urmtoarea secven de program se definete un pointer la un tip ntreg, se creaz
un obiect dinamic (indicat de pointer), se iniializeaz cu o valoare i apoi se distruge obiectul
creat.
int *p;
p = (int*)malloc(sizeof(int));
*p = 3;
free(p);
Rezultatul returnat de funcia malloc este convertit la tipul int* pentru a fi compatibil cu
poinerul p. Parametrul fuciei malloc trebuie s indice numrul de octei utilizai pentru
reprezentatrea obiectelor de tip int. ntruct reprezentarea obiectelor tipului int este
dependent de calculator, se folosete operatorul sizeof, care returneaz numrul de octei
ocupat de tipul de date al parametrului.
n concluzie, dac T reprezint un tip de date i pointerul p este definit ca:
T *p;
atunci alocarea memoriei pentru un obiect dinamic de tipul T se realizeaz n mod uzual astfel:
p = (T*)malloc(sizeof(T));
Observaie. Un apel de forma: free(p); nu se poate face dect dac anterior s-a alocat
memorie pentru pointerul p, altfel execuia programului va fi eronat.
n afar de malloc, se mai pot utiliza i alte funcii de alocare a memoriei. Iat principalele
funcii:
1) Funcia calloc, aloc n blocuri consecutive de memorie i returneaz adresa de nceput a
zonei alocate, sau NULL n cazul n care nu se poate aloca memorie. n plus, ea iniializeaz
zona de memorie alocat cu zero.
void* calloc(size_t <nr_blocuri>, size_t <dim_bloc>);
funcii, adresa blocului de memorie alocat anterior este NULL i funcia realloc se
comport identic funciei malloc.
void* realloc(void* <adresa_bloc>, size_t <dim_bloc>);
Exemplul 8.2. Urmtorul program are doar un scop didactic i folosete obiecte dinamice pentru
determinarea mediei aritmetice a trei numere reale.
#include <stdio.h>
#include <alloc.h>
int main(void) {
float *pmed, *px1, *px2, *px3;
px1 = (float *)malloc(sizeof(float);
px2 = (float *)malloc(sizeof(float);
px3 = (float *)malloc(sizeof(float);
pmed = (float *)malloc(sizeof(float);
printf(\nIntroduceti x1, x2, x3: );
scanf(%f%f%f, px1, px2, px3);
*pmed = (*px1 + *px2 + *px3)/3;
printf(\nmed=%f, *pmed);
return 0;
}
Observaii.
1. ntruct variabilele pointer (px1, px2 i px3 n exemplul anterior) reprezint chiar adrese se
memorie, ele nu mai sunt prefixate de operatorul de adresare & in cadrul funciei scanf.
2. Distrugerea obiectelor dianmice se face cu ajutorul funciei free, iar dac aceasta nu apare,
distrugerea se realizeaz automat la sfritul execuiei programului, cum este cazul
exemplului precedent.
este un pointer de tipul T a crui valoare este egal cu valoarea lui p, la care se adaug
valoarea:
n*sizeof(T)
Cu alte cuvinte, p+n reprezint adresa celui de-al n-lea obiect consecutiv dup cel
indicat de p.
Observaie. n cazul adunrii, nu se pot aduna doi pointeri, chiar dac sunt de acelai
tip.
n cazul scderii operandul din stnga este obligatoriu un pointer, iar operandul din
dreapta poate fi un pointer de aselai tip, sau un ntreg:
o n cazul n care operandul al doilea este un ntreg, rezultatul reprezint tot un
pointer de aclai tip cu operandul stng. Dac T reprezint un tip de date i n
este o expresie ntrag, iar un poiner p este definit ca:
T *p;
este un pointer de tipul T a crui valoare este egal cu valoarea lui p, la care se
scade valoarea:
n*sizeof(T)
Cu alte cuvinte,
p-n
reprezint adresa celui de-al n-lea obiect naintea celui indicat de p.
o n cazul n care operandul al doilea este un pointer, de acelai tip cu tipul
primului operant, rezultatul este un ntreg ce reprezint numrul de obiecte de
acelai tip dintre adresele indicate de cei doi pointeri. S considerm
urmtoarea secven de cod:
int v[10] = {0};
int i = 4, j = 2, n;
int* p = &v[i];
int* q = &v[j];
n = p q;
atunci:
Eval(p-q) = Eval(i-j) = 2
Legtura ntre tablouri i pointeri se poate observa simplu din urmtorul exemplu. Dac se
consider declaraiile:
int v[] = {1, 2, 3};
int* p = &v[0];
int n = 1;
atunci expresia v[n] este echivalent cu *(p+n), iar expresia &v[n] este echivalent cu
p+n. Cu alte cuvinte, tablourile sunt considerate de ctre compilator ca nite pointeri constani:
variabila v din definiia anterioar este considerat ca un pointer de tipul const int*, a crei
valoare este iniializat la adresa de memorie a primului element al tabloului, iar aceast valoare
nu poate fi modificat n timpul execuiei programului.
n mod asemntor se poate defini operaia de scdere: p-n poate fi interpretat ca fiind
expresia p+(-n) i reprezint adresa celui de-al n-lea element anterior celui indicat de p.
Observaie. n cazul tablourilor se pot ns referi elemente aflate n afara zonai de memorie
alocate, ceea ce impune o atenie n ceea ce privete valoarea indicelui unui element al tabloului
(compilatorul nu face o verificare a depirii zonei de memorie ataat tabloului). De exemplu,
considernd un tablou a cu 15 componente de tip int i n o variabil de tip int, atunci expresia
&a[-n] este echivalent cu a-n, adic este egal cu valoarea:
a n * sizeof(int)
ceea ce reprezint o adres de memorie corect pentru compilator. n mod asemntor, expresia
&a[n] este corect chiar dac n depete numrul maxim de componente al tabloului (15),
deoarece valoarea:
a + n * sizeof(int)
Relaia ntre i, j i k se poate determina simplu, dac se numr toate elementele aflate pe liniile
0, 1, , i-1, la care se adaug cele j elemente de pe linia i. Deoarece toate liniile au m elemente,
se poate scrie:
k = m*i+j
Observaie. n relaia anterioar nu apare numrul maxim de linii al tabloului a. Din acest motiv,
exist situaii n care compilatorul permite specificarea incomplet a tablourilor.
Formula de acces pentru componentele unui tablou tridimensional, sau n cazul general kdimensional se poate deduce n mod asemntor.
Expresiile ce conin pointeri i operatori de incrementare/decrementare se interpreteaz n
acelai mod: ei permit indicarea spre elementul succesor/predecsor al elementului curent indicat
de pointerul p. n acest caz ns pot apare confuzii legate de ordinea de evaluare a celor doi
operatori (operatorul de dereferire i cel de incrementare/decrementare). Trebuie reinut faptul c
operatorii de incrementare/decrementare sunt mai prioritari dect operatorul de dereferire.
Urmtorul tabel conine principalele expresii cu aceti operatori combinai (s-a specificat n
tablou doar operatorul de incrementare):
*p++
*++p
(*p)++
++*p
Din tabelul precedent se observ faptul c primele dou expresii acioneaz asupra pointerului,
pe cnd ultimele doua supra obiectului indicat de acesta.
n mod asemntor se pot descrie expresiile combinate ce conin operatori de
decrementare i de dereferire.
n cazul n care ambii operanzi dint-o expresie sunt pointeri, singura operaie permis este
cea de scdere. n acest caz, ambii pointerii trebuie sa aib acelai tip de baz. Dac p1 i p2 sunt
pointeri la un tip T, atunci valoarea expresiei p1-p2 este un ntreg ce cpecific numrul de
obiecte de tipul T aflate ntre obiectele indicate de p1 i p2.
Pe baza operaiei de scdere a pointerilor se definesc operatorii de relaie aplicai pointerilor,
conform tabelului urmtor (p1 i p2 sunt pointeri asociai aceluia tip de date de baz):
Expresie
p1 < p2
p1 <= p2
p1 > p2
p1 >= p2
Semnificaie
p1 p2 < 0
p1 p2 <= 0
p1 p2 > 0
p1 p2 >= 0
n cazul tablourilor multidimensionale se pot scrie expresii mai mult sau mai puin complexe n
care apar operatori de indexare i de dereferire. Semnificaia evalurii unei asemenea expresii se
poate determina relativ simplu dac se ine seama de precedena operatorilor. Tabelul urmtor
prezint cteva exemple de utilizare a acestor operatori n cazul unui tablou bidimensional,
considernd declaraia urmtoare:
int a[3][4];
Expresie
a
*a
**a
a[1]
*a[1]
Semnificaie
Pointer la un vector de 4 elemente int (prima linie a matricii)
Pointer la un element int (prima linie, prima coloan)
Un element int (prima linie, prima coloan)
Pointer la un element element int (linia a doua, prima coloan)
Un element element int (linia a doua, prima coloan)
a+1
*a+1
a[1][1]
a[1]+1
Alocarea memoriei pentru n elemente de tip int se poate realiza cu ajutorul funciei malloc, ca
n figura 8.1.
pv = (int*)malloc(n*sizeof(int));
pv
0
n-1
Dezalocarea memoriei pentru un tablou alocat dinamic se poate realiza simplu cu ajutorul
funciei free:
free(pv);
n cazul tablourilor bidimensionale, o metod simpl este aceea n care o asemenea matrice este
privit ca un vector de pointeri, fiecare element din vector indicnd la o linie a matricii. Pentru
aceasta, se va utiliza un tablou unidimensional asociat liniilor, fiecare element al tabloului
memornd adresa primului element din linia respectiv. De exemplu, pentru un tablou
bidimensional ale crui componente sunt de tip int, declararea se poate face astfel:
int **pa;
pa[n]
Figura 8.2. Alocarea memoriei pentru un tablou bidimensional
Alocarea memoriei se face separat pentru vectorul de pointeri la linii, ct i pentru fiecare linie a
tabloului. De exemplu, dac se dorete alocarea unui tablou cu n linii i m coloane, o funcie de
alocare dinamic se poate scrie astfel:
int** AlocaMatrice(int n, int m) {
int k;
int **pa = (int**)malloc(n*sizeof(int*));
for(k=0; k<n; k++)
pa[k] = (int*)malloc(m*sizeof(int));
return pa;
}
Funcia returneaz adresa primului elemnt al vectorului de pointeri la linii. Tipul de date al
tabloului de pointeri la linii este int*, pe cnd al elementelor de pe fiecare linie este int.
Referirea unui element al unui tablou bidimensional cu alocare dinamic se poate face cu
ajutorul operatorului de indexare, ca i n cazul tablourilor cu alocare static. De exemplu, pentru
tabloul declarat int **pa; elementul de pe linia i i coloana j se specific pa[i][j]. Exist
totui o deosebire ntre codul generat de compilator la referirea unei componente dintr+un tablou
cu alocare dinamic i unul cu alocare static.
De exemplu, pentru tabloul definit astfel:
int a[2][3];
Pentru eliberarea memoriei, trebuie dezalocat att zona de memorie asociat elementelor
liniilor, ct i cea asociat pointerilor la linii:
void DealocaMatrice(int **pa, int n) {
int k;
for(k=0; k<n; k++)
free(pa[k]);
free(pa);
}
Observaie. Metoda utilizat la alocarea dinamic a tablourilor bidimensionale poate fie extins
i la tablourile multidimensionale.
Exemplul 8.3. Se va relua exemplul produsului a dou matrici, utiliznd alocarea dinamic a
acestora.
#include <stdio.h>
#include <alloc.h>
double** AlocaMatrice(int n, int m) {
int k;
double **a = (double**)malloc(n*sizeof(double*));
for(k=0; k<n; k++)
a[k] = (double*)malloc(m*sizeof(double));
return a;
}
void DealocaMatrice(double **a, int n) {
int k;
for(k=0; k<n; k++)
free(a[k]);
free(a);
}
double** CitesteMatrice(int n, int m) {
int i, j;
double **a = AlocaMatrice(n, m);
printf(\nIntroduceti elementele matricii:);
for(i=0; i<n; i++)
for(j=0; j<m; j++)
scanf(%lf, &a[i][j]);
return a;
}
void AfiseazaMatrice(int n, int m) {
int i, j;
printf(\nElementele matricii sunt:);
for(i=0; i<n; i++) {
O constant ir de caractere este interpretat de ctre compilator ca un pointer la tipul char, care
ca valoare adresa de memorie a primului caracter din ir. De exemplu, definiia urmtoare:
Pentru a suplini faptul c limbajul C nu posed un tip de date predefinit pentru irurile de
caractere i nu ofer operatori specifici, sunt puse la dispozie numeroase funcii de bibliotec
pentru prelucrarea acestora. n continuare sunt prezentate cteva funcii mai des utilizate, a cror
declarare de afl n fiierele header string.h i stdio.h.
A) Funcia gets citete un ir de caractere de la terminalul standard de intrare:
char* gets(char* <destinatie>);
Ea returneaz ultimul caracter scris sau EOF n caz de eroare. Aceste dou funcii sunt declarate
n fiierul stdio.h.
C) Funcia strcpy este utilizat pentru copierea unui ir de caractere:
char* strcpy(char* <destinatie>, const char* <sursa>);
Ea copiaz irul de caractere (inclusiv terminatorul de ir) din zona de memorie indicat de
pointerul <sursa> n zona de memorie indicat de pointerul <destinatie>.
Funcia adaug o copie a irulului <sir_1> la sfritul irului <sir_2> i returneaz irul
rezultat.
E) Funcia strlen determin lungimea unui ir, returnnd numrul de caractere din ir,
exclusiv terminatorul:
size_t strlen(const char* <sir>);
Valoarea returnat este zero dac cele dou iruri sunt egale, un numr negativ dac primul ir
este mai mic (n odrine lexicografic) dect cel de-al doilea i un numr pozitiv dac primul ir
este mai mare dect al doilea.
G) Funcia strchr caut prima apariie a unui caracter ntr-un ir:
char* strchr(const char* <sir>, int <c>);
Funcia returneaz adresa primei aparitii a caracterului n ir sau NULL dac irul nu conine
caracterul cutat.
H) Funcia strrchr realizeaz tot o cutare a unui caracter ntr-un ir, dar n sens invers:
char* strrchr(const char* <sir>, int <c>);
Funcia returneaz adresa ultimei aparitii a caracterului n ir sau NULL dac irul nu conine
caracterul cutat.
I) Funcia strstr caut un subir de caractere ntr-un ir:
char* strstr(const char* <sir>, const char* <subsir>);
Funcia caut irul de caractere n irul specificat i returneaz un pointer la primul caracter din
prima apariie a subirului n ir; dac subirul nu a fost gsit se returneaz NULL.
Un alg grup de funcii se refer la conversia irurilor de caractere n valori numerice. De
exemplu, irul s = 123 poate fi convertit n numrul ntreg 123 sau n numrul real
corespunztor. n mod uzual declaraiile acestor funcii se afl n fiierul stdlib.h.
funcia atoi convertete un ir la o valoare ntreg:
int atoi(const char* <sir>);
p1
p2
start
citeste text
p &text[0]
p2 p
cat timp pNULL executa
p1 p2
p2 strstr(p, )
incepand de la de la pointerul p *
p p+N+1
altfel
p p1+1
p2 p
scrie linie
altfel
ramase*
scrie linie
p NULL
sfarsit
Descrierea programului.
#include <stdio.h>
#include <string.h>
#define L_TEXT 256
#define L_LINIE 82
int main() {
char text[L_TEXT], linie[L_LINIE], spatiu[] = ;
char *p, *p1, *p2, *r;
int N, k;
printf(\nNumarul maxim de caractere pe linie: );
scanf(%d, &N);
getchar();
/* sare peste caracterul ENTER */
printf(\nIntroduceti textul:\n);
gets(text);
printf("\nTextul formatat este:\n");
p = text;
p2 = p;
while (p) {
p1 = p2;
p2 = strstr(p1, spatiu)+1;
if (p2 && p2-p>N) {
if (p2-p1>N) {
r = linie;
k = 0;
while (k++<N)
*r++ = *p++;
*r = '\0';
}
else {
r = linie;
while (p<p1)
*r++ = *p++;
*r = '\0';
}
p2 = p;
puts(linie);
}
else if (p2 == NULL) {
r = linie;
while (p)
*r++ = *p++;
*r = '\0';
puts(linie);
}
}
return 0;
}
Observaie. n afar de tipul char, n standardul limbajului C mai este definit un tip de date
numit wchar_t (abreviere pentru wide char type), reprezentnd caractere pe doi octei.
Tipul wchar_t se utilizeaz n cazul altor alfabete dect cel englez, cnd se folosete setul
extins de caractere. n general, toate funciile care lucreaz cu caractere de tip char sunt dublate
de funcii care lucreaz cu wchar_t. Iat cteva exemple:
strcat
strcpy
strlen
strchr
strrchr
strstr
wcscat
wcscpy
wcslen
wcschr
wcsrchr
wcsstr
Funciile care lucreaz cu wchar_t, au o sintax asemntoare cu celelalte, ceea ce difer fiind
tipul parametrilor (wchar_t n loc de char).
8.6 Probleme
8.1.
8.2.
8.3.
8.4.
8.5.
Se consider un polinom de dou variabile, P(X,Y), specificat prin numrul termeni din
polinom, vectorul coeficienilor (cte un coeficient pentru fiecare termen) i o matrice cu
un numr de linii egal cu numrul de termeni i dou coloane reprezentnd puterile celor
dou variabile n termenul corespunztor. S se determine:
a) Valoarea polinomului ntr-un punct dat (x0, y0);
b) Polinomul rezultat prin derivarea polinomului iniial n raport cu variabila X.
8.6.
8.7.
8.8.
8.9.
8.10. Se consider n puncte n plan de coordonate: (x1, y1), (x2, y2), ..., (xn, yn).
a) S se determine dac poligonul cu vrfurile n punctele date este convex sau nu.