Sunteți pe pagina 1din 9

Valeriu Iorga

Programare n C / C++

8.7. iruri de caractere. O constant ir de caractere se reprezint intern printr-un tablou de caractere terminat prin caracterul nul \0, memoria alocat fiind lungimea irului + 1 (1 octet pentru caracterul terminator al irului ). Un tablou de caractere poate fi iniializat fr a-i specifica dimensiunea: char salut[]={B,o,n,j,o,u,r,!,\0}; sau mai simplu, specificnd irul ntre ghilimele: char salut[]=Bonjour! (tabloul este iniializat cu coninutul irului de caractere -se aloc 9 octei) Folosirea unui pointer la un ir de caractere iniializat nu copiaz irul, ci are urmtorul efect:

se aloc memorie pentru irul de caractere, inclusiv terminatorul nul la o adres fix de memorie se iniializeaz spaiul cu valorile constantelor caractere se iniializeaz pointerul Psalut cu adresa spaiului alocat

char *Psalut=Buna ziua!; (pointerul este iniializat s indice o constant ir de caractere) Aadar, n C nu exist operaia de atribuire de iruri de caractere (sau n general de atribuire de tablouri), ci numai atribuire de pointeri - atribuirea t=s nu copiaz un tablou, pentru aceasta se folosete funcia strcpy(t, s). Pentru a uura lucrul cu iruri de caractere, n biblioteca standard sunt prevzute o serie de funcii, ale cror prototipuri sunt date n fiierele <ctype.h> i <string.h>. n fiierul <ctype.h> exist o serie de funcii (codificate ca macroinstruciuni) care primesc un parametru ntreg, care se convertete n unsigned char, i ntorc rezultatul diferit de 0 sau egal cu 0, dup cum caracterul argument satisface sau nu condiia specificat: islower(c) isupper(c) isalpha(c) isdigit(c) isxdigit(c) isalnum(c) isspace(c) isgraph(c) isprint(c) iscntrl(c) ispunct(c) 1 1 1 1 1 1 1 1 1 1 1 dac dac dac dac dac dac dac dac dac dac dac c {a..z} c {A..Z} c {A..Z}{a..z} c {0..9} c {0..9}{A..F}{a..f} isalpha(c)||isdigit(c) c { ,\n,\t,\r,\f,\v} c este afiabil, fr spaiu c este afiabil, cu spaiu c este caracter de control isgraph(c) && !isalnum(c)

Conversia din liter mare n liter mic i invers se face folosind funciile: tolower(c) i toupper(c). Exemplul 19: Scriei o funcie care convertete un ir de caractere reprezentnd un numr ntreg, ntr-o valoare ntreag. Numrul poate avea semn i poate fi precedat de spaii albe. #include <ctype.h> int atoi(char *s) { int i, nr, semn; for(i=0; isspace(s[i]); i++) /*ignora spatii albe*/ ; semn=(s[i]==-1)?-1:1; /*stabilire semn*/ if(s[i]==+||s[i]==-) /*se sare semnul*/ i++;

Valeriu Iorga for(nr=0;isdigit(s[i]);i++) nr=10*nr+(s[i]-0); return semn*nr;

Programare n C / C++ /*conversie in cifra*/ /*si alipire la numar*/

Exemplul 20: { se se se se se }

Scriei o funcie care convertete un ntreg ntr-un ir de caractere n baza 10.

Algoritmul cuprinde urmtorii pai: extrage semnul numrului; extrag cifrele numrului, ncepnd cu cmps; transform n caractere i se depun ntr-un tablou; adaug semnul i terminatorul de ir; inverseaz irul;

