2010-08-10 18 views
3

Je commence à apprendre perl, en utilisant la Wrox Beginning Perl available on perl.org et avez une question concernant un par exemple la boucle qu'ils fournissent au chapitre 3.Pourquoi l'ajout ou la suppression d'une nouvelle ligne change-t-il la façon dont perl fonctionne pour les fonctions de boucle?

#!/usr/bin/perl 

use warnings; 
use strict; 

my @count = (1..10); 
for (reverse(@count)) { 
     print "$_...\n"; 
     sleep 1; 
} 
print "Blast Off!\n" 

C'est le script qu'ils fournissent, et il fonctionne comme prévu. Il affiche un nombre suivi de ... chaque seconde, en attendant une seconde entre chaque nombre. Une fois terminé, il affiche

Cependant, si je supprime le saut de ligne de l'instruction print, le comportement change. Le script attend silencieusement 10 secondes, puis affiche tous les 10 numéros et Blash Off! à la fois. Pourquoi le changement?

#!/usr/bin/perl 

use warnings; 
use strict; 

my @count = (1..10); 
for (reverse(@count)) { 
     print "$_..."; 
     sleep 1; 
} 
print "Blast Off!\n" 
+1

STDOUT est tamponné par défaut. Faites "perldoc perlvar" et cherchez $ | – xcramps

+0

Pour plus de plaisir essayez 'print" $ _... \ r' (après avoir réglé autoflush); –

Répondre

11

Perl met en mémoire tampon la sortie print et le tampon n'est pas vidé jusqu'à la nouvelle ligne. Vous pouvez ajouter $| = 1 avant votre boucle pour dire Perl pour vider le tampon entre les instructions d'impression, vous donnant ainsi la sortie attendue avec le retard approprié:

#!/usr/bin/perl 

use warnings; 
use strict; 

$| = 1; #Add this line 
my @count = (1..10); 
for (reverse(@count)) { 
     print "$_..."; 
     sleep 1; 
} 
print "Blast Off!\n"' 
+0

Je l'ai fait, avec les instructions select, est plus sûr s'il y a une autre interaction de fichier –

+2

Encore mieux, et plus moderne: utiliser IO :: Handle; STDOUT-> autoflush (1); – mscha

4

La sortie standard est mise en mémoire tampon. Il ne videra pas le tampon jusqu'à ce qu'il voit une nouvelle ligne. Vous pouvez corriger cela en ajoutant la ligne suivante avant la boucle:

my $ofh = select(STDOUT); $| = 1; select $ofh; 

Brisons que vers le bas:

my $ofh = select(STDOUT); - sélectionne STDOUT (sortie standard) que la poignée en cours de fichier sélectionné, et stocke tout ce qui était la Poignée de fichier sélectionnée précédente dans $ofh

$| = 1; - définit le handle de fichier actuel (par exemple, STDOUT) sur unbuffered. - resélectionne tout ce qui était auparavant le handle de fichier sélectionné, de sorte que si le code a sélectionné un handle de fichier autre que STDOUT à un moment donné, il sera toujours sélectionné après que cette ligne de code soit terminée.

+0

Vous devriez probablement expliquer ce que les 'select's sont pour –

+0

@Brad, done Merci pour la suggestion –

4

Vous regardez le comportement standard de la ligne- sortie orientée de la bibliothèque C stdio lors de l'écriture sur un terminal.

Voir autoflush pour les détails perl.

1

Une façon plus nette que d'utiliser select() pour définir l'indicateur de autoflush sur STDOUT est d'utiliser IO :: Handle (qui a été inclus dans le noyau Perl depuis la version 5.004):

use IO::Handle; 
STDOUT->autoflush(1)