drose2211 has asked for the wisdom of the Perl Monks concerning the following question:

I am attempting to print out a stack. The method I am using works, but it looks like there is probably a better way to go about it. Is it possible to make a loop that pops each value off the end of the stack and prints it rather than the (probably) unnecessarily long way I am doing it here:

#!/usr/bin/perl use strict; use warnings; my $a, $b, $c, $d, $e; my $file = "data.txt"; open(my $fh,'<', $file) or die "can't open $file $!"; my @stack = <$fh>; chomp @stack; $a = pop @stack; print $a . "\n"; $b = pop @stack; print $b . "\n"; $c = pop @stack; print $c . "\n";

Replies are listed 'Best First'.
Re: Printing Stacks
by BrowserUk (Patriarch) on Mar 26, 2018 at 20:09 UTC

    Your @stack is just an array, and you want to see them in the reverse order:

    print $stack[ $_ ] for reverse 0 .. $#stack;

    And if you really want to destroy the stack in the process, add:

    undef @stack;

    You could also do:

    print while pop @stack;

    But that's just wasteful :) (It's actually not, perl's arrays are well optimised for this operation.)


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
Re: Printing Stacks
by Perlbotics (Archbishop) on Mar 26, 2018 at 20:08 UTC

    A little rewrite using DATA instead of an external file and a loop.

    use strict; use warnings; #my ($a, $b, $c, $d, $e); my $file = "data.txt"; #open(my $fh,'<', $file) or die "can't open $file $!"; #my @stack = <$fh>; my @stack = <DATA>; #chomp @stack; #$a = pop @stack; #print $a . "\n"; #$b = pop @stack; #print $b . "\n"; #$c = pop @stack; #print $c . "\n"; print while defined ($_ = pop @stack); __DATA__ line 1 line 2 line 3 line 4

    Result:

    line 4 line 3 line 2 line 1

    See also: reverse and File::ReadBackwards.

      I did it this way and it worked, but it all comes out on one line and I have tried adding a new line in several areas, but I keep getting errors. Where would I add a new line character to make sure they all come out on separate lines?

        Either refrain from chomping @stack or else replace print with say.

        I have tried adding a new line in several areas, but I keep getting errors.

        If you want help fixing errors you have to say what those errors were (precisely) and how you generated them (with an SSCCE). Just saying "I keep getting errors" is not informative enough.

Re: Printing Stacks
by AnomalousMonk (Archbishop) on Mar 26, 2018 at 20:29 UTC

    Another way: Print last n lines of array in reverse order:

    c:\@Work\Perl\monks>perl -wMstrict -e "my @stack = ( 'line 1', 'line two', 'third line', 'line the fourth', 'almost there', 'last line', ); ;; my $n = 3; ;; print qq{$_ \n} for @stack[ -$n .. -1 ]; " line the fourth almost there last line
    The  @stack[ -$n .. -1 ] expression is an array slice. (Update: Negative indices index from the end of the array.)

    Update: Oops... Just realized the lines are not printed in reverse order. Oh well, easily fixed (but not as neat):

    c:\@Work\Perl\monks>perl -wMstrict -e "my @stack = ( 'line 1', 'line two', 'third line', 'third from last', 'almost there', 'last line', ); ;; my $n = 3; ;; print qq{$_ \n} for reverse @stack[ -$n .. -1 ]; " last line almost there third from last


    Give a man a fish:  <%-{-{-{-<

Re: Printing Stacks
by BillKSmith (Monsignor) on Mar 26, 2018 at 22:18 UTC
    You can print the whole array at once.
    use strict; use warnings; #my $file = "data.txt"; my $file = \do{my $simulated_file = "line1\nline2\nline3\nline4\n";}; # Line above simulates the file. open (my $fh, '<', $file) or die "can't open file $!"; my @stack = <$fh>; chomp @stack; { local $, = "\n"; print reverse( @stack ), "\n"; } @stack = (); # Only needed if you wish to destroy the @stack OUTPUT: line4 line3 line2 line1
    Bill