En los títulos y los textos vais a encontrar unas cuantas citaciones cinematográficas (y si, soy un cinéfilo). Si no os interesan podéis fingir no verlas, ya que no son fundamentales para la comprensión de los post...

Este blog es la versión en Español de mi blog en Italiano L'arte della programmazione in C. Espero que mis traducciones sean comprensibles...

jueves, 16 de agosto de 2012

Oh my, my, strncpy()
cómo usar la strncpy() en C

Esperando alguna idea para un post más interesante (y, seguramente, más largo de preparar) me centraré un poco en la libc y, en particular, en la strncpy(), aunque, en realidad, la elección de la función es sólo un pretexto para dar algunas sugerencias de estilo, como veréis (si tenéis un lapsus de memoria con la libc, haced clic en el nombre de la función).

Escribir en C sin utilizar directamente las funciones de la biblioteca libc es bastante inusual, pero hay casos en que, entre las miles y miles de funciones disponibles, falta solo la que necesitas (o está ahí y no te has dado cuenta). Ejemplo: me ha pasado (es un caso real, lo juro) de tener que leer líneas repetitivas de un file y de tener que extraer sólo una parte de las líneas para copiarlo en un array, o sea, resumiendo:

- tenemos x líneas del tipo "... id = 123456;" (el número cambia en cada línea y en lugar de los puntos hay otras informaciones).
- el número puede ser más o menos largo: de 1 a 8 caracteres.
- hay que extraer el numero, transformarlo en int y copiarlo en un array de int.

Bueno, obviamente hay muchas maneras de hacerlo, y uno podria ser empezar con identificar donde empieza el número y luego usar la strncpy()... pero el número no tiene longitud fija: entonces hay que obtener la longitud y luego usar la strncpy(). O, quizás, usar la strtok(), y así sucesivamente. Y el código se hace siempre más largo y ilegible: que bonito seria solucionarlo todo con una simple llamada a la strcnpy()!

Pero yo digo: quien dijo que si no hay ninguna función en libc que haga lo que yo necesito no puedo reescribirla yo? Estas funciones no son necesariamente misteriosas y indescriptibles. Por ejemplo, la strncpy() es una función muy sencilla, y volver a escribirla para mi propio uso es muy sencillo:

/* myStrncpy()
 * versión especial de la strncpy() que se para al primer ";" y copia max (n-1) char
 * asegurando un "\0" final
 */
char *myStrncpy(
    char         *dest,
    const char *src,
    size_t       n)
{
    size_t i;

    // copia src en dest (con stop a <n - 1> chars o al primer "\0" o al primer ";")
    for (i = 0; i < (n - 1) && src[i] != '\0' && src[i] != ';'; i++)
        dest[i] = src[i];

    // llena con "\0" los chars que quedan
    for ( ; i < n; i++)
        dest[i] = '\0';

    // devuelve un pointer a dest
    return dest;
}


Así, el flujo principal del programa hace una sola llamada a myStrncpy(), sin cosas raras, salvando elegancia y legibilidad. En otro file podemos poner la myStrncpy(), lista para su reutilización en otros proyectos (será parte de nuestra, personal, libc).

Hasta el próximo post.

1 comentario: