File Content reversal-Not working with foreach and pop from array

D

divyajacob

I was trying out a program
Accept a filename as command line argument. Display the
contents of that file in the opposite order that they appear in the
file.

file content is :-

Three Rings for the Elven-kings under the sky,
Seven for the Dwarf-lords in their halls of stone,
Nine for Mortal Men doomed to die,
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them
In the Land of Mordor where the Shadows lie.


I want to print it like:-

In the Land of Mordor where the Shadows lie.
One Ring to bring them all and in the darkness bind them
One Ring to rule them all, One Ring to find them,
In the Land of Mordor where the Shadows lie.
One for the Dark Lord on his dark throne
Nine for Mortal Men doomed to die,
Seven for the Dwarf-lords in their halls of stone,
Three Rings for the Elven-kings under the sky,

The program I wrote is
use strict;
my $num = $#ARGV + 1;
my $str;
my @file;
if($num >= 1)
{
$str = $ARGV[0];
}
else
{
print "No argument provided\n";
}

open (FILE,$str);
while(<FILE>)
{
push(@file,$_);
}
print "Reversed file content\n";
foreach(@file)
{

print pop(@file);
}
O/p
perl ex_04.pl ringfile.txt
Reversed file content
In the Land of Mordor where the Shadows lie.
One Ring to bring them all and in the darkness bind them
One Ring to rule them all, One Ring to find them,
In the Land of Mordor where the Shadows lie.

I am getting only 4 lines in the output,Why I am not getting full 8
lines in the output?
Please help..am I doing anything wrong.

Thanks in advance
Divya
 
J

Jürgen Exner

divyajacob said:
I was trying out a program
Accept a filename as command line argument. Display the
contents of that file in the opposite order that they appear in the
file.

file content is :-

Three Rings for the Elven-kings under the sky,
Seven for the Dwarf-lords in their halls of stone,
Nine for Mortal Men doomed to die,
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them
In the Land of Mordor where the Shadows lie.


I want to print it like:-

In the Land of Mordor where the Shadows lie.
One Ring to bring them all and in the darkness bind them
One Ring to rule them all, One Ring to find them,
In the Land of Mordor where the Shadows lie.
One for the Dark Lord on his dark throne
Nine for Mortal Men doomed to die,
Seven for the Dwarf-lords in their halls of stone,
Three Rings for the Elven-kings under the sky,

The program I wrote is
use strict;
my $num = $#ARGV + 1;

