Por que usar novas linhas à direita em vez de liderar com printf?

77

Ouvi dizer que você deve evitar levar novas linhas ao usar printf . Então, em vez de printf("\nHello World!") , você deve usar printf("Hello World!\n")

Neste exemplo específico acima, não faz sentido, pois a saída seria diferente, mas considere isto:

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

comparado a:

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

Não consigo ver nenhum benefício com as novas linhas iniciais, exceto que parece melhor. Existe algum outro motivo?

EDIT:

I'll address the close votes here and now. I don't think this belong to Stack overflow, because this question is mainly about design. I would also say that although it may be opinions to this matter, Kilian Foth's answer and cmaster's answer proves that there are indeed very objective benefits with one approach.

    
por Broman 19.11.2018 / 08:10
fonte

8 respostas

219

Uma boa quantidade de terminais de E / S é line-buffered , portanto, ao finalizar uma mensagem com \ n, você pode ter certeza de que ela será exibida em tempo hábil. Com um entrelinha \ n, a mensagem pode ou não ser exibida de uma só vez. Freqüentemente, isso significaria que cada etapa exibe a mensagem de progresso da etapa anterior , que não causa confusão e desperdiça tempo quando você tenta entender o comportamento de um programa.

    
por 19.11.2018 / 08:17
fonte
71

Em sistemas POSIX (basicamente qualquer linux, BSD, qualquer sistema baseado em código aberto que você possa encontrar), uma linha é definida como uma cadeia de caracteres que é terminada por uma nova linha \n . Essa é a suposição básica sobre a qual todas as ferramentas de linha de comando padrão se baseiam, incluindo (mas não se limitando a) wc , grep , sed , awk e vim . Esta também é a razão pela qual alguns editores (como vim ) sempre adicionam \n no final de um arquivo, e por que os padrões anteriores de C requeriam que os cabeçalhos terminassem com um caractere \n .

Btw: Ter \n linhas terminadas torna o processamento de texto muito mais fácil: você sabe com certeza que tem uma linha completa quando tiver esse terminador. E você sabe com certeza que precisa ver mais personagens se ainda não encontrou o terminador.

Naturalmente, isso está no lado de entrada dos programas, mas a saída do programa é usada com frequência como entrada de programa novamente. Portanto, sua saída deve se ater à convenção para permitir a entrada contínua em outros programas.

    
por 19.11.2018 / 14:31
fonte
31

Além do que outros mencionaram, sinto que há uma razão muito mais simples: é o padrão. Sempre que algo é impresso no STDOUT, quase sempre assume que já está em uma nova linha e, portanto, não precisa iniciar um novo. Também supõe que a próxima linha a ser escrita funcionará da mesma maneira, por isso, termina de maneira útil iniciando uma nova linha.

Se você gerar linhas de nova linha intercaladas com linhas padrão de traçado de linha, "terminará assim:

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 presumivelmente não é o que você quer.

Se você usar apenas novas linhas de destaque em seu código e só executá-lo em um IDE, ele poderá ficar bem. Assim que você executá-lo em um terminal ou introduzir código de outras pessoas que irá gravar em STDOUT ao lado de seu código, você verá uma saída indesejável como acima.

    
por 19.11.2018 / 21:13
fonte
17

Como as respostas altamente aprovadas já deram excelentes razões técnicas para que as novas linhas sejam preferidas, vou abordá-las de outro ângulo.

Em minhas opiniões, os seguidores tornam um programa mais legível:

  1. uma alta relação sinal-ruído (também conhecida como simples, mas não mais simples)
  2. ideias importantes vêm em primeiro lugar

Dos pontos acima, podemos argumentar que as novas linhas são melhores. As novas linhas estão formatando "ruído" quando comparadas à mensagem, a mensagem deve se destacar e, portanto, deve vir em primeiro lugar (o realce de sintaxe também pode ajudar).

    
por 19.11.2018 / 21:42
fonte
16

O uso de novas linhas iniciais simplifica modificações posteriores.

Como exemplo (muito trivial) baseado no código do OP, suponha que você precise produzir alguma saída antes da mensagem "Initializing", e essa saída vem de uma parte lógica diferente do código, em um arquivo de origem diferente.

Quando você executar o primeiro teste e encontrar "Inicializando" agora está anexado ao final de uma linha de alguma outra saída, você tem que pesquisar o código para encontrar onde foi impresso, e então espere mudar "Inicializando" para "\ nInicializando" não estraga o formato de outra coisa, em circunstâncias diferentes.

Agora, considere como é possível lidar com o fato de que sua nova saída é realmente opcional, portanto, sua mudança para "\ nInicializando" às vezes produz uma linha em branco indesejada no início da saída ...

Você define um sinalizador global ( shock horror ?? !!! ) informando se houve algum resultado precedente e o testa para imprimir "Inicializando" com um líder opcional "\ n" ou você produz o "\ n" junto com sua saída anterior e deixa os futuros leitores de código perguntando por que este "Initializing" não tem um "\ n" como todas as outras mensagens de saída fazem?

Se você gerar consistentemente novas linhas finais, no ponto em que você sabe que chegou ao fim da linha que precisa ser encerrada, você evita todos esses problemas. Note que isso pode requerer uma instrução puts ("\ n") separada no final de alguma lógica que produza uma linha peça por peça, mas o ponto é que você emite a nova linha no lugar mais antigo no código onde você sabe você precisa fazer isso, não em outro lugar.

    
por 19.11.2018 / 18:07
fonte
7

Why use trailing newlines instead of leading with printf?

Corresponda de perto as especificações C.

A biblioteca C define uma linha como terminando com um caractere de nova linha '\n' .

A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. C11 §7.21.2 2

O código que grava dados como linhas corresponderá a esse conceito da 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: última linha requer um caractere de nova linha de terminação . Eu recomendaria sempre escrever uma% final% co_de na saída e tolerar sua ausência na entrada.

Verificação ortográfica

Meu corretor ortográfico reclama. Talvez você também o faça.

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

 v--------v OK
"Processing\n");
    
por 21.11.2018 / 05:56
fonte
4

As novas linhas iniciais geralmente facilitam a gravação do código quando existem condicionais, por exemplo,

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

(Mas, como foi observado em outro lugar, você pode precisar liberar o buffer de saída antes de executar qualquer etapa que consome muito tempo da CPU).

Assim, um bom argumento pode ser feito para ambas as maneiras de fazê-lo, no entanto pessoal eu não gosto de printf () e usaria uma classe personalizada para construir a saída.

    
por 19.11.2018 / 14:09
fonte
2

As novas linhas iniciais não funcionam bem com outras funções da biblioteca, principalmente puts() e perror na Biblioteca Padrão, mas também qualquer outra biblioteca que você provavelmente usará.

Se você quiser imprimir uma linha pré-escrita (constante ou já formatada - por exemplo, com sprintf() ), então puts() é a escolha natural (e eficiente). No entanto, não há como puts() terminar a linha anterior e escrever uma linha não terminada - ela sempre escreve o terminador de linha.

    
por 22.11.2018 / 00:24
fonte

Tags