My @array will not stop taking in STDIN...
my @array = undef;
while (@array = undef){
@array = <STDIN>;
for (@array[x]=5){
@array = defined;
}
}
My @array will not stop taking in STDIN...
my @array = undef;
while (@array = undef){
@array = <STDIN>;
for (@array[x]=5){
@array = defined;
}
}
As clarified, limit the STDIN
to five lines
use warnings;
use strict;
use feature 'say';
my @input;
while (<STDIN>) {
chomp;
push @input, $_;
last if @input == 5;
}
say for @input;
There are other things to comment on in the posted code. While a good deal of it is cleared up in detail in Dave Cross answer, I'd like to address the business of context when reading from a filehandle.
The "diamond" operator <>
is context-aware. From I/O Operators (perlop)
If a
<FILEHANDLE>
is used in a context that is looking for a list, a list comprising all input lines is returned, one line per list element. It's easy to grow to a rather large data space this way, so use with care.
In the usual while
loop the <>
is in the scalar context
while (my $line = <$fh>)
and it is the same with while (<$fh>)
since it assigns to $_
variable, a scalar, by default.
But if we assign to an array, say from a filehandle $fh
with which a file was opened
my @lines = <$fh>;
then <>
operator works in the list context. It reads all lines until it sees EOF (end-of-file), at which point it returns all lines, which are assigned to @lines
. Remember that each line has its newline. You can remove them all by
chomp @lines;
since chomp works on a list as well.
With STDIN
this raises an issue when input comes from keyboard, as <>
waits for more input since EOF isn't coming on its own. It is usually given as Ctrl+D
† on Unixy systems (Ctrl+Z on Windows).
So you can, in principle, have @array = <STDIN>
and quit input with Ctrl+D
but this may be a little awkward for input expected from keyboard, as it mostly implies the need for line by line processing. It is less unusual if STDIN
comes from a file,
script.pl < input.txt
or a pipe on the command line
some command with output | script.pl
where we do get an EOF (courtesy of EOT).
But I'd still stick to a customary while
when reading STDIN
, and process it line by line.
† The Ctrl+D
is how this is usually referred to but one actually types a low-case d
with Ctrl
. Note that Ctrl
and c
(labeled as Ctrl+C
) does something entirely different; it sends the SIGINT
signal, which terminates the whole program if not caught.
my @array = undef;
while (@array = undef){
These two lines don't do what (I assume) you think they are doing.
my @array = undef;
This defines an array with a single element which is the special value undef
. I suspect that what you actually wanted was:
my @array = ();
which creates an empty array. But Perl arrays are always empty when first created, so this can be simplified to:
my @array;
The second line repeats that error and adds a new one.
while (@array = undef) {
I suspect you want to check for an empty array here and you were reaching for something that meant something like "if @array is undefined
). But you missed the fact that in Perl, assignment operators (like =
) are different to comparison operators (like ==
). So this line assigns undef
to @array
rather than comparing it. You really wanted @array == undef
- but that's not right either.
You need to move away from this idea of checking that an array is "defined". What you're actually interested in is whether an array is empty. And Perl has a clever trick that helps you work that out.
If you use a Perl array in a place where Perl expects to see a single (scalar) value, it gives you the number of elements in the array. So you can write code like:
my $number_of_elements = @an_array;
The boolean logic check in an if
or while
condition is a single scalar value. So if you want to check if an array contains any elements, you can use code like this:
if (@array) {
# @array contains data
} else {
# @array is empty
}
And to loop while an array contains elements, you can simply write:
while (@array) {
# do something
}
But here, you want to do something while your array is empty. To do that, you can either invert the while
condition logic (using !
for "not"):
while (!@array) {
# do something
}
Or you can switch to using an until
test (which is the opposite of while
):
until (@array) {
# do something
}
I'm going to have to stop there. I hope this gives you some insight into what is wrong with your code. I'm afraid that this level of wrongness permeates the rest of your code too.