- Tot el que s'ha dit sobre els punters a taules és igualment aplicable als strings. Tot i això caldrà fer algunes puntualitzacions referents a la definició i còpia de strings. En primer lloc, la definició d'un punter a char no és un string. Com a molt és un punter a un vector de caràcters. És a dir, només per escriure: "char *s2;" no n'hi ha prou per definir un string, ja que així només definim l'espai de memòria per a un punter a caràcter.
- En segon lloc, no podem copiar strings només amb el signe '=' perquè són vectors; sí que es permet copiar l'adreça d'un vector de caràcters sobre una variable de tipus punter a char, però només es copia l'adreça!.
- En tercer i últim lloc, es pot accedir a un caràcter d'un string a través d'un punter a char seguit de l'índex del caràcter entre claudàtors, ja que correspon al mode d'adreçament punter base més desplaçament.
ex 3.6: PUTSTRI1.C mostra com es defineix un string de 10 caràcters, més un punter a char que apuntarà a aquest string (vector):
#include <stdio.h> #include <string.h> void main(void) { char s1[10]; /* vector de 10 caràcters */ char *s2; /* punter a string */ strcpy(s1,"sensual"); /* inicialitzo vector */ s2 = s1; /* inicialitzo punter */ s2[3] = 'x'; /* accés al vector a través del punter */ printf("%s\t%s\n",s1,s2); /* imprimeix strings (vector i punter) */ }
cex 3.2: El següent contraexemple mostra que no es pot accedir a un punter a char com si fos una cadena de caràcters, ja que no té espai reservat per als caràcters de la cadena (l'execució d'aquest programa pot ser catastròfica perquè accedeix a memòria a través d'un punter no inicialitzat!):
#include <stdio.h> #include <string.h> void main(void) { char *s1; strcpy(s1,"sensual"); printf("string 1: %s\n",s1); }
- De vegades es pot veure en alguns programes de C com es defineixen frases constants que s'imprimiran en algun moment, i que són assignades a punters a caràcter mitjançant l'autoinicialització. Aquestes cadenes es guarden en algun lloc de memòria cada cop que es carrega el programa, i el punter queda inicialitzat al principi de la cadena. No obstant això, el punter es pot canviar per a que apunti a alguna altra cadena.
ex 3.7: PUTSTRI2.C representa com assignar una cadena constant a un punter a char:
#include <stdio.h> void main(void) { char s1[10] = "sensual"; char *s2 = "senxual"; printf("string 2: %s\n",s2); s2 = s1; printf("string 2: %s\n",s2); }
- Moltes vegades necessitem llistes de missatges. Una forma d'emmagatzemar aquestes llistes és fer un vector de vectors de caràcter, és a dir, una matriu de caràcters. Per exemple, la llista dels noms dels mesos es podria introduir com un vector de 12 vectors de 9 chars cadascun (la longitud màxima que té "desembre", per exemple, i el caràcter fi de string):
char mes[12][9]; void inicialitzar_taules_mes(void) { strcpy(mes[0],"Gener"); strcpy(mes[1],"Febrer"); strcpy(mes[2],"Març"); strcpy(mes[3],"Abril"); : : }
ex 3.8: STRIMES1.C mostra com gràcies a l'autoinicialització en declarar les variables, podem introduir els noms dels mesos d'una forma molt més simple:
#include <stdio.h> char mesos[12][9] = {"Gener","Febrer","Març","Abril","Maig", "Juny","Juliol","Agost","Setembre", "Octubre","Novembre","Desembre" }; int diesmes[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; void main(void) { for(i=0; i<12; i++) printf("%s\t%d\n",mes[i],diesmes[i]); }
- El problema que sorgeix amb aquest mètode és que els strings són variables, mentre que el vector de vectors definirà una longitud fixa i màxima per a tots els strings. Per tant, si els strings són més curts estarem perdent bytes de memòria, mentre que si són més llargs no els podrem emmagatzemar:
- La solució passa per definir la llista de strings com un vector de punters a char, en el supòsit que tinguéssim totes les cadenes emmagatzemades a memòria de forma consecutiva (sense perdre cap byte), i els punters assignats al principi de cada cadena (la cadena s'acaba amb el caràcter sentinella).
ex 3.9: STRIMES2.C insereix a memòria les cadenes corresponents als noms dels mesos i inicialitza els punters del vector mesos quan el declara:
#include <stdio.h> char *mesos[12] = {"Gener","Febrer","Març","Abril","Maig", "Juny","Juliol","Agost","Setembre", "Octubre","Novembre","Desembre" }; int diesmes[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; void main(void) { for(i=0; i<12; i++) printf("%s\t%d\n",mes[i],diesmes[i]); }
- Editeu el fitxer EXERCI_3.C i substituïu els interrogants per les instruccions que implementin el que es demana en els comentaris adjunts. El resultat ha de ser:
a = 4.80 tf = ( 0.0, 0.0, 9.6, 0.0, 6.1, 0.0) m : 0.0 0.0 0.0 0.0 0.0 0.0 12.6 0.0 0.0 0.0 0.0 2.9