¿Por qué usar nuevas líneas finales en lugar de liderar con printf?

77

Escuché que debes evitar las nuevas líneas principales al usar printf . De modo que en lugar de printf("\nHello World!") debería usar printf("Hello World!\n")

En este ejemplo particular anterior no tiene sentido, ya que la salida sería diferente, pero considera esto:

printf("Initializing");
init();
printf("\nProcessing");
process_data();
printf("\nExiting");

comparado con:

printf("Initializing\n");
init();
printf("Processing\n");
process_data();
printf("Exiting");

No puedo ver ningún beneficio con las nuevas líneas finales, excepto que se ve mejor. ¿Hay alguna otra razón?

  

EDITAR:

     

Abordaré las votaciones cerradas aquí y ahora. No creo que esto pertenezca a Stack overflow, porque esta pregunta es principalmente sobre diseño. También diría que aunque pueden ser opiniones sobre este asunto, respuesta de Kilian Foth y la respuesta de cmaster prueba que efectivamente existen beneficios muy objetivos con un solo enfoque.

    
pregunta Broman 19.11.2018 - 08:10
fuente

8 respuestas

219

Una buena cantidad de E / S de terminal es line-buffered , por lo que al finalizar un mensaje con \ n puede estar seguro de que se mostrará de manera oportuna. Con una dirección \ n, el mensaje puede o no mostrarse a la vez. A menudo, esto significaría que cada paso muestra el mensaje de progreso del paso anterior , lo que provoca un final de confusión y una pérdida de tiempo cuando intenta comprender el comportamiento de un programa.

    
respondido por el Kilian Foth 19.11.2018 - 08:17
fuente
71

En los sistemas POSIX (básicamente cualquier linux, BSD, cualquiera que sea el sistema basado en código abierto que pueda encontrar), una línea se define como una cadena de caracteres que termina con una nueva línea \n . Esta es la suposición básica sobre la que se basan todas las herramientas de línea de comando estándar, que incluye (pero no se limita a) wc , grep , sed , awk y vim . Esta es también la razón por la que algún editor (como vim ) siempre agrega un \n al final de un archivo, y por qué los estándares anteriores de C requerían que los encabezados terminen con un carácter \n .

Por cierto: tener \n líneas terminadas hace que el procesamiento del texto sea mucho más fácil: sabes con seguridad que tienes una línea completa cuando tienes ese terminador. Y está seguro de que necesita mirar más caracteres si aún no ha encontrado ese terminador.

Por supuesto, esto está en el lado de entrada de los programas, pero la salida del programa se usa muy a menudo como entrada de programa nuevamente. Por lo tanto, su salida debe atenerse a la convención por el hecho de permitir la entrada sin problemas en otros programas.

    
respondido por el cmaster 19.11.2018 - 14:31
fuente
31

Además de lo que otros han mencionado, siento que hay una razón mucho más simple: es el estándar. Cada vez que se imprime algo en STDOUT, casi siempre se supone que ya está en una nueva línea y, por lo tanto, no es necesario que comience una nueva. También supone que la siguiente línea que se va a escribir actuará de la misma manera, por lo que termina de forma útil al comenzar una nueva línea.

Si imprime líneas de nueva línea interpoladas con líneas de nueva línea estándar, "terminará teniendo este aspecto:

Trailing-newline-line
Trailing-newline-line

Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line

Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line

... que probablemente no es lo que quieres.

Si solo usa las nuevas líneas iniciales en su código y solo lo ejecuta en un IDE, puede que salga bien. Tan pronto como lo ejecute en una terminal o introduzca el código de otras personas que escribirá en STDOUT junto con su código, verá una salida indeseable como la anterior.

    
respondido por el The Guy with The Hat 19.11.2018 - 21:13
fuente
17

Dado que las respuestas altamente votadas ya han dado excelentes razones técnicas por las que se deberían preferir las nuevas líneas finales, lo abordaré desde otro ángulo.

En mis opiniones, lo siguiente hace que un programa sea más legible:

  1. una alta relación señal-ruido (también conocida como simple pero no más simple)
  2. las ideas importantes son lo primero

A partir de los puntos anteriores, podemos argumentar que las nuevas líneas finales son mejores. Las nuevas líneas tienen un formato de "ruido" en comparación con el mensaje, el mensaje debe sobresalir y, por lo tanto, debe aparecer primero (el resaltado de sintaxis también puede ayudar).

    
respondido por el Alex Vong 19.11.2018 - 21:42
fuente
16

