web-dev-qa-db-fra.com

Pourquoi utiliser des sauts de ligne au lieu de mener avec printf?

J'ai entendu dire que vous devriez éviter les sauts de ligne lors de l'utilisation de printf. Ainsi, au lieu de printf("\nHello World!"), vous devez utiliser printf("Hello World!\n")

Dans cet exemple particulier ci-dessus, cela n'a pas de sens, car la sortie serait différente, mais considérez ceci:

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

par rapport à:

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

Je ne vois aucun avantage avec les nouvelles lignes à la fin, sauf qu'il semble mieux. Y a-t-il une autre raison?

ÉDITER:

Je vais parler des votes serrés ici et maintenant. Je ne pense pas que cela appartienne au débordement de la pile, car cette question concerne principalement le design. Je dirais également que bien qu'il puisse s'agir d'opinions à ce sujet, réponse de Kilian Foth et réponse de cmaster prouve qu'il y a effectivement des avantages très objectifs avec une seule approche.

81
klutt

Une bonne partie des E/S du terminal est mise en mémoire tampon de ligne, donc en terminant un message avec\n vous pouvez être certain qu'il sera affiché en temps opportun. Avec un interligne\n, le message peut ou non s'afficher en une seule fois. Souvent, cela signifie que chaque étape affiche le message de progression de l'étape précédente, ce qui ne provoque pas de confusion et de perte de temps lorsque vous essayez de comprendre le comportement d'un programme.

221
Kilian Foth

