Lección 4 · 4 de 20
Cadenas a fondo · C
Trocee líneas con strtok, construya textos con snprintf sin desbordar el búfer y copie con strncpy de forma segura en C, con strchr y strstr.

`strtok` parte una línea en campos. La primera llamada recibe la cadena y los separadores (";"); las siguientes reciben NULL para seguir donde se quedó, hasta que devuelve NULL. Funciona escribiendo '\0' encima de cada separador: por eso line es un array modificable y, al terminar, line solo contiene "Ana Lopez". Nunca la use sobre una cadena literal.
`snprintf` escribe con formato, como printf, pero en un búfer y sin pasar nunca de su tamaño: siempre termina el texto con '\0'. Devuelve cuántos caracteres habría necesitado; si ese número es mayor o igual que sizeof badge, el texto se ha cortado, como le pasa a "Maximiliano Fernandez".
`strncpy` copia como mucho n caracteres, pero si el origen es más largo no añade el `'\0'` final. La forma segura es copiar sizeof code - 1 caracteres y poner el terminador a mano en la última posición. Así code queda en "IB3170".
`strchr` busca un carácter y `strstr`, una subcadena; las dos devuelven un puntero a lo encontrado o NULL. dash + 1 es la cadena que empieza justo después del primer guion: la ruta MAD-BCN.
strtok guarda su posición en una variable interna, así que no se pueden trocear dos cadenas a la vez. Para eso existe strtok_r en POSIX y strtok_s en Windows.
Código · main.c
#include <stdio.h>#include <string.h>int main(void) { // strtok splits a line into fields. It writes '\0' over each separator, // so it needs a modifiable array, never a string literal. char line[] = "Ana Lopez;Madrid;34;Engineer"; int i = 0; for (char *field = strtok(line, ";"); field; field = strtok(NULL, ";")) printf("Field %d: %s\n", i++, field); printf("line is now just \"%s\"\n", line); // snprintf never writes past the buffer and returns the length it needed. const char *names[] = {"Ana", "Maximiliano Fernandez"}; for (int k = 0; k < 2; k++) { char badge[16]; int needed = snprintf(badge, sizeof badge, "Hi, %s!", names[k]); printf("Badge \"%s\" needed %d chars: %s\n", badge, needed, needed < (int)sizeof badge ? "fits" : "truncated"); } // strncpy does not add '\0' when the source is too long: add it yourself. const char *flight = "IB3170-MAD-BCN"; char code[7]; strncpy(code, flight, sizeof code - 1); code[sizeof code - 1] = '\0'; printf("Flight code: %s (%zu chars)\n", code, strlen(code)); // strchr and strstr search inside a string and return a pointer. const char *dash = strchr(flight, '-'); printf("Route: %s, has MAD: %s\n", dash + 1, strstr(flight, "MAD") ? "yes" : "no"); return 0;}Salida · cc main.c -o main && ./main
Field 0: Ana Lopez Field 1: Madrid Field 2: 34 Field 3: Engineer line is now just "Ana Lopez" Badge "Hi, Ana!" needed 8 chars: fits Badge "Hi, Maximiliano" needed 26 chars: truncated Flight code: IB3170 (6 chars) Route: MAD-BCN, has MAD: yes
Para recordar
strtokmodifica la cadena: use un array, no un literal.snprintfnunca desborda y devuelve la longitud que necesitaba.- Tras
strncpy, ponga usted el'\0'final. strchrystrstrdevuelven un puntero oNULL.
Ejercicio
Trocee la línea "Madrid,Sevilla,,Bilbao" con strtok y fíjese en qué pasa con el campo vacío; después construya con snprintf una lista "Madrid / Sevilla / Bilbao" en un búfer de 20 caracteres y diga si se ha cortado.