Better (unless you fooled around with $[ )
my $num = @ARGV;
# using an array in scalar context yields the number of array elements
my $str;
my @file;
if($num >= 1)

More perlishly written as
if (@ARGV) {
# yields false if and only if array length is 0
{
$str = $ARGV[0];
}
else
{
print "No argument provided\n";

Logical error. Probably missing:
exit -1;
Otherwise you continue your program and try to open a file even if there
was no filename supplied.
open (FILE,$str);

You should use lexical file handles, the 3-argument form of open(), and
always, yes always, check for failure:
open ($FILE, '<', $str) or die "Cannot open $str: $!";
while(<FILE>)
{
push(@file,$_);
}

The whole while loop can be replaced by
@file = said:
print "Reversed file content\n";
foreach(@file) {
print pop(@file);
}

This is bad bad bad style. While looping through the array using foreach
you are altering the array itself, i.e. you are deleting elements from
the array. Don't do that because results are unpredictable.

In this case by the time the loop has been executed 4 fimes the array
contains only 4 remaining elements and the foreach loop has reached the
end of the array.

Instead use a while loop:
while (@file) {
This will repeat the loop until all elements have been pop'ed out of the
array and only the empty array is left.

And of course the most obvious approach is to use reverse().

print reverse (@file);

jue
 
J

Justin C

I was trying out a program
Accept a filename as command line argument. Display the
contents of that file in the opposite order that they appear in the
file.

file content is :-

Three Rings for the Elven-kings under the sky,
Seven for the Dwarf-lords in their halls of stone,
Nine for Mortal Men doomed to die,
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them
In the Land of Mordor where the Shadows lie.


I want to print it like:-

In the Land of Mordor where the Shadows lie.
One Ring to bring them all and in the darkness bind them
One Ring to rule them all, One Ring to find them,
In the Land of Mordor where the Shadows lie.
One for the Dark Lord on his dark throne
Nine for Mortal Men doomed to die,
Seven for the Dwarf-lords in their halls of stone,
Three Rings for the Elven-kings under the sky,

The program I wrote is
use strict;
my $num = $#ARGV + 1;
my $str;
my @file;
if($num >= 1)
{
$str = $ARGV[0];
}
else
{
print "No argument provided\n";
}

open (FILE,$str);
while(<FILE>)
{
push(@file,$_);
}
print "Reversed file content\n";
foreach(@file)
{

print pop(@file);
}

You're removing from the stack that your reading from. The 'foreach'
works with each line, you then go and confuse it by taking a line away
with 'pop'. In this instance I'd be inclined to 'while (@file)' instead.
Your pop will then be OK.

As well as 'use strict' add 'use warnings', they're very helpful.

Justin.
 
S

sln

I was trying out a program
Accept a filename as command line argument. Display the
contents of that file in the opposite order that they appear in the
file.
[snip]
foreach(@file)
{

print pop(@file);
} [snip]

I am getting only 4 lines in the output,Why I am not getting full 8
lines in the output?
Please help..am I doing anything wrong.

Thanks in advance
Divya

The only question is why the bogus pretense of programming.
Are you trying to actually print out a reverse of the file
or are you whining that this:

print pop(@array) foreach(@array)

never works?

How do you know what pop, push, foreach is ??
What does print pop(@array) do?
You have to go to the root of the problem.

-sln
 
U

Uri Guttman

just to stick my $.02 in with all the other good answers cause this is
shorter and likely faster.

d> open (FILE,$str);


use File::ReadBackwards ; # get it from cpan

tie( *HANDLE, 'File::ReadBackwards', $str ) ;
print <HANDLE> ;

uri
 
J

John W. Krahn

divyajacob said:
I was trying out a program
Accept a filename as command line argument. Display the
contents of that file in the opposite order that they appear in the
file.

file content is :-

Three Rings for the Elven-kings under the sky,
Seven for the Dwarf-lords in their halls of stone,
Nine for Mortal Men doomed to die,
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them
In the Land of Mordor where the Shadows lie.


I want to print it like:-

In the Land of Mordor where the Shadows lie.
One Ring to bring them all and in the darkness bind them
One Ring to rule them all, One Ring to find them,
In the Land of Mordor where the Shadows lie.
One for the Dark Lord on his dark throne
Nine for Mortal Men doomed to die,
Seven for the Dwarf-lords in their halls of stone,
Three Rings for the Elven-kings under the sky,

The program I wrote is
use strict;
my $num = $#ARGV + 1;
my $str;
my @file;
if($num>= 1)
{
$str = $ARGV[0];
}
else
{
print "No argument provided\n";
}

open (FILE,$str);
while(<FILE>)
{
push(@file,$_);
}
print "Reversed file content\n";
foreach(@file)
{

print pop(@file);
}
O/p
perl ex_04.pl ringfile.txt
Reversed file content
In the Land of Mordor where the Shadows lie.
One Ring to bring them all and in the darkness bind them
One Ring to rule them all, One Ring to find them,
In the Land of Mordor where the Shadows lie.

I am getting only 4 lines in the output,Why I am not getting full 8
lines in the output?
Please help..am I doing anything wrong.

#!/usr/bin/perl
use warnings;
use strict;

my $str = shift or die "No argument provided\n";

print `tac $str`;

__END__




John
 
U

Uri Guttman

JWK> my $str = shift or die "No argument provided\n";

JWK> print `tac $str`;

well, if you are going to fork out, why need the backticks and print?

system "tac $str" ;

uri
 
J

John W. Krahn

Uri said:
JWK> my $str = shift or die "No argument provided\n";

JWK> print `tac $str`;

well, if you are going to fork out, why need the backticks and print?

system "tac $str" ;

Cause then I would have to do all the system error checking (which you
neglected to do) and besides, print() with no filehandle does not
necessarily go to STDOUT. :)



John
 
U

Uri Guttman

JWK> Cause then I would have to do all the system error checking (which you
JWK> neglected to do) and besides, print() with no filehandle does not
JWK> necessarily go to STDOUT. :)

i didn't expect the spanish inquisition!

<cue michael palin who is always late>

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top