void inversare(char[]); void itoa(int n, char s[]){ int j, semn; if((semn=n)<0) n=-n; j=0; do s[j++]=n%10+0; while ((n/=10)>0); if(semn<0) s[j++]=-; s[j]=\0; inversare(s); } void inversare(char s[]) { int i,j; char c; for(i=0,j=strlen(s)-1;i<j;i++,j--) c=s[i], s[i]=s[j], s[j]=c; } Exemplul 21: Scriei o funcie care convertete un ntreg fr semn ntr-un ir de caractere n baza 16. Pentru a trece cu uurin de la valorile cifrelor hexazecimale 0,1,15 la caracterele corespunztoare; 0,1,,a,,f, vom utiliza un tablou iniializat de caractere. static char hexa[]=0123456789abcdef; void itoh(int n, char s[]) { j=0; do { s[j++]=hexa[n%16]; while ((n/=16)>0); s[j]=\0; inversare(s); } Fiierul <string.h> conine prototipurile urmtoarelor funcii: char* strcpy(char* d,const char* s) copiaz irul s n d, inclusiv \0, ntoarce d char* strncpy(char* d,const char* s, copiaz n caractere din irul s n d, int n) completnd eventual cu \0, ntoarce d char* strcat(char* d,const char* s) concateneaz irul s la sfritul lui d,

Valeriu Iorga

Programare n C / C++

ntoarce d char* strncat(char* d,const char* s, concateneaz cel mult n caractere din irul s int n) la sfritul lui d, completnd cu \0, ntoarce d int strcmp(const char* d, compar irurile d i s, ntoarce const char* s) 1 dac d<s, 0 dac d==s i 1 dac d>s int stricmp(const char* d, compar irurile d i s (ca i strcmp()) const char* s) fr a face distincie ntre litere mari i mici int strncmp(const char* d, similar cu strcmp(), cu deosebirea c se const char* s, int n ) compar cel mult n caractere int strincmp(const char* d, similar cu strncmp(), cu deosebirea c nu const char* s, int n ) se face distincie ntre literele mari i mici char* strchr(const char* d,char c) caut caracterul c n irul d; ntoarce un pointer la prima apariie a lui c n d, sau NULL char* strrchr(const char* d,char c) ntoarce un pointer la ultima apariie a lui c n d, sau NULL char* strstr(const char* d, ntoarce un pointer la prima apariie a const char* s) subirului s n d, sau NULL char* strpbrk(const char* d, ntoarce un pointer la prima apariie a unui const char* s) caracter din subirul s n d, sau NULL int strspn(const char* d, ntoarce lungimea prefixului din d care const char* s) conine numai caractere din s int strcspn(const char* d, ntoarce lungimea prefixului din d care const char* s) conine numai caractere ce nu apar n s int strlen(const char* s) ntoarce lungimea lui s (\0 nu se numr) char* strlwr(char* s) convertete literele mari n litere mici n s char* strupr(char* s) convertete literele mici n litere mari n s void* memcpy(void* d, copiaza n octei din s n d; ntoarce d const void* s,int n) void* memmove(void* d, ca i memcopy, folosit daca s i d se const void* s,int n) ntreptrund void* memset(void* d,const int c, copiaz caracter c n primele n poziii din d int n) int memcmp(const void* d, compar zonele adresate de s i d const void* s,int n) char* strtok(const char* d, caut n d subirurile delimitate de caracterele const char* s) din s;primul apel ntoarce un pointer la primul subir din d care nu conine caractere din s urmtoarele apeluri se fac cu primul argument NULL, ntorcndu-se de fiecare dat un pointer la urmtorul subir din d ce nu conine caractere din s; n momentul n care nu mai exist subiruri, funcia ntoarce NULL Ca exerciiu, vom codifica unele din funciile a cror prototipuri se gsesc n <string.h>, scriindu-le n dou variante: cu tablouri i cu pointeri. Exemplul 22:Scriei o funcie avnd ca parametru un ir de caractere, care ntoarce lungimea sirului /*varianta cu tablouri*/

Valeriu Iorga int strlen(char *s) { int j; for(j=0; *d!=\0; d++) j++; return j; } /*varianta cu pointeri*/ int strlen(char *s) { char *p=s; while(*p) p++; return p-s; } Exemplul 23:Scriei o funcie care copiaz un ir de caractere s n d. /*varianta cu tablouri*/ void strcpy(char *d, char *s) { int j=0; while((d[j]=s[j])!=\0) j++; } /*varianta cu pointeri*/ void strcpy(char *d, char *s) { while((*d=*s)!=\0){ d++; s++; }

Programare n C / C++

Postincrementarea pointerilor poate fi fcut n operaia de atribuire deci: void strcpy(char *d, char *s){ while((*d++=*s++)!=\0) ; } Testul fa de \0 din while este redundant, deci putem scrie: void strcpy(char *d, char *s){ while(*d++=*s++) ; } Exemplul 24: Scriei o funcie care compar lexicografic dou iruri de caractere i ntoarce rezultatul 1, 0 sau 1 dup cum d<s, d==s sau d>s. /*varianta cu tablouri*/ int strcmp(char *d, char *s) { int j; for(j=0; d[j]==s[j]; j++) if(d[j]==\0) return 0; return d[j]-s[j]; } /*varianta cu pointeri*/ int strcmp(char *d, char *s) { for(; *d==*s; d++,s++)

Valeriu Iorga if(*d==\0) return 0; return *d-*s;

Programare n C / C++

Exemplul 25: Scriei o funcie care determin poziia (indexul) primei apariii a unui subir s ntr-un ir d. Dac s nu apare n d, funcia ntoarce 1. int strind(char d[], char s[]){ int i,j,k; for (i=0; d[i]; i++) { for (j=i,k=0; s[k] && d[j]==s[k]; j++,k++) ; if (k>0 && s[k]==\0) return i; } return 1; } 8.8. Funcii de intrare / ieire relative la iruri de caractere. Pentru a citi un ir de caractere de la intrarea standard se folosete funcia gets() avnd prototipul: char *gets(char *s); Funcia gets() citete caractere din fluxul standard de intrare stdin n zona de memorie adresat de pointerul s. Citirea continu pn la ntlnirea sfritului de linie. Marcajul de sfrit de linie nu este copiat, n locul lui fiind pus caracterul nul (\0). Funcia ntoarce adresa zonei de memorie n care se face citirea (adic s) sau NULL, dac n locul irului de caractere a fost introdus marcajul de sfrit de fiier. Pentru a scrie un ir de caractere terminat prin caracterul NULL, la ieirea standard stdout, se folosete funcia: int puts(char *s); Caracterul terminator nu este transmis la ieire, n locul lui punndu-se marcajul de sfrit de linie. Caracterele citite ntr-un tablou ca un ir de caractere (cu gets()) pot fi convertite sub controlul unui format folosind funcia: int sscanf(char *sir, char *format, adrese_var_formatate); Singura deosebire fa de funcia scanf() const n faptul c datele sunt preluate dintr-o zon de memorie, adresat de primul parametru (i nu de la intrarea standard). Exemplul 26: Scriei o funcie care citete cel mult n numere reale, pe care le plaseaz ntr-un tablou x. Funcia ntoarce numrul de valori citite. Vom citi numerele ntr-un ir de caractere s. De aici vom extrage n mod repetat cte un numr, folosind funcia sscanf() i l vom converti folosind un format corespunztor. Ciclul se va repeta de n ori, sau se va opri cnd se constat c s-au terminat numerele. Vom scrie funcia n 2 variante: folosind tablouri sau folosind pointeri. /* varianta cu tablouri */ int citreal(int n, double x[]) { char s[255]; int j; double y; for (j=0; j<n; j++) { if(gets(s)==NULL)

Valeriu Iorga return j; if(sscanf(s,%lf,&y)!=1) /*conversie ]n real*/ break; /*s-au terminat numerele*/ x[j]=y; } return j; } /* varianta cu pointeri */ int citreal(int n, double *px) { char s[255]; int j=0; double y; double *p=px+n; while(px<p) { if(gets(s)==NULL) return j; if(sscanf(s,%lf,&y)!=1) /*conversie in real*/ break; /*s-au terminat numerele*/ *px++=y; j++; } return j; } 8.9. Tablouri de pointeri. Un tablou de pointeri este definit prin: tip *nume[dimensiune];

Programare n C / C++

Exemplul 27: S se sorteze o list de nume. Folosirea unui tablou de iruri de caractere este lipsit de eficien, deoarece irurile sunt de lungimi diferite. Vom folosi un tablou de pointeri la iruri de caractere. Prin sortare nu se vor schimba irurile de caractere, ci pointerii ctre acestea.
Vasile Constantin Ion Vasile Constantin Ion

Citirea irurilor de caractere presupune:

rezervarea de spaiu pentru iruri

iniializarea tabloului de pointeri cu adresele irurilor Pentru rezervarea de spaiu se folosete funcia char *strdup(char *s); care: salveaz irul indicat de s ntr-o zon de memorie disponibil, alocat dinamic ntoarce un pointer ctre zona respectiv sau NULL. Citirea numelor este terminat prin EOF. Funcia de citire ntoarce numrul de linii citite:

int citire(char *tabp[]){ int j=0; char tab[80]; while(1) {

Valeriu Iorga gets(tab); if(tab==NULL) break; tabp[j]=strdup(tab); } return j; }

Programare n C / C++

Sortarea o vom realiza cu algoritmul bulelor: dac irul de nume ar fi ordonat, atunci dou nume consecutive s-ar afla n relaia < sau ==. Vom cuta aadar relaiile >, schimbnd de fiecare dat ntre ei pointerii corespunztori (schimbare mai eficient dect schimbarea irurilor). Se fac mai multe parcurgeri ale listei de nume; la fiecare trecere, o variabil martor sortat, iniializat la 1 este pus pe 0, atunci cnd se interschimb doi pointeri. Lista de nume va fi sortat n momentul n care n urma unei parcurgeri a listei se constat c nu s-a mai fcut nici o schimbare de pointeri. void sortare(char *tp[], int n) { int j, sortat; char *temp; for(sortat=0; !sortat;){ sortat=1; for(j=0;j<n-1;j++) if(strcmp(tp[j],tp[j+1])>0){ temp=tp[j], tp[j]=tp[j+1], tp[j+1]=temp, sortat=0; } } } void afisare(char *tp[], int n){ int j; for (j=0; j<n; j++) if(tp[j]) puts(tp[j]); } void main(void) { int n; char *nume[100]; n=citire(nume); sortare(nume,n); afisare(nume,n); } Exemplul 28: Definii o funcie, avnd ca parametru un ntreg, reprezentnd o lun, care ntoarce (un pointer la) numele acelei luni char *nume_luna(int n) { static char *nume[]={Luna inexistenta,Ianuarie, Februarie,Martie,Aprilie,Mai,Iunie, Iulie,August,Septembrie,Octombrie, Noiembrie,Decembrie}; return(n<1||n>12)?nume[0]:nume[n]; } 8.10. Probleme propuse (iruri de caractere).

Valeriu Iorga

Programare n C / C++

1. Scriei o funcie C care stabilete dac un ir de caractere dat ca parametru reprezint un palindrom. Pentru aceasta este necesar ca primul i ultimul caracter din irul de caractere s fie egale, al doilea i penultimul, .a.m.d. Funcia ntoarce 1 dac irul de caractere este un palindrom i 0 n caz contrar. 2. Un text citit de pe mediul de intrare reprezint un program C. S se copieze pe mediul de ieire, pstrnd structura liniilor, dar suprimnd toate comentariile. 3. Dintr-un text, citit de pe mediul de intrare, s se separe toate cuvintele, plasndu-le ntr-un vector cu elemente iruri de caractere de lungime 10 (cuvintele mai scurte se vor completa cu spaii libere, iar cele mai lungi se vor trunchia la primele 10 caractere. Se vor afia elemenetele acestui tablou, cte 5 elemente pe o linie, separate ntre ele prin 2 asteriscuri. 4. Dintr-un text citit de pe mediul de intrare s se afieze toate cuvintele care conin cel puin 3 vocale distincte. 5. Scriei un program care citete i afieaz un text i determin numrul de propoziii i de cuvinte din text. Fiecare propoziie se termin prin punct, iar n interiorul propoziiei cuvintele sunt separate prin spaii, virgul sau liniu. 6. De pe mediul de intrare se citete un text format din cuvinte separate prin spaii libere. S se afieze acest text la ieire, pstrnd structura liniilor i scriind n dreptul liniei cel mai lung cuvnt din linie. Dac mai multe cuvinte au aceeai lungime maxim, va fi afiat numai primul dintre ele. 7. Scriei un program care citete de la intrarea standard cuvinte, pn la ntlnirea caracterului punct i afieaz cte un cuvnt pe o linie, urmat de desprirea acestuia n silabe. Se utilizeaz urmtoarele reguli de desprire n silabe:

o consoan aflat ntre dou vocale trece n silaba a doua n cazul a dou sau mai multe consoane aflate ntre dou vocale, prima rmne n silaba ntia, iar celelalte trec n silaba urmtoare. Nu se iau n considerare excepiile de la aceste reguli.

8. S se transcrie la ieire un text citit de la intrarea standard, suprimnd toate cuvintele de lungime mai mare ca 10. Cuvintele pot fi separate prin punct, virgul sau spaii libere i nu se pot continua de pe o linie pe alta. 9. Scriei un program care citete de la intrarea standard un text terminat prin punct i l transcrie la ieirea standard, nlocuind fiecare caracter * printr-un numr corespunztor de spaii libere care ne poziioneaz la urmtoarea coloan multiplu de 5. Se va pastra structura de linii a textului. 10. Scriei un program pentru punerea n pagin a unui text citit de la intrarea standard. Se fac urmtoarele precizri:

cuvintele sunt separate ntre ele prin cel puin un spaiu un cuvnt nu se poate continua de pe o linie pe alta lungimea liniei la ieire este N lungimea maxim a unui cuvnt este mai mic dect N / 2 In textul rezultat se cere ca la nceput de linie s fie un nceput de cuvnt, iar sfritul de linie s coincid cu sfritul de cuvnt. n acest scop, spaiile se distribuie uniform i simetric ntre cuvinte. Face excepie doar ultima linie. Caracterul punct apare doar la sfrit de text.

Valeriu Iorga

Programare n C / C++

11. Modificai funcia strind() astfel nct s ntoarc n locul indexului un pointer i NULL n caz c c subirul s nu apare n irul destinaie d (adic scriei funcia strstr() ).

S-ar putea să vă placă și