snprintf vs strcpy (etc.) en C

Para hacer la concatenación de cadenas, he estado haciendo strcpy, strncpy de char* buffers. Luego me enteré de la snprintf y amigos.

Deben me quedo con mi strcpy, strcpy + \0 terminación? O debo usar snprintf en el futuro?

strncpy está totalmente fuera de lugar aquí. strncpy no debe ser usado para limitar la longitud de la cadena a copiar. Esto no es lo que la función hace y esto no es lo que fue desarrollado para. La correspondiente contraparte para snprintf en este contexto sería strlcpy (aunque no es la norma).

OriginalEl autor monkeyking | 2010-04-09

7 respuestas

  1. 7

    Para la mayoría de propósitos dudo que la diferencia entre el uso de strncpy y snprintf es medible.

    Si hay cualquier formato involucrados tienden a pegarse a sólo snprintf en lugar de la mezcla en strncpy así.

    Me parece que esto ayuda a que el código de la claridad, y significa que usted puede utilizar la siguiente expresión para seguir la pista de dónde usted está en el buffer (evitando así la creación de un Shlemiel el Pintor algoritmo):

    char sBuffer[iBufferSize];
    char* pCursor = sBuffer;
    
    pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer),  "some stuff\n");
    
    for(int i = 0; i < 10; i++)
    {
       pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer),  " iter %d\n", i);
    }
    
    pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer),  "into a string\n");
    Sería aún más clara si se utiliza una sola llamada a snprintf. Y ser conscientes de que si el buffer no es lo suficientemente grande, snprintf devolverá el necesario tamaño de búfer (o un número negativo en caso de error), por lo que el incremento de los pCursor como que puede ser peligroso.
    Hacer un s/snprint/snprintf/ en el código. Además, tu ejemplo no tiene sentido. Yo seguiría a formateadores.
    huy, gracias fija el nombre de la función. Sí, es un tonto ejemplo, lo hizo un poco más útil.
    sí, lo sé, cualquiera de las necesidades que ha conocido límites en el tamaño de la cadena o algunos comprobación de errores.

    OriginalEl autor John Carter

  2. 6

    snprintf es más robusto si desea dar formato a la cadena. Si sólo desea concatenar, uso strncpy (no usar strcpy), ya que es más eficiente.

    OriginalEl autor yassin

  3. 3

    Todos *printf funciones de verificación de formato y ampliar su correspondiente argumento, por lo tanto es más lento que una simple strcpy/strncpy, que sólo copiar un número determinado de bytes de memoria lineal.

    Mi regla de oro es:

    • Uso snprintf siempre que el formato se necesita.
    • Palo a strncpy/memcpy cuando sólo se necesita una copia de un bloque de memoria lineal.
    • Puede usar strcpy siempre que usted sabe exatcly el tamaño de los búferes va a copiar. No use que si usted no tiene el control total sobre el tamaño de búferes.

    OriginalEl autor jweyrich

  4. 3

    sprintf tiene una muy útil valor de retorno que permite eficiente anexar.

    Aquí está el modismo:

    char buffer[HUGE] = {0}; 
    char *end_of_string = &buffer[0];
    end_of_string += sprintf( /* whatever */ );
    end_of_string += sprintf( /* whatever */ );
    end_of_string += sprintf( /* whatever */ );

    Usted consigue la idea. Esto funciona porque sprintf devuelve el número de caracteres que escribió para el buffer, por lo que el avance de su búfer de que muchas de las posiciones va a dejar que apunta a la '\0' al final de lo que se ha escrito hasta ahora. Así que cuando la mano de la actualización de la posición a la siguiente sprintf, se puede comenzar a escribir nuevos caracteres a la derecha allí.

    Contraste con strcpy, cuyo valor de retorno es necesario para ser inútil. Las manos de nuevo el mismo argumento que pasó. De manera anexa con strcpy implica atravesar toda la primera cadena buscando el final de la misma. Y, a continuación, añadiendo de nuevo con otro strcpy llamada implica atravesar toda la primera cadena, seguido por la 2ª cuerda, que ahora vive después de ella, buscando el '\0'. Un tercer strcpy volverá a recorrer las cadenas que ya se han escrito de nuevo. Y así sucesivamente.

    Así que para muchos pequeños anexa a un búfer muy grande, strcpy approches (O^n), donde n es el número de anexa. Que es terrible.

    Además, como han mencionado otros, que hagan cosas diferentes. sprintf puede ser utilizado para dar formato a los números, los valores de puntero, etc, en el búfer.

    Woops, me acabo de dar cuenta que le preguntó específicamente acerca de snprintf. El lenguaje puede todavía trabajar, pero también es necesario mantener un recuento de cómo unos personajes permanecen en el búfer. Entonces se convierte en written = snprintf(buf, remanining, ...); buf += written; remaining -= written;
    Se necesita cuidado especial con snprintf. Ver mi comentario a therefromhere la respuesta.

    OriginalEl autor janks

  5. 2

    Creo que no hay otra diferencia entre strncpy y snprintf.

    Pensar acerca de esto:

    const int N=1000000;
    char arr[N];
    strncpy(arr, "abce", N);

    Generalmente, strncpy establecerá el resto del búfer de destino ‘\0’. Esto va a costar mucho tiempo de CPU. Mientras que cuando se llame a snprintf,

    snprintf(a, N, "%s", "abce");

    dejará el búfer sin cambios.

    No sé por qué strncpy va a hacer eso, pero en este caso, voy a elegir snprintf en lugar de strncpy.

    OriginalEl autor gordon liu

  6. 1

    strcpy, strncpy, etc. sólo copias de cadenas a partir de una ubicación de memoria a otra. Pero, con snprint, usted puede hacer más cosas como el formato de la cadena. Copia de los números enteros en búfer, etc.

    Depende únicamente de su requisito. Si según tu lógica, strcpy & strncpy ya está trabajando para usted, no hay necesidad de saltar a snprintf.

    También, recuerde utilizar strncpy para una mejor seguridad sugeridas por otros.

    Yo sé lo que quieres decir, pero strncpy no está restringido a la lectura (o incluso de escribir) NUL cadenas terminadas.
    Sí, lo sé. Probablemente, yo no expresé mi respuesta correctamente. He editado. Gracias por señalándolo.

    OriginalEl autor Jay

  7. 1

    Como los otros punto de ya: no utilice strncpy.

    • strncpy no cero terminar en caso de truncamiento.
    • strncpy será cero-pad el búfer completo si la cadena es más corta que la de búfer. Si el buffer es grande, esto puede ser un rendimiento de drenaje.

    snprintf (por las plataformas POSIX) cero terminar. En Windows, sólo hay _snprintf, que no cero terminar, de modo que tome en cuenta.

    Nota: cuando se utiliza snprintf, utilice este formulario:

    snprintf(buffer, sizeof(buffer), "%s", string);

    lugar de

    snprintf(buffer, sizeof(buffer), string);

    El último es inseguro y – si la cadena depende de la entrada de usuario – puede conducir a la pila rompe, etc.

    OriginalEl autor Thomas Stuefe

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *