Limbaje de programare: Tablouri, șiruri, pointeri

Repetăm mai jos câteva tipare simple care trebuie stăpânite pentru rezolvarea unor probleme cu tablouri, șiruri, pointeri.

Parcurgerea unui tablou

Secvențele de cod de mai jos presupun existența unui tablou a de dimensiune size:
de exemplu primit ca parametru în funcție: void f(double a[], unsigned size)
sau declarat: const int size = 10; /* sau altă valoare */ double a[size];

Alocarea dinamică a unui tablou

Alocăm dinamic un tablou dacă creăm un tablou într-o funcție și avem nevoie de el după încheierea funcției; în acest caz funcția trebuie să transmită în afară adresa tabloului (de exemplu ca valoare returnată).
Mai alocăm dinamic un tablou (chiar când e folosit doar în funcție) când tabloul e mare, și din acest motiv nu dorim să fie pe stivă (unde se pun variabilele locale).

Un tablou de n elemente de tipul tip se alocă cu apelul
malloc(n * sizeof(tip))
. Valoarea returnată se atribuie unui pointer de tipul tip * și se folosește doar după ce s-a verificat că nu e NULL (alocarea a avut succes) . Un exemplu de funcție care adună doi vectori de reali de aceeași dimensiune și returnează adresa vectorului creat:

double *addvect(double a[], double b[], unsigned len)
{
  double *c = malloc(len * sizeof(double));
  if (c)	// c e folosit doar dacă e nenul
    for (int i = len; i--; )	// un pointer poate fi folosit cu indici [i]
      c[i] = a[i] + b[i];	// ca un tablou (numele tabloului e adresa lui)
  return c;
}

Parcurgerea unui șir de caractere

Un șir de caractere se parcurge la fel ca și un tablou, cu un indice, sau cu un pointer. Un șir de caractere se termină cu caracterul '\0' deci parcurgerea se face cât timp caracterul curent e nenul.
void parcurge(char *s)
{
  for (int i = 0; s[i]; ++i) {
    /* fa ceva cu caracterul curent s[i] */
  }
  for (char *p = s; *p; ++p) {
    /* fa ceva cu caracterul curent *p */
  }
}
Dacă sirul de caractere e dat printr-un pointer (și nu adresa constantă de început a unui tablou), și ulterior în acea funcție nu mai avem nevoie de adresa de început a șirului, putem parcurge șirul chiar cu pointerul dat:
char *strchr(const char *s, int c)	// cauta caracterul c in sirul s
{
  for (; *s; ++s)		// parcurge cat timp *s e nenul
    if (*s == c) return s;	// returneaza adresa unde a fost gasit
  return NULL;			// altfel returneaza NULL: nu a fost gasit
}

Alocarea dinamică a unui șir de caractere

Alocarea șirurilor de caractere se face după aceleași reguli ca și orice alocare de tablou. În acest caz particular: Un caz comun este cel în care dorim să facem o copie a unui șir (de exemplu pentru că șirul se află într-un tablou static care urmează a fi refolosit / suprascris). (O funcție strdup care face acest lucru nu e definită în standardul C, dar există în standardul POSIX și în multe biblioteci).
char *strdup(char *s)
{
  char *p = malloc(strlen(s) + 1);
  if (p) strcpy(p, s);
  return p;
}

Marius Minea
Last modified: Tue Dec 4 16:30:00 EET 2012