Sur les systèmes POSIX (essentiellement n'importe quel linux, BSD, quel que soit le système open source que vous puissiez trouver), une ligne est définie comme une chaîne de caractères terminée par une nouvelle ligne \n. Il s'agit de l'hypothèse de base sur laquelle s'appuient tous les outils de ligne de commande standard, y compris (mais sans s'y limiter) wc, grep, sed, awk et vim. C'est aussi la raison pour laquelle certains éditeurs (comme vim) ajoutent toujours un \n à la fin d'un fichier, et pourquoi les normes antérieures de C exigeaient que les en-têtes se terminent par un \n personnage.

Btw: Avoir \n les lignes terminées facilitent le traitement du texte: vous savez avec certitude que vous avez une ligne complète lorsque vous avez ce terminateur. Et vous savez avec certitude que vous devez regarder plus de personnages si vous n'avez pas encore rencontré ce terminateur.

Bien sûr, cela se trouve du côté de l'entrée des programmes, mais la sortie du programme est très souvent utilisée à nouveau comme entrée de programme. Ainsi, votre sortie doit respecter la convention dans le but de permettre une entrée transparente dans d'autres programmes.

En plus de ce que d'autres ont mentionné, j'ai l'impression qu'il y a une raison beaucoup plus simple: c'est la norme. Chaque fois que quelque chose s'imprime sur STDOUT, il suppose presque toujours que c'est déjà activé une nouvelle ligne, et donc n'a pas besoin d'en démarrer une nouvelle. Il suppose également que la prochaine ligne à écrire agira de la même manière, donc elle se termine utilement en commençant une nouvelle ligne.

Si vous produisez des lignes de nouvelle ligne entrelacées avec des lignes de nouvelle ligne de fin standard, "cela finira par ressembler à ceci:

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

... ce qui n'est probablement pas ce que vous voulez.

Si vous n'utilisez que des sauts de ligne de début dans votre code et que vous ne l'exécutez que dans un IDE, cela peut s'avérer correct. Dès que vous l'exécutez dans un terminal ou introduisez du code d'autres personnes qui écrira dans STDOUT à côté de votre code, vous verrez une sortie indésirable comme ci-dessus.

31

Étant donné que les réponses très appréciées ont déjà donné d'excellentes raisons techniques pour lesquelles les nouvelles lignes de fin devraient être préférées, je vais l'aborder sous un autre angle.

À mon avis, ce qui suit rend un programme plus lisible:

  1. un rapport signal/bruit élevé (alias simple mais pas plus simple)
  2. les idées importantes viennent en premier

À partir des points ci-dessus, nous pouvons affirmer que les sauts de ligne de fin sont meilleurs. Les sauts de ligne mettent en forme le "bruit" par rapport au message, le message doit ressortir et doit donc venir en premier (la mise en évidence de la syntaxe peut aussi aider).

17
Alex Vong

L'utilisation de sauts de ligne simplifie les modifications ultérieures.

Comme exemple (très trivial) basé sur le code de l'OP, supposons que vous ayez besoin de produire une sortie avant le message "Initializing", et que la sortie provient d'une partie logique différente du code, dans un autre fichier source.

Lorsque vous exécutez le premier test et que "Initialisation" est maintenant ajouté à la fin d'une ligne d'une autre sortie, vous devez parcourir le code pour trouver où il a été imprimé, puis espérer changer "Initialisation" en "\ nInitialisation "ne gâche pas le format de quelque chose d'autre, dans des circonstances différentes.

Considérez maintenant comment gérer le fait que votre nouvelle sortie est en fait facultative, donc votre changement en "\ nInitializing" produit parfois une ligne vide indésirable au début de la sortie ...

Définissez-vous un indicateur global (shock horror ?? !!!) indiquant s'il y a eu une sortie précédente et testez-le pour imprimer "Initializing" avec un "\ n" en tête facultatif, ou faites-vous une sortie le "\ n" avec votre sortie précédente et laissez les futurs lecteurs de code se demander pourquoi cette "initialisation" ne pas a un "\ n" comme tous les autres messages de sortie?

Si vous affichez systématiquement des sauts de ligne de fin, au point où vous savez que vous avez atteint la fin de la ligne qui doit être terminée, vous évitez tous ces problèmes. Notez que cela peut nécessiter une instruction put ("\ n") distincte à la fin d'une logique qui génère une ligne morceau par morceau, mais le fait est que vous sortez la nouvelle ligne à la première place dans le code où vous sais que tu dois le faire, pas ailleurs.

16
alephzero

Pourquoi utiliser des sauts de ligne au lieu de mener avec printf?

Correspond étroitement à la spécification C

La bibliothèque C définit une ligne comme fin avec un caractère de nouvelle ligne '\n'.

Un flux de texte est une séquence ordonnée de caractères composée de lignes , chaque ligne consistant en zéro ou plusieurs caractères plus un caractère de nouvelle ligne de fin. Si la dernière ligne nécessite un caractère de nouvelle ligne de fin est définie par l'implémentation. C11 §7.21.2 2

Le code qui écrit les données sous forme de lignes correspondra alors à ce concept de bibliothèque.

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 dernière ligne nécessite un caractère de fin de ligne . Je recommande de toujours écrire un '\n' Final en sortie et de tolérer son absence en entrée.


Vérification orthographique

Mon correcteur orthographique se plaint. Peut-être que vous aussi.

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

 v--------v OK
"Processing\n");

Les sauts de ligne peuvent souvent faciliter l'écriture du code lorsqu'il existe des conditions, par exemple,

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

(Mais comme cela a été noté ailleurs, vous devrez peut-être vider le tampon de sortie avant de faire des étapes qui prennent beaucoup de temps CPU.)

Par conséquent, un bon argument peut être fait pour les deux façons de le faire, mais personnellement, je n'aime pas printf () et utiliserais une classe personnalisée pour construire la sortie.

4
Ian

Les sauts de ligne principaux ne fonctionnent pas bien avec d'autres fonctions de bibliothèque, notamment puts() et perror dans la bibliothèque standard, mais aussi avec toute autre bibliothèque que vous êtes susceptible d'utiliser.

Si vous souhaitez imprimer une ligne pré-écrite (soit une constante, soit une ligne déjà formatée - par exemple avec sprintf()), alors puts() est le choix naturel (et efficace). Cependant, puts() ne peut pas terminer la ligne précédente et écrire une ligne non terminée - il écrit toujours le terminateur de ligne.

1
Toby Speight