In limbajul C++ nu exista tipul de date sir de caractere (string), asa cum exista in alte limbaje de programare (Visual Basic, Turbo Pascal etc.), ele se declara ca tablouri de tip char. Spre exemplu, declaratia:
char a[10], b[3];
defineste doua tablouri unidimensionale (vectori) a si b de tip char avand 10 si respectiv 3 componente.
Ca la orice vector, numele arre semnificatia de adresa nemodificabila catre prima componenta (cea de ind 818h78i ice 0). La declarare se poate face si initializare, respectand regulile de de initializare ale tablourilor. De exemplu, urmatoarea declaratie:
char a[3] = ;
int i, j;
/* Adresarea cu un singur indice */
printf('Varianta In');
for (i = 0; i < 7; i++)
printf('%sn', zile[i]);
/* Adresarea cu doi indici */
printf('Varianta IIn');
for (i = 0; i < 7; i++)
/* Afisarea primei litere a fiecarei zile */
for (i = 0; i < 7; i++)
printf('%cn', zile[i][0]);
Rezolvarea aceleeasi probleme folosind pointeri evidentiaza si mai pregnat tratarea ca entitate distincta a fiecarui sir, a carei adresa va fi continuta intr-un element al vectorului de pointeri pzile.
#include <stdio.h>
void main()
int i, j;
printf('Varianta In');
for (i = 0; i < 7; i++)
printf('%sn', pzile[i]);
printf('Varianta IIn');
for (i = 0;i < 7; i++)
for (i = 0; i < 7; i++)
printf('%cn', *pzile[i]);
Pentru realizarea operatiilor de I/E, limbajul C, prin descriptorii %c si %s in functiile scanf si printf, ofera o modalitate comoda de citire si afisare a caracterelor si sirurilor de caractere. Aceste functii au fost prezentate detaliat intr-o lectie anterioara si utilizate in toate exemplele folosite. Din aceste motive in continuare ne vom referi la alte functii ce se pot folosi pentru realizarea operatiilor de I/E.
Un inconvenient major al functiei scanf il constituie faptul ca, caracterele spatiu, Tab si New Line actioneaza implicit ca separatori si deci prin aparitia lor in sirul de intrare forteaza sfarsitul sirului, neputand fi citit intr-o singura variabila un text format din mai multe cuvinte.
Pe langa aceste functii, limbajul C pune la dispozitie si functii de I/E pentru un caracter si respectiv pentru siruri de caractere.
Functia getchar() asigura preluarea intr-o variabila de tip int sau char a unui caracter de la terminal; prototipul functiei se gaseste in fisierul stdio.h. Varianta getch() realizeaza acelasi lucru fara a returna si ecoul caracterului citit; in plus, la citirea unui caracter acesta este preluat imediat din zona tampon a tastaturii, fara a se astepta prezenta unui terminator (Enter). Prototipul functiei getch() se gaseste in fisierul conio.h. Echivalentele lor pentru iesire sunt functiile putchar() (prototipul in stdio.h) si respectiv putch() (are prototipul in fisierul conio.h). De exemplu, urmatoarea secventa de program asigura citirea si scrierea unui caracter:
int c;
c = getchar();
putchar(c);
S-a definit c ca fiind de tip int, datorita faptului ca functiile getchar si getch sunt declarate ca fiind de tip int, pentru a putea prelua in afara caracterelor obisnuite si pe cele care transmit doua coduri la apasare (spre exemplu tastele sageata) sau coduri asociate functiilor de fisier: New Line, EOF (Ctrl+Z) etc., necesare testarii unor conditii. Spre exemplu, urmatorul program copiaza din fisierul standard de intrare (stdin), pe fisierul satndard de iesire (stdout), caracter cu caracter, pana la intalnirea sfarsitului de fisier:
#include <stdio.h>
void main()
Caracterele speciale (Tab, Exc, Cr, FF, Backspace etc.) executa diferite functii la imprimare. Daca se doreste simpla lor afisare, fara a fi executate, simbolurile asocaite lor trebuie filtrate si transmise in conformitate ci conventiile limbajului C, ca siruri de caractere aferente secevntelor escape. Un astfel de filtru este realizat in programul urmator:
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
void main()
Programul asigura afisarea corespunzatoare a tuturor codurilor ASCII citite de la tastatura, fara ecou si fara a astepta terminator de introducere. In program s-a apelat o macrocomanda de clasificare, isprint, pentru a verifica apartenenta caracterului introdus (daca este sau nu tiparibil). Limbajul C++ pune la dispozitie mai multe macrocomenzi de clasificare, pentru a verifica apartenenta la o clasa a unui caracter. Toate aceste macrocomenzi (vezi tabelul urmator) se gasesc in fisierul ctype.h.
Macrocomanda |
Descriere |
isalnum(c) |
Verifica daca c este o litera (A la Z sau a la z) sau o cifra (0 la 9) |
isalpha(c) |
Verifica daca c este este o litera (A la Z sau a la z) |
isascii(c) |
Verifica daca byte-ul de ordin inferior al lui c este in intervalul 0 la 127(0x00--0x7F) |
iscntrl(c) |
Verifica daca c este un caracter de stergere sau un caracter de control obisnuit (0x7F sau 0x00 la 0x1F) |
isdigit(c) |
Verifica daca c este o cifra (0 la 9) |
isgraph(c) |
Verifica daca c este un caracter imprimabil, la fel ca isprint, cu expectia faptului ca spatiul este exclus |
islower(c) |
Verifica daca c este o litera mica (a la z) |
isprint(c) |
Verifica daca c este un caracter imprimabil (0x20 la 0x7E) |
ispunct(c) |
Verifica daca c este un caracter de punctuatie (iscntrl sau isspace) |
isspace(c) |
Verifica daca c este un spatiu, tab, retur de car (carriage return), linie noua (new line), tab vertical salt de pagina (formfeed) - 0x09 la 0x0D, 0x20 |
isupper(c) |
Verifica daca c este o litera mare (A la Z) |
isxdigit(c) |
Verifica daca c este o cifra hexazecimala (0 la 9, A la F, a la f) |
Fiecare macrocomanda este un predicat care returneaza o valoare diferita de zero pentru adevarat si o valoare egala cu 0 pentru fals.
Programul prezentat, folosind o structura de selectie multipla, imparte codurile ASCII in patru clase:
caractere imprimabile – pe care le afiseaza ca atare;
caractere de control – pe care le afiseaza ca doua caractere, din care primul este ^;
secvente escape – pe care le afiseaza conform conventiilor din limbajul C;
alte coduri – pe care le afiseaza sub forma secventelor escape in octal.
Pentru citirea si scrierea sirurilor de caractere limbajul C++ pune la dispozitie urmatoarele functiile gets si puts, precum si functiile sscanf si sprintf; care vor fi prezentate in continuare.
Functia gets citeste un sir de caractere de pe fisierul standard de intrare. Prototipul functiei se gaseste in fisierul stdio.h. Apelul functiei se realizeaza folosind sintaxa:
gets(sir
unde: sir – este tabloul de caractere in care se vor memora caracterele citite.
Observatii
Functia gets colecteaza de la fisierul standard de intrare (stdin) un sir de caractere terminat cu linie noua (Enter) si le stoceaza in variabila sir. Sirul de caractere citit poate sa contina caractere “spatii albe” (spatii, tab etc.).
Functia gets inlocuieste in variabila sir caracterul linie noua cu un caracter NUL (0).
Functia puts tipareste pe fisierul standard de iesire (stdout) un sir de caractere. Prototipul functiei se gaseste in fisierul stdio.h. Functia se apeleaza folosind sintaxa:
puts(sir
unde: sir – este tabloul de caractere care se va tipari la fisierul standard de iesire.
Functia puts copiaza sirul sir terminat cu un caracter NUL la fisierul standard de iesire (stdout) si adauga un caracter “linie noua”. Spre exemplu, programul urmator:
#include <stdio.h>
void main()
citeste siruri de caractere, le numara si la tastarea sfarsitului de fisier (CTRL+Z) afiseaza numarul de randuri citite.
Functiile sscanf si sprintf sunt analoage functiilor scanf si printf. Ele au la apelare un parametru suplimentar (primul) care indica adresa zonei de memorie in care se pot pastra caractere ale codului ASCII. Ceilalti parametrii sunt identici cu cei ai functiilor scanf si printf. Functiile au prototipurile in fisierul stdio.h.
Primul parametru al acestor functii poate fi numele unui tablou de tip char, deoarece un astfel de nume are ca valoare chiar adresa de inceput a zonei de memorie care ii este alocata.
Functia sscanf se apeleaza folosind urmatoara sintaxa:
sscanf(buffer format lista_argumente
unde:
buffer – adresa zonei de memorie in care se pastreaza datele convertite.
format - reprezinta un sir de caractere ce contine textul de afisat si specificatorii de format (asemanatori celor pentru functia printf);
lista_argumente - este formata dintr-unul sau mai multe argumente separate prin virgule. Fiecare argument din lista reprezinta adresa zonei de memorie unde se gasesc datele ce se vor converti. Adresa zonei de memorie se specifica, de regula, printr-o constructie de forma:
&nume_zona_memorie
Functia sprintf se apeleaza utilizand formatul urmator:
sprintf(buffer format lista argumente
unde:
buffer – adresa zonei de memorie in care se gasesc datele de convertit.
format - reprezinta un sir de caractere ce contine textul de afisat si specificatorii de format (asemanatori celor pentru functia printf);
lista_argumente - este formata dintr-unul sau mai multe argumente separate prin virgule. Fiecare argument din lista reprezinta zona de memorie unde se vor plasa datele convertite.
Functia sprintf se foloseste, ca si functia printf, pentru a realiza conversii ale datelor de diferite tipuri din formatele lor interne, in formatele externe, reprezentate prin succesiuni de caractere. Diferenta consta in aceea ca, respectivele caractere nu sunt transmise la terminalul standard, ci se pastreaza in zona de memorie definita de primul parametru al functiei sprintf. Ulterior ele pot fi afisate folosind functia puts. Din acest motiv, un apel al functiei printf poate fi inlocuit cu un apel al functiei sprintf urmat de un apeel al functiei puts. O astfel de inlocuire este utila atunci cand vrem sa afisam de mai multe ori aceleasi date. In acest caz se apeleaza functia sscanf o singura data pentru a formata datele din zona de memorie si apoi ele vor fi afisate ori de cate ori este necesaa, fara a mai face conversiile, folosind functia puts. Functia sprintf, ca si functia printf, returneaza numarul de caractere rezultat in urma conversiilor efectuate.
Functia sscanf realizeaza, ca si functia scanf, conversii din format extern in format intern. Deosebirea consta in faptul ca de data aceasta caracterele nu sunt cititedin zona tampon corespunzatoare tastaturii, ci ele provin dintr-o zona de memorie a carei adresa este definita de primul parametru al functiei sscanf. Aceste caractere pot proveni in zona respectiva din urma apelului functiei gets. In acest fel, apelul functiei scanf poate fi inlocuit printr-un apel al functiei gets urmat de un apel al functiei sscanf. De regula asemenea inlocuiri sunt utile atunci cand vrem sa eliminam erorile aparute la tastarea datelor.
Functia sscanf, ca si functia scanf, returneaza numarul campurilor convertite corect conform specificatorilor de format din apel.
Exercitii
Sa se scrie un program care citeste un intreg pozitiv de tip long, stabileste daca acesta este prim si afiseaza un mesaj corespunzator.
#include <stdio.h>
#include <stdlib.h>
/* Citeste un numar pozitiv de tip long, stabileste daca */
/* este un numar prim si afiseaza un mesaj corespunzator */
void main()
if (sscanf(tab,'%ld', &n) != 1 || n <= 0)
j = 0; // Ciclul se va intrerupe; numarul tastat este corect
}
while (j);
for (j = 1, i = 2; i * i <= n && j; i++)
if (n % i == 0) // Numarul nu este prim
j = 0;
printf('Numarul: %ld ', n);
if (j == 0)
printf('nu ');
printf('este primn');
Biblioteca standard a limbajului contine o serie de functii care permit operatii cu siruri de caractere. Majoritatea acestor functii au prototipul in fisierul string.h.
Inainte de a prezenta principalele functii de prelucrare a sirurilor de caractere, vom reaminti cateva dintre caracteristicile sirurilor de caractere:
Un sir de caractere se pastreaza intr-o zona de memorie organizata ca tablou unidimensional de tip char. Fiecare caracter se pastreaza pe cate un byte prin codul sau numeric.
Cel mai frecvent cod utilizat in reprezentarea interna a caracterelor este codul ASCII.
Dupa ultimul caracter al sirului se pastreaza caracterul NUL (‘0’).
Pentru a opera cu un sir de caractere se poate utiliza numele tabloului ale carui elemente au ca valori codurile caracterelor sirului respectiv sau pointeri variabili spre sirul respectiv de caractere.
Numele tabloului este considerat un pointer constant spre sirul respectiv.
Cele mai frecvente prelucrari asupra sirurilor de caractere sunt urmatoarele:
Determinarea lungimii sirurilor de carctere.
Copierea sirurilor de caractere.
Concatenarea sirurilor de caractere.
Compararea sirurilor de caractere.
Functiile standard prin care se realizeaza aceste operatii au fiecare un nume care incepe cu prefixul str (prescurtare de la string).
Lungimea unui sir de caractere se defineste prin numarul de caractere proprii care intra in compunerea sirului respectiv. Caracterul NUL este un caracter impropriu si el nu este considerat la determinarea lungimii unui sir de caractere. Prezenta acestui caracter este necesara, deoarece el indica terminarea sirului si la determinarea lungimii unui sir se numara caracterele sirului pana la intalnirea caracterului NUL.
Functia pentru determinarea lungimii unui sir de caractere se numeste strlen si apelarea ei se realizeaza folosind urmatorul format de apel:
strlen(sir
unde: sir reprezinta numele tabloului ce contine sirul de caractere a careui lungime se determina.
Exemple
char *const p = “Borland International”;
unsigned n;
n = strlen(p);
Lui n i se atribuie valoarea 21, care reprezinta numarul de caractere proprii din compunerea sirului referit de p.
char tab[] = “Acesta este un sir”;
int n;
n = strlen(tab);
Lui n i se atribuie valoarea 18.
int n;
n = strlen(“Acesta este un sir”);
Lui n i se atribuie aceeasi valoare ca si in exemplul anterior.
Pentru a copia un sir de caractere din zona de memorie in care se afla intr-o alta zona de memorie se foloseste functia strcpy. Apelarea functiei strcpy se realizeaza utilizand urmatorul format:
strcpy(destinatie sursa
unde:
destinatie reprezinta adresa zonei de memorie in care se vor copia caracterele;
sursa reprezinta adresa zonei de memorie in care se gasesc caracterele de copiat.
Atat sursa cat si destinatie pot fi nume de tablouri de tip char sau pointeri constanti catre zonele de memorie ce contin/vor contine caractere.
Functia strcpy copiaza sirul de caractere spre care refera sursa in zona de memorie a carei adresa de inceput este valoarea lui destinatie. Functia copiaza atat caracterele proprii sirului, cat si caracterul NUL de la sfarsitul sirului respectiv.
La revenire, functia returneaza adresa de inceput a zonei in care s-a transferat sirul, adica chiar valoarea lui destinatie.
Exemple
char tab[] = “Borland International”;
char sir[sizeof tab]; // Are acelasi numar de elemente ca si tab
strcpy(sir, tab);
char sir[100];
strcpy(sir, “Copiere sir de caractere”);
char *p = “Sir de caractere”;
char sir[100];
char *q;
q = strcopy(sir, p); // dupa copiere lui q i se atribuie adresa
// zonei in care s-a copiat sirul de caractere.
Pentru a copia cel mult n caractere se foloseste functia strncpy, care se apeleaza respectand urmatoarea sintaxa:
strcpy(destinatie sursa numar_caractere
unde:
destinatie reprezinta adresa zonei de memorie in care se vor copia caracterele;
sursa reprezinta adresa zonei de memorie in care se gasesc caracterele de copiat.
numar_caractere reprezinta numarul de caractere ce se vor copia.
Daca numar_caractere este mai mare decat lungimea sirului referit de sursa, atunci toate caracterele sirului respectiv se transfera in zona referita de destinatie.
Pentru concatenarea (unirea) a doua siruri limbajul C++ dispune de doua functii: strcat si strncat.
Concatenarea a doua siruri de caractere (adaugarea celui de-al doilea sir la sfarsitul primului sir) se realizeaza cu ajutorul functiei strcat. Formatul de apelare a functiei este:
strcat(destinatie sursa
unde:
destinatie este adresa zonei sirului de caractere la sfarsitul caruia se va adauga sirul concatenat;
sursa este adresa sirului ce se va aduaga.
Aceasta functie copiaza sirul de caractere referit de sursa, in zona de memorie ce urmeaza imediat dupa ultimul caracter propriu al sirului referit de destinatie. Se presupune ca zona referita de pointerul destinatie este suficienta pentru a pastra caracterele proprii celor doua siruri care se concateneaza, plus caracterul NUL, care termina sirul rezultat in urma concatenarii.
Functia strcat reurneaza valoarea pointerului destinatie.
Exemplu
char dest[] = “Limbajul C++“;
char sursa[] = “este C dezvoltat”;
strcat(dest, ‘ ‘); // Adauga la sfarsitul sirului dest un spatiu
strcat(dest, sursa); // Adauga textul din sursa dupa caracterul
// spatiu din sirul dest.
Functia strncat adauga la sfarsitul primului sir prmele n caractere din cel de-al doilea sir. Forma de apelare a functiei strncat este:
strncat(destinatie sursa nr_caractere
unde:
destinatie este adresa zonei sirului de caractere la sfarsitul caruia se vor adauga cele nr_caractere din sirul referit de sursa;
sursa este adresa sirului in care se gasesc caracterele ce se vor concatena cu sirul referit de destinatie;
nr_caractere este numarul de caractere din sirul referit de sursa ce se vor concatena cu sirul referit de destinatie.
Functia strncat concateneaza la sfarsitul sirului referit de destinatie, cel mult nr_caractere ale sirului referit de sursa. Daca nr_caractere este mai mare decat lungimea sirului referit de sursa, atunci se concateneaza intregul sir, altfel numai primele nr_caractere caractere.
Exemplu
char sir1[00]=”Limbajull E este mai bun decat “;
char sir2[] = “limbajul C++, care este un superset a lui C”;
strncat(sir1, sie2, 12);
Dupa revenirea din functie, tabloul sir1 contine :Limbajul E este mai bun decat Limbajul C++
Sirurile de caractere se compara folosind codurile ASCII ale caracterelor din compunerea lor.
Fie s1 si s2 doua tabouri unidimensionale de tip caracter utilizate pentru a pastra, fiecare, cate un sir de caractere. Rezultatul compararii celor doua siruri se determina dupa urmatoarele reguli:
Cele doua siruri sunt egale daca au lungimi egale si s1[i] = s2[i] pentru toate valorile posibile ale lui i.
Sirul s1 este mai mic decat s2, daca exista un indice i astfel incat:
s1[i] < s2[i]
si
s1[j] = s2[j] pentru j = 1, 2, …, i –1.
Sirul s1 este mai mare decat s2, daca exista un indice i astfel incat:
s1[i] > s2[i]
si
s1[j] = s2[j] pentru j = 1, 2, …, i –1.
Compararea sirurilor de caractere se realizeaza folosind urmatoarele functii: strcmp, strncmp, stricmp si strincmp.
Functia strcmp compara doua siruri de caractere si poate fi apelata folosind urmatoarea sintaxa:
strcmp(sir1 sir2
unde: sir1 si sir2 reprezinta pointeri catre zonele in care se gasesc caracterele celor doua siruri ce se vor compara.
Functia strcmp returneaza:
o valoare negativa daca sirul referit de pointerul sir1 este mai mic decat sirul referit de pointerul sir2;
zero daca sirul referit de pointerul sir1 este mai mic decat sirul referit de pointerul sir2;
o valoare pozitiva daca sirul referit de pointerul sir1 este mai mare decat sirul referit de pointerul sir2;
Sintaxa de apelare a functiei strncmp este:
strncmp(sir1 sir2 n
unde:
sir1 si sir2 reprezinta pointeri catre zonele in care se gasesc caracterele celor doua siruri ce se vor compara.
n reprezinta numarul maxim de caractere din ambele siruri ce se vor lua in considerare. Daca minimul dintre lungimile celor doua siruri este mai mic decat n, functia strncmp realizeaza aceeasi comparatie ca si functia strcmp.
Valorile returnate de functia strncmp este acelasi ca si in cazul functie strcmp.
Daca la compararea a doua siruri de caractere nu dorim sa se faca distinctie intre literele mari si mici, atunci se va utiliza funtia stricmp. Formatul de apelare este:
stricmp(sir1 sir2
unde: sir1 si sir2 reprezinta pointeri catre zonele in care se gasesc caracterele celor doua siruri ce se vor compara.
Valorile returnate de functia stricmp sunt aceleasi ca si in aczul functiei strcmp.
Functia strincmp este similara functiei strncmp, cu deosebirea ca la compararea sirurilor nu se face deosebire intre literele mari si mic. Formatul de apelare este:
strincmp(sir1 sir2 n
unde:
sir1 si sir2 reprezinta pointeri catre zonele in care se gasesc caracterele celor doua siruri ce se vor compara.
n reprezinta numarul maxim de caractere din ambele siruri ce se vor lua in considerare. Daca minimul dintre lungimile celor doua siruri este mai mic decat n, functia strncmp realizeaza aceeasi comparatie ca si functia strcmp.
Valorile returnate de functia strincmp este acelasi ca si in cazul functie strcmp.
Exercitii
a. Sa se scrie un program care citeste o succesiune de cuvinte si-l afiseaza pe cel mai lung dintre ele.
#include <stdio.h>
#include <string.h>
#define MAX 100
void main()
if (max) printf('%sn', cuv_max);
Observatii
Se presupune ca un cuvant are cel mult 100 caractere, sunt separate prin spatii si pentru terminare se tasteaza sfarsitul de fisier (Ctrl+Z);
Cuvantul citit se pastreaza in tabloul cuvant. Citirea se face utilizand spefificatorul de format %100s, care permite citirea a cel mult 100 caractere diferite de cele albe;
Dupa citire se determina lungimea sirului si se compara cu valoarea variabilei max, care pastreaza lungimea maxima curenta;
Daca lungimea cuvantului curent citit este mai mare decat lungimea maxima, atunci lui max i se atribuie aceasta valoare, iar cuvantul citi este copiat in cuv_max.
b. Sa se scrie un program care citeste o succesiune de cuvinte, le sorteaza in ordine crescatoare si apoi le afiseaza.
#include <stdio.h>
#include <string.h>
#define MAXS 30 // Numarul maxim de siruri
#define MAXC 25 // Numarul maxim de caractere dintr-un sir
void main()
printf('Sirurile ordonate alfabetic sunt:n');
for (i = 0; i < nr; i++)
printf('%sn', tabel[i]);
|