8.9. Utilizarea tablourilor de pointeri la prelucrari de date de tip sir de caractere

2019/03/18 in Programare in C

Tablourile de pointeri pot fi utilizate pentru a prelucra succesiuni de siruri de caractere. Utilizari de acest fel s-au vazut deja in exercitiile din paragraful precedent (vezi 8.18. si 8.14.).

Intr-un program se intalnesc adesea siruri de caractere care se trateaza intr-un mod unitar. In acest caz, este util sa se defineasca un tablou de pointeri, fiecare element al sau fiind un pointer spre un astfel de sir de caractere.

Astfel de tablouri pot fi utilizate pentru a pastra sau avea acces la diferite denumiri, cuvinte cheie, mesaje de eroare etc.

De exemplu, pentru a pastra denumirile lunilor calendaristice se poate utiliza un tablou de 13 elemente.

Numim tpdl acest tablou. Elementul tpdl[1] este un pointer spre sirul de caractere "ianuarie", tpdl[2] este pointer spre sirul "februarie", etc. Ultimul element, tpdl[12] este pointer spre sirul de caractere "decembrie".

Primul element al tabloului nu pointeaza spre denumirea niciunei luni. De aceea, acest element poate avea ca valoare pointerul nul. O alta posibilitate este ca tpdl[0] sa pointeze spre un text de eroare, de exemplu "luna ilegala".

Daca p este un pointer spre un sir de caractere, atunci poate fi definit sau declarat ca pointer spre un sir de caractere printr-o constructie de forma: char *p = sir;

Sirul de caractere sir se pastreaza intr-o zona de memorie, iar lui p i se atribuie adresa de inceput a zonei respective.

In mod analog se pot initializa elementele tabloului tpdl folosind o definitie sau declaratie de forma:
char *tpdl[] = {
"luna ilegala", 
"ianuarie", 
"februarie", 
"martie", 
"aprilie", 
"mai", 
"iunie", 
"iulie", 
"august", 
"septembrie", 
"octombrie", 
"noiembrie", 
"decembrie", 
};

Prin aceasta constructie, elementul tpdl[i], pentru 1 <= i <= 12, este pointer spre sirul de caractere care denumeste luna calendaristica a i-a din an. De exemplu, apelul:

printf("%s\n", tpdl[1]);

afiseaza textul:

ianuarie

Exercitii:

8.19. Sa se scrie o functie care are ca parametru un intreg n si returneaza un pointer spre denumirea lunii calendaristice a n-a pentru 1 <= n <= 12 sau spre textul "luna ilegala" pentru n in afara intervalului.

Fie denluna numele acestei functii. Ea returneaza un pointer spre char, deci returneaza o data de tip char *. Deci antetul ei este: char *denluna(int n)

char *denluna(int n)
/* returneaza pointerul spre spre denumirea lunii */
{
static char *tpdl[] = {
"luna ilegala", 
"ianuarie", 
"februarie", 
"martie", 
"aprilie", 
"mai", 
"iunie", 
"iulie", 
"august", 
"septembrie", 
"octombrie", 
"noiembrie", 
"decembrie", 
};

return n < 1 || n > 12 ? tpdl[0] : tpdl[n];
}

8.20. Sa se scrie un program care citeste o data calendaristica scrisa sub forma:

zzllaaaa

o valideaza si o afiseaza sub forma:

zz luna aaaa

unde:

zz reprezinta ziua pe 2 cifre;
zz reprezinta numarul lunii pe 2 cifre;
aaaa reprezinta anul pe 4 cifre;
luna reprezinta denumirea lunii calendaristice.

Data citita se valideaza utilizand functia v_calend definita la exercitiul 6.5.

#include <stdio.h>
#include <stdlib.h>
#include "FUNCTIA092C.C";
#include "FUNCTIA103.C";

int nrzile[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

main()
{
  int zz, ll, aaaa;

  if(scanf("%2d %2d %4d", &zz, &ll, &aaaa) != 3) {
    printf("nu s-a tastat un intreg de 8 cifre\n");
    exit(1);
  }
  if(v_calend(zz, ll, aaaa) == 0) {
    printf("data calendaristica eronata\n");
    exit(1);
  }
  printf("%02d %s %4d\n", zz, denluna(ll), aaaa);
}

8.21. Sa se scrie o functie care din denumirea lunii calendaristice determina numarul ei.

Aceasta functie este inversa functiei denluna definita in exercitiul 8.19.

Functia are ca parametru un pointer spre denumirea lunii calendaristice. Folosind acest pointer, denumirea lunii se cauta cu ajutorul functiei strcmp pentru a stabili coincidenta ei cu unul din sirurile de caractere spre care pointeaza elementele tabloului tpdl. In cazul in care denumirea este eronata, functia returneaza valoarea zero.

int nrluna(char *denl)
/* returneaza numarul lunii din denumirea ei */
{
static char *tpdl[] = {
"", 
"ianuarie", 
"februarie", 
"martie", 
"aprilie", 
"mai", 
"iunie", 
"iulie", 
"august", 
"septembrie", 
"octombrie", 
"noiembrie", 
"decembrie", 
};
int i;

for(i=1; i <= 12; i++)
  if(strcmp(denl, tpdl[i]) == 0)
    return i;
  return 0;
}

8.22. Sa se scrie un program care citeste o data calendaristica tastata sub forma:

zz luna aaaa

si o afiseaza sub forma:

zz/ll/aaaa

daca este valida.

In aceste formate s-au utilizat notatiile:

zz reprezinta ziua pe 1-2 cifre;
zz reprezinta numarul lunii pe 1-2 cifre;
aaaa reprezinta anul pe 4 cifre;
luna reprezinta denumirea lunii calendaristice.

#include <stdio.h>
#include <stdlib.h>
#include "FUNCTIA092C.C";
#include "FUNCTIA104.C";

int nrzile[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

main()
{
  int zz, ll, aaaa;
  char dl[11]; /* pastreaza denumirea lunii calendaristice */

  if(scanf("%2d %10s %4d", &zz, dl, &aaaa) != 3) {
    printf("data calendaristica eronata\n");
    exit(1);
  }
  if((ll = nrluna(dl)) == 0) {
    printf("luna eronata\n");
    exit(1);
  }
  if(v_calend(zz, ll, aaaa) == 0) {
    printf("data calendaristica eronata\n");
    exit(1);
  }
  printf("%d/%d/%d\n", zz, ll, aaaa);
}

8.10. Tratarea parametrilor din linia de comanda