Documente Academic
Documente Profesional
Documente Cultură
Curs Siruri Caractere
Curs Siruri Caractere
Programare n C / C++
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
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
Programare n C / C++
for(nr=0;isdigit(s[i]);i++)
nr=10*nr+(s[i]-0);
return semn*nr;
Exemplul 20:
/*conversie in cifra*/
/*si alipire la numar*/
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)
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
Programare n C / C++
Valeriu Iorga
Programare n C / C++
if(*d==\0)
return 0;
return *d-*s;
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
Programare n C / C++
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];
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
Valeriu Iorga
Programare n C / C++
gets(tab);
if(tab==NULL)
break;
tabp[j]=strdup(tab);
}
return j;
}
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++
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:
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() ).