// vectors de caràcters

Cadenes en C

Una cadena no és un tipus propi: és un vector de char acabat amb un caràcter especial. Això té conseqüències — i una bona col·lecció de funcions de <string.h> per treballar-hi.

Què és una cadena en C?

Una cadena és un vector de char amb un caràcter especial, '\0' (caràcter nul), just després de l'últim caràcter real. És així com C sap on acaba el text, ja que el vector en si pot tenir més espai reservat del que fa servir.

Declaració

char nom[20] = "Jordi";

Això reserva 20 caràcters, però només n'omple 6: 'J', 'o', 'r', 'd', 'i' i el '\0' final. Els altres 14 caràcters hi són reservats però no s'utilitzen.

Llegir-ne una del teclat

char nom[20];
scanf("%s", nom);              // s'atura al primer espai
fgets(nom, 20, stdin);         // admet espais; inclou el \n si hi cap

scanf("%s", ...) talla al primer espai (no serveix per a "Sant Cugat"). fgets és la forma recomanada: admet espais i, a més, no es passa mai de la mida que li indiques (evitant desbordaments de memòria).

Funcions de <string.h>

FuncióFa
strlen(s)retorna la llargada de s (sense comptar el '\0')
strcpy(dest, orig)copia orig a dest
strcat(dest, orig)enganxa orig al final de dest
strcmp(a, b)compara alfabèticament: 0 si iguals, <0 si a va abans, >0 si b va abans

Exemple

char nom[20] = "Jordi";
char salutacio[30] = "Hola, ";

printf("Llargada: %zu\n", strlen(nom));
strcat(salutacio, nom);
printf("%s!\n", salutacio);

salutacio ha de tenir prou espai reservat per acollir el seu propi contingut més el de nom: si no, strcat escriuria fora dels límits del vector — un error greu en C, que no sempre es nota a l'instant.

strlen() no retorna un int, sinó un size_t (un enter sense signe): per això fem servir %zu i no %d al printf. Compilar amb -Wall t'avisaria d'aquest detall si te n'oblidessis.

Funcions de <ctype.h>

Treballen amb un sol char, no amb cadenes senceres — útils dins d'un bucle que recorre caràcter a caràcter.

FuncióFa
isalpha(c)cert si c és una lletra
isdigit(c)cert si c és un dígit
isupper(c) / islower(c)cert si c és majúscula / minúscula
toupper(c) / tolower(c)retorna c convertit a majúscula / minúscula

Recórrer una cadena caràcter a caràcter

Com que una cadena és un vector, pots indexar-la amb [i] — i, com que no en guardes la llargada enlloc, la manera de saber quan parar és comprovar si has arribat al '\0'.

Exemple: comptar vocals

char paraula[20] = "programar";
int i = 0, comptador = 0;

while (paraula[i] != '\0') {
    if (paraula[i] == 'a' || paraula[i] == 'e' || paraula[i] == 'i' || paraula[i] == 'o' || paraula[i] == 'u') {
        comptador++;
    }
    i++;
}

No hi ha cap funció de la biblioteca estàndard que ja faci "compta les vocals": en C, aquest tipus de recorregut manual és el pa de cada dia. Compara-ho amb Python, on for lletra in paraula: ja ho fa tot sol, sense índexs ni '\0'.

Mira la cadena processar-se pas a pas

Al recorregut manual, fixa't en com cada caràcter es visita un per un fins trobar el '\0' final.

Funcions de string.h

Recorregut manual

Codi

Variables

NomValor

Cadena

Terminal

Pas 1 / 1

Problemes per resoldre

Sense solució ni comprovació automàtica: escriu el programa, compila'l (gcc programa.c -o programa) i prova'l amb els exemples. Les pistes són plegades perquè les obris només si les necessites.

1. Invertir una cadena

Escriu un programa que inverteixi una cadena fixa escrita al codi, sense fer servir cap funció que ja ho faci.

Original: Python
Invertida: nohtyP
Pistes

Primer troba la llargada amb strlen(). Després, amb dos índexs (esquerra des de 0, dreta des de llargada-1) que s'acosten, intercanvia els caràcters — el mateix patró que vas fer amb vectors d'enters.

Pots fer-ho en el mateix vector (in-place) o escriure el resultat en un vector nou; si ho fas en un de nou, no t'oblidis de posar-hi el '\0' final.

2. Comptar ocurrències d'una lletra

Demana una paraula i una lletra, i digues quantes vegades apareix aquella lletra a la paraula.

Paraula: anagrama
Lletra: a
Apareix 4 vegades
Pistes

Llegeix la paraula amb fgets (admet qualsevol lletra sense problemes) i la lletra amb scanf(" %c", &lletra).

Recorre la paraula amb el mateix patró de while (paraula[i] != '\0') de la teoria, comparant cada caràcter amb la lletra buscada.

3. És un palíndrom?

Demana una paraula i digues si és un palíndrom (es llegeix igual del dret que del revés), com "radar".

Paraula: radar
És un palíndrom
Pistes

No cal invertir-la de debò: amb dos índexs (esquerra i dreta, com a l'exercici 1) que s'acosten des dels dos extrems, compara paraula[esquerra] amb paraula[dreta] a cada pas. Si mai no coincideixen, ja no és un palíndrom.

Pots parar en el moment que trobis una diferència (per exemple, amb una variable indicadora que passi a fals), sense necessitat de comprovar la resta.

Exercicis d'autoavaluació

Aquests es generen amb valors nous a l'atzar i tenen solució comprovable.

—

Quina serà la sortida per terminal d'aquest programa?