TABLOURI, SIRURI DE CARACTERE
Notatia indiciala a variabilelor nu este noua; ea a fost si este folosita in special de matematicieni ori de cate ori este nevoie ca o prelucrare sa fie exprimata cit mai sintetic. Este evident ca prelucrarea SsaSbScSdSeSf arata mult mai putin elegant decat In ultimul caz cele sase variabile a,b,c,d,e,f au fost redenumite x1,x2,,x6; ele pot fi privite astfel drept primele componente ale vectorului x
Tablourile reprezinta tocmai implementarea notiunilor de vector, matrice sau masiv multidimensional intr-un limbaj de nivel inalt. Ele reprezinta colectii omogene de date ( adica de acelasi tip), stocate in locatii de memorie invecinate. Accesul la oricare din elementele tabloului se face cu ajutorul indicilor.
Tablouri unidimensionale
Declaratia unui tablou unidimensional se face dupa forma generala:
tip nume_tablouadimi;
unde:
tip reprezinta tipul de baza al elementelor indexate;
dim reprezinta numarul de elemente ale tabloului;
nume_tablou este un identificator reprezentand numele tabloului.
Dimensiunea zonei continue alocate se calculeaza prin relatia
dimens_allocsdim*sizeof(tip).
De exemplu, prin declaratia
int aa i
se vor aloca vectorului a 100*2s200 de octeti intr-o zona continua de memorie.
Observatii:
alocarea se face in timpul compilarii;
o data facuta alocarea, in scopul maririi vitezei de executie nu se mai face nici o verificare a dimensiunii; gestionarea corecta a zonei de memorie alocate cade, deci, exclusiv in sarcina programatorului.
Referirea la un element al tabloului unidimensional se face precizand numele tabloului urmat de o expresie intreaga intre paranteze drepte, adica
nume_tablouaexpri
Expresia expr poate lua valori intregi cuprinse in intervalula0,dim-1i. Astfel, in urma declaratiei float ya i; vectorului y va avea componente reale si anume:
ya i componenta
ya i componenta
ya i componenta
Intentia de a referi ultimul element al unui tablou sub forma nume_tablouadimi este o greseala cu atat mai grava, cu cat, tinand cont de observatiile anterioare, ea nu este depistata de compilator. De obicei expresiile intregi folosite pentru a accesa componentele unui tablou sunt constante sau variabile simple (indici).
Exemplul 14.1
Comutarea componentelor unui vector si afisarea lor in coloana.
#include 'stdio.h'
#include 'conio.h'
void main(void)
A
int xa50i,i,n,c;
/* citirea elementelor vectorului */
printf('tn lungimea sirului n<50 este:');
scanf('%d',&n);
for (is0;i<n;iSS)
A
printf('tn xa%iis',i);
scanf('%i',&xaii);
I
/* comutarea elementelor */
for (is0;i<n/2;iSS)
A
csxaii;
xaiisxan-1-ii;
xan-1-iisc;
I
/* afisarea elementelor vectorului comutat */
for (is0;i<n;iSS)
printf('tn componenta xa%ii este %i',i,xaii);
getch();
I
Tablouri multidimensionale
Daca elementele unui tablou unidimensional sunt la rindul lor tablouri unidimensionale obtinem un tablou bidimensional sau o matrice. De exemplu, declaratia:
int xa ia i
se poate interpreta astfel: x este un tablou cu elemente xaii is0,1,2,3. Fiecare element xaii cu is0,1,2,3 este un tablou cu elemente intregi xaiiaji cu js0,1,2
Generalizand, un tablou multidimensional poate fi considerat ca un tablou unidimensional care are ca elemente un tablou cu restul de dimensiuni; declaratia unui tablou cu dimensiunile dim1,dim2,,dimn are forma generala:
tip nume_tablouadim1iadim2i adimni
iar referirea la un element al tabloului se face prin:
nume_tablouaindice1iaindice2iaindiceni,
unde indicei ia valori intregi in intervalul a0,dimi-1i, pentru is1,2,,n
Observatii:
Referirea clasica la elementele unui tablou prin separarea indicilor prin virgula este incorecta in C si are semnificatia rezultata din folosirea operatorului de secventiere. De exemplu, considerand declaratia de mai sus, referirea xai,ji este echivalenta cu xaji
Dimensiunea zonei continue de memorie alocate este data (in octeti) de valoarea dim1*dim2*dim3*dimn*sizeof(tip)
Exemplul 14.2
Calculul si afisarea sumei a doua matrici a si b de dimensiune 4x3 citite de la tastatura.
#include 'stdio.h'
#include 'conio.h'
void main(void)
A
int aa10ia10i,ba10ia10i,ca10ia10i;
short i,j,m,n;
/* citirea dimensiunilor mtricilor a,b si c */
do
A
printf('tn ms');
scanf('%i',&m);
printf('tn ns');
scanf('%i',&n);
I
while (m<1 TT m>10 TT n<1 TT n>10);
/* citirea elementelor matricilor a si b */
for (is0;i<m;iSS)
for (js0;j<n;jSS)
A
printf('tn aa%iia%iis',i,j);
scanf('%i',&aaiiaji);
printf('tn ba%iia%iis',i,j);
scanf('%i',&baiiaji);
I
/* calculul matricii suma csaSb */
for (is0;i<m;iSS)
for (js0;j<n;jSS)
caiiajisaaiiajiSbaiiaji;
/* afisarea matricii suma c */
printf('tn matricea suma este:tn');
for (is0;i<m;iSS)
A
for (js0;j<n;jSS)
printf('%4i',caiiaji);
printf('tn');
I
getch();
I
IniTializarea tablourilor
Exemplele anterioare ne-au aratat cum se poate initializa un tablou prin valori date de la tastatura. Exista insa posibilitatea initializarii unui tablou printr-o definitie de forma:
declaratie tablousAlista valori_initialeI;
unde valorile_initiale sunt expresii constante compatibile cu tipul de baza al tabloului.
Exemple:
int vectora6isA-7,-2,95,21,5,-23I;
float aa3ia2isA1,2,3,4,5,6I;
int ba3ia2ia2isA1,2,3,4,5,6,7,8,9,10,11,12I;
In cel de-al doilea caz a fost initializata o matrice. Cum se vor completa elementele matricii? Raspunsul este simplu: "pe linii", adica se completeaza linia , apoi linia si in sfarsit linia . Matricea a va arata astfel:
2
4
6
Pentru a sugera modul de initializare al tablourilor multidimensionale se pot folosi acolade despartitoare in interiorul listei de valori.
Astfel, matricea a se poate scrie mai sugestiv
int ba3ia2is A
A1, 2I,
A3, 4I,
A5, 6I,
I;
In general, initializarea elementelor unui tablou multidimensional se face dupa regula <ultimul indice variaza cel mai rapid>, care este o generalizare a regulii de memorare <pe linii>. Astfel, cele douasprezece componente ale tabloului ba3ia2ia2i vor fi initializate astfel:
ba0ia0ia0is1
ba0ia0ia1is2
ba0ia1ia0is3
ba0ia1ia1is4
ba1ia0ia0is5
ba1ia0ia1is6
ba1ia1ia0is7
ba1ia1ia1is8
ba2ia0ia0is9
ba2ia0ia1is10
ba2ia1ia0is11
ba2ia1ia1is12
Aceste reguli decurg din modul de liniarizare a unui tablou in C: pozitiei i1*i2**in din tablou ii corespunde in forma sa liniarizata (forma sub care i se va aloca memoria) pozitia k data de formula:
ksi1*dim2**dimnSi2*dim3*dimnSSin-1*dimnSin.
De exemplu, in cazul unei matrici aamiani liniarizarea se face dupa formula ksi*nSj
Sa notam in cazul general cu dim produsul dim1*dim2**dimn si cu nval_in numarul constantelor din lista de initializare.
Daca dimsnval_in initializarea tabloului decurge normal dupa regula de mai sus.
Daca dim<nval_in se va produce o eroare, iar daca dim>nval_in restul de elemente sunt initializate cu zero.
Se observa ca formula de alocare nu depinde de prima dimensiune a tabloului, fapt ce permite urmatoarele initializari echivalente cu cele prezentate la inceputul sectiunii:
int vectoraisA-7,-2,95,21,5,-23I;
float aaia2isA1,2,3,4,5,6I;
int baia2ia2isA1,2,3,4,5,6,7,8,9,10,11,12I;
Tablouri Si Siruri de caractere
In C nu exista un tip special pentru definirea unui sir de caractere. Sirurile de caractere se construiesc cu ajutorul tablourilor unidimensionale.
Declaratia unui sir cu numele, nume_sir de lungime maxim dim-1 caractere se face sub forma:
char nume_siradimi;
Sfarsitul unui sir este marcat de caracterul 't0'; din acest motiv, in declaratia sirului, dimensiunea tabloului trebuie sa fie cel putin cu o unitate mai mare decat numarul de caractere al sirului pe care vrem sa-l memoram.
De exemplu:
char sra10i;
contine declaratia sirului sr. Initializarea se poate face printr-o definitie a sirului sub forma:
char sra10is"aAbBcCdD";
Daca numarul elementelor din sir este mai mare decat dimensiunea sirului, caracterele in plus sunt ignorate, in caz contrar restul elementelor este initializat cu zero (caracterul nul
Daca nu se precizeaza dimensiunea, se poate face urmatoarea initializare:
char srais"aAbBcCdD";
care este echivalenta cu initializarea tabloului sr cu un sir de caractere, adica
char sraisA'a','A','b','B','c','C','d','D',t0'I;
Se observa prezenta explicita a terminatorului de sir 't0'
Ultimele doua variante rezerva sirului un numar de locatii egal cu numarul elementelor din sir plus o unitate (corespunzatoare terminatorului 't0') si este mai comoda, deoarece nu precizeaza o limita maxima pentru numarul de caractere, permitand programatorului sa evite numararea elementelor din sir.
Legatura dintre siruri si tablouri unidimensionale permite referirea indexata la caracterele sirului. Folosind acest lucru, in exemplul de mai jos se selecteaza si afiseaza literele mici din sirul sir
Exemplul 14.3
Selectarea si afisarea literelor mici dintr-un sir.
#include 'stdio.h'
#include 'conio.h'
void main(void)
A
int i;
char sirais'aAbBcCdD';
printf('tn Sirul este: %s',sir);
printf('tn Literele mici din sir sunt: ');
for (is0;siraii;iSs2)
printf('%c',siraii);
getch();
I
FuncTii pentru prelucrarea Sirurilor de caractere
14.5.1. FuncTii cu prototipul in "stdio.h"
Pentru operatiile de intrare/iesire cu siruri se pot folosi functiile scanf() respectiv printf() cu descriptorul de format %s
Exemplul 14.4
Citirea a doua siruri sub forma nume prenume si afisarea lor sub forma prenume nume
#include 'stdio.h'
#include 'conio.h'
void main(void)
A
char numea25i,prenumea25i;
printf('tn Numeles');
scanf('%s',nume);
printf('tn Prenumeles');
scanf('%s',prenume);
printf('tn %s %s',prenume,nume);
getch();
I
Pentru citirea unui sir de la tastatura se poate folosi functia gets() cu forma generala:
gets(sir_destinatie);
iar pentru afisarea unui sir pe ecran functia puts() cu forma generala:
puts(sir).
Observatie Functia gets() transfera in sir_destinatie toate caracterele pana la apasarea tastei Enter
14.5.2. FuncTii cu prototipul in "string.h"
Fisierul "string.h" contine prototipurile functiilor specializate pentru manipularea sirurilor de caractere. Iata cateva dintre acestea:
Functia strcpy() cu forma generala:
strcpy(sir_destinatie, sir_sursa);
copiaza sir_sursa in sir_destinatie
Functia strcmp() cu forma generala:
int strcmp(sir1, sir2);
compara cele doua siruri caracter cu caracter si intoarce o valoare:
<0 daca sir1<sir2;
s0 daca sir1ssir2;
>0 daca sir1>sir2.
Comparatia sirurilor se face lexicografic.
Functia strlen() cu forma generala:
unsigned int strlen(sir);
intoarce numarul de elemente dintr-un sir;
Functia strcat() cu forma generala:
char *strcat(sir1, sir2);
adauga sir2 la sfarsitul sirului sir1 (concatenare).
Exemplul 14.5.
Se citeste de la tastatura un numar neprecizat de siruri de caractere. Citirea se termina cand se intalneste sirul "stop". Programul stabileste sirul "minim" (in sens lexicografic) si il afiseaza impreuna cu lungimea sa.
#include 'stdio.h'
#include 'conio.h'
#include 'string.h'
void main(void)
A
char mina20i,xa20i;
printf('tn Introduceti siruri de caractere !
printf('tn La sfarsit tastati STOP tn');
strcpy(min,gets(x));
while (strcmp(x,'stop'))
A
strcmp(min,x)<0 ? min : strcpy(min,x);
gets(x);
I
printf('tn Sirul minim este '); puts(min);
printf('tn si are lungimea %i',strlen(min));
getch();
I
TESTE DE CONTROL
Declaratia
float xa100i;
inseamna
a) rezervarea in memorie a locatii la adrese consecutive
b) rezervarea in memorie a locatii la adrese intamplatoare
c) rezervarea a de octeti pentru variabila reala x
Secventa de program
int xamiani,ms3,ns2;
a) este corecta deoarece dimensiunile m si n ale matricii sunt cunoscute
b) este gresita deoarece m si n trebuia sa fie declarati inainte de x
c) este gresita deoarece la declarare in main(), dimensiunile unui tablou trebuie sa fie constante si nu variabile
Secventa de program
int ya10i;
ya10is7;
a) atribuie componentei ya10i a tabloului y valoarea
b) este gresita deoarece componentele tabloului sunt ya0i,ya1i,ya2i,,ya9i
c) este corecta deoarece componentele tabloului sunt ya1i,ya2i,,ya10i
In secventa de program
int xa3ia2i;
xa1,2is5;
a) atribuirea xa1,2is5 este echivalenta cu xa1ia2is5
b) atribuirea xa1,2is5 este corecta sintactic si inseamna xa2i
Urmatoarele trei declaratii ale tabloului x
int xa6i;
int xa3ia2i;
int xa2ia3i;
a) sunt echivalente
b) nu sunt echivalente
In urma initializarii tabloului a
int aa3ia2isA1,2,3,4,5,6I;
componenta aa1ia0i are valoarea
a)
b)
c) alta valoare decat decat sau
Initializarea
int aa3ia2isA1,2,3,4,5,6I;
este echivalenta cu:
a) int aa3ia2isA
A1,2I,
A3,4I,
A5,6I,
I;
b) int aa3ia2isA
A1,4I,
A2,5I,
A3,6I,
I;
Initializarea
float xa2ia3isA1,2,3,4,5,6I;
este echivalenta cu
a) float xaiaisA1,2,3,4,5,6I;
b) float xaia3isA1,2,3,4,5,6I;
c) float xa2iaisA1,2,3,4,5,6I;
Secventa de program
int xa10i,i;
for(is1;i<s10;iSS)
scanf("%d",&xaii);
a) este gresita sintactic
b) nu initializeaza toate componentele vectorului x
c) produce eroare la executie
Secventa de program
char xais"abcd";
este echivalenta cu:
a) initializarea char xaisA'a','b','c','d'I;
b) initializarea char xa4isA'a','b','c','d'I;
c) initializarea char xaisA'a','b','c','d','t0'I;
Secventa de program
char xais"abcd";
putch(xa1i);
a) afiseaza caracterul 'a'
b) afiseaza caracterul 'b'
c) este gresita deoarece elementele dintr-un sir nu se pot referi indexat
Secventa de program
char xa20is"abcd";
printf("tn Lungimea siruluis%i",strlen(x));
afiseaza mesajul
a) Lungimea siruluis20
b) Lungimea siruluis4
c) Lungimea siruluis5
Secventa de program
char xais "rac";
char yais "arc";
printf("%d",strcmp(x,y));
afiseaza o valoare
a) egala cu zero
b) mai mica strict decat zero
c) mai mare strict decat zero
Secventa de program
char xais"ac";
char yais"ar";
strcat(x,y);
printf("tn %s",x);
afiseaza
a) acar
b) arac
In secventa de program
char xa20i;
xs"
atribuirea
xs"
a) este gresita
b) este gresita, iar copierea sirului "Ploiesti" in variabila x se realizeaza prin strcpy(x,"Ploiesti")
c) este corecta
Secventa de program
char xa20i;
gets(x);
puts(x);
afiseaza acelasi sir daca inlocuim gets(x); cu:
a) gets(&x);
b) scanf("%s",&x);
c) scanf("%s",x);
In secventa de program
int i;
char xa20is"xyzw";
puts(x);
apelul
puts(x);
poate fi inlocuit cu:
a) printf("tn %s",x);
b) for(is0;i<5;iSS)
putch(xaii);
RASPUNSURI
14.1-a 14.2-c 14.3-b 14.4-b 14.5-b
14.6-b 14.7-a 14.8-b 14.9-b 14.10-c
14.11-b 14.12-b 14.13-c 14.14-a 14.15-a, b
14.16-a, b, c 14.17-a, b
|