El uso de nuevas líneas finales simplifica las modificaciones posteriores.

Como un ejemplo (muy trivial) basado en el código del OP, suponga que necesita producir un resultado antes del mensaje "Inicializando", y que el resultado proviene de una parte lógica diferente del código, en un archivo fuente diferente.

Cuando ejecuta la primera prueba y encuentra que "Initializing" ahora se agrega al final de una línea de otra salida, tiene que buscar en el código para encontrar dónde se imprimió, y luego esperar que cambie "Initializing" a "\ nInicializar" no arruina el formato de otra cosa, en diferentes circunstancias.

Ahora considere cómo manejar el hecho de que su nueva salida es realmente opcional, por lo que su cambio a "\ nInicializar" a veces produce una línea en blanco no deseada al inicio de la salida ...

¿Establece una marca global ( shock horror ?? !!! ) que indica si hubo alguna salida anterior y la prueba para imprimir "Inicializando" con un encabezado opcional "\ n", o ¿genera el "\ n" junto con su salida anterior y deja a los lectores de códigos futuros preguntándose por qué esta "Inicialización" no tiene un "\ n" inicial como los demás mensajes de salida?

Si sale constantemente nuevas líneas finales, en el punto en el que sabe que ha llegado al final de la línea que debe terminarse, elude todos esos problemas. Tenga en cuenta que esto podría requerir una declaración de put ("\ n") al final de alguna lógica que genera una línea por pieza, pero el punto es que usted genera la nueva línea en el lugar más temprano en el código donde sabe. necesitas hacerlo, no en otro lugar.

    
respondido por el alephzero 19.11.2018 - 18:07
fuente
7
  

¿Por qué usar nuevas líneas finales en lugar de liderar con printf?

Muy similar a la especificación de C.

La biblioteca C define una línea como terminando con un carácter de nueva línea '\n' .

  

Una secuencia de texto es una secuencia ordenada de caracteres compuestos en líneas , cada línea consta de cero o más caracteres más un carácter de terminación de nueva línea. Si la última línea requiere un carácter de nueva línea de terminación está definida por la implementación. C11 §7.21.2 2

El código que escribe datos como líneas coincidirá con ese concepto de la biblioteca.

printf("Initializing"); // Write part of a line
printf("\nProcessing"); // Finish prior line & write part of a line
printf("\nExiting");    // Finish prior line & write an implementation-defined last line

printf("Initializing\n");//Write a line 
printf("Processing\n");  //Write a line
printf("Exiting");       //Write an implementation-defined last line

Re: la última línea requiere un carácter de terminación de nueva línea . Recomiendo escribir siempre un '\n' final en la salida y tolerar su ausencia en la entrada.

Corrector ortográfico

Mi corrector ortográfico se queja. Quizás tu también lo haga.

  v---------v Not a valid word
"\nProcessing"

 v--------v OK
"Processing\n");
    
respondido por el chux 21.11.2018 - 05:56
fuente
4

Las nuevas líneas iniciales a menudo pueden facilitar la escritura del código cuando hay condicionales, por ejemplo,

printf("Initializing");
if (jobName != null)
    printf(": %s", jobName);
init();
printf("\nProcessing");

(Pero como se ha señalado en otra parte, es posible que deba vaciar el búfer de salida antes de realizar cualquier paso que requiera mucho tiempo de CPU).

Por lo tanto, se puede hacer un buen caso para ambas formas de hacerlo, sin embargo, personalmente no me gusta printf () y usaría una clase personalizada para construir la salida.

    
respondido por el Ian 19.11.2018 - 14:09
fuente
2

Las nuevas líneas principales no funcionan bien con otras funciones de la biblioteca, en particular con puts() y perror en la Biblioteca estándar, pero también con cualquier otra biblioteca que pueda usar.

Si desea imprimir una línea escrita previamente (ya sea una constante o una ya formateada, por ejemplo, con sprintf() ), entonces puts() es la opción natural (y eficiente). Sin embargo, no hay forma de que puts() termine la línea anterior y escriba una línea sin terminar, siempre escribe el terminador de línea.

    
respondido por el Toby Speight 22.11.2018 - 00:24
fuente

Lea otras preguntas en las etiquetas