$line1=<IN>;
$line2=<IN>;
$line3=<IN>;
Regards,
Peng
or:
my @lines;
my $limit = 3;
for my $line(1..$limit) {
$lines[$line] = <IN>
}
But then again I have a personal dislike of counters and flags, so I
tend to look for ways to avoid using them.
--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.
And that was an off-by-one error. Saw it as I hit 'post'.
So the correct code would of course be:
my @lines;
my $limit = 3;
for my $line(0..$limit-1) {
$lines[$line] = <IN>
Better would be
my @lines;
push @lines, <IN> for 1..3;
though I would probably rather have
my @lines = map <IN>, 1..3;
since I don't like variable declarations just hanging around not doing
anything useful.
Ben
BZZT!
Both of your examples will read the entire file into @lines.
Left as an exercise to figure out why this is and how to fix it.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
True. Good catch. (Or possibly stupid mistake on my part.)
> Q: "How to fix it".
> A: They need to stop trying to be so fucking clever. Clever kills.
'They' in this case being me? I wasn't trying to be clever, I was trying
to write the code in a simple and obvious way. Counting indices by hand
is much easier to get wrong than letting perl count them for you.
Ben
You mean like: for (0..2) { $lines[$_] = <IN> }
But in any case, this mistake is not a cleverness one,
because the exact same problem exists in the code:
for (my $i = 0; $i < 3; $i++) {
push @lines, <IN>;
}
Which I would hardly call 'clever'.
> You mean like: for (0..2) { $lines[$_] = <IN> }
I'am not smart enough to not try being clever.
Besides (and for wrong reasons: I used to like Lisp), I like maps.
So, I was thinking of the following minimal(?) fix(?):
my @lines = map scalar <IN>, 1..3;
Marc
Mmm, I suppose. I think my problem with that is that I just dislike
array indices other than [0] and [-1]: I think of arrays as 'frozen
lists', so either you iterate over the whole thing or you attack it from
the ends.
The original buggy code was essentially
for (1..3) { $lines[$_] = <IN> }
and the use of explicit subscripts disguises the fact that there's an
extra 'undef' element on the beginning.
> But in any case, this mistake is not a cleverness one,
> because the exact same problem exists in the code:
>
> for (my $i = 0; $i < 3; $i++) {
> push @lines, <IN>;
> }
>
> Which I would hardly call 'clever'.
I suspect that anyone approaching that code who didn't have a background
in C *would* call it clever, or at any rate much more complicated and
less comprehensible than a simple
for (1..3)
Something like
repeat (3) {...}
would be even simpler, of course, but unfortunately Perl doesn't allow
modules to create new syntax like that[0].
Ben
[0] ...without support code that will make you go blind.
c.f. Devel::Declare, and/or source filters.
BM> Quoth Willem <wil...@turtle.stack.nl>:
>> Ben Morrow wrote:
>> ) 'They' in this case being me? I wasn't trying to be clever, I was trying
>> ) to write the code in a simple and obvious way. Counting indices by hand
>> ) is much easier to get wrong than letting perl count them for you.
>>
>> You mean like: for (0..2) { $lines[$_] = <IN> }
BM> Mmm, I suppose. I think my problem with that is that I just dislike
BM> array indices other than [0] and [-1]: I think of arrays as 'frozen
BM> lists', so either you iterate over the whole thing or you attack it from
BM> the ends.
amusing viewpoint but what about random accesses, direct accesses (it
happens), splicing (both inserts and deletes), etc. true, i do what you
say most of the time but i still keep those other things in my
toolbox. :)
uri
--
Uri Guttman ------ u...@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
>>> my @lines;
>>> my $limit = 3;
>>> for my $line(1..$limit) {
>>> $lines[$line] =<IN>
>>> }
>>>
>>> But then again I have a personal dislike of counters and flags, so I
>>> tend to look for ways to avoid using them.
>>
>> And that was an off-by-one error. Saw it as I hit 'post'.
>>
>> So the correct code would of course be:
>>
>> my @lines;
>> my $limit = 3;
>> for my $line(0..$limit-1) {
>> $lines[$line] =<IN>
>> }
> In some senses you original code was correct although
> it didn't fill $lines[0].
> As required, it read a certain number of lines into an array.
> Nonetheless, I suggest you start disliking silly errors
> more than you dislike counters and flags.
> HTH
You know, if you want your advice to be taken seriously, it would be
better not to behave like a complete twit.
Mart
Hi,
May be the special var "$." (line NBR of the last read file handle)
could help :
my @lines;
while (<>) { push @lines,$_ if($.<4) }
Regards,
Alexandre
b> On Jun 8, 6:14 pm, Peng Yu <pengyu...@gmail.com> wrote:
>> I want to give a given number of lines. Current, I have to write the
>> following code to read, for example, 3 lines. Is there a subroutine to
>> read a given number of lines in an array?
>>
>> $line1=<IN>;
>> $line2=<IN>;
>> $line3=<IN>;
b> Hi,
b> May be the special var "$." (line NBR of the last read file handle)
b> could help :
b> my @lines;
b> while (<>) { push @lines,$_ if($.<4) }
and what happens to the lines after the third one? that will read to eof
which is likely not wanted.
better to invert the loop:
while ( $. < 4 ) {
push @lines, scalar <> ;
}
or for those lovers of one liners:
push @lines, scalar <> while $. < 4 ;
Ah ! Your "scalar <>" (thank you) gave me another idea :
my @lines = grep {defined $_} map {scalar <>} (1..3);
>>>>>> "b" == bankair <ban...@gmail.com> writes:
>
> b> On Jun 8, 6:14 pm, Peng Yu <pengyu...@gmail.com> wrote:
> >> I want to give a given number of lines. Current, I have to write
> >> the following code to read, for example, 3 lines. Is there a
> >> subroutine to read a given number of lines in an array?
> >>
> >> $line1=<IN>;
> >> $line2=<IN>;
> >> $line3=<IN>;
>
> b> Hi,
>
> b> May be the special var "$." (line NBR of the last read file handle)
> b> could help :
> b> my @lines;
> b> while (<>) { push @lines,$_ if($.<4) }
>
> and what happens to the lines after the third one? that will read to eof
> which is likely not wanted.
>
> better to invert the loop:
>
> while ( $. < 4 ) {
> push @lines, scalar <> ;
> }
>
> or for those lovers of one liners:
>
> push @lines, scalar <> while $. < 4 ;
Those have the potential of an infinite loop when the file has less than
3 lines. Besides, even when fixed, the 'push @lines, scalar <>' pushes
undef at eof, so I very much doubt this is what you want.
So I guess the best option (assuming you want to exit early at eof, not
push undefs):
while (<>) {
last if ($.>=4)
push @lines,$_;
}
Eventually followed by
push @lines, undef for ($. .. 3);
If you do want undefs for missing lines.
M4
The variable $. holds the current line number for the last filehandle
accessed. It may be useful to you, see perldoc perlvar for details.
Justin.
--
Justin C, by the sea.
I don't understand why 'scalar' has to be used. Would you please let
me know where I should read in man page to understand file handle in
scalar and list context.
> I don't understand why 'scalar' has to be used. Would you please let
> me know where I should read in man page to understand file handle in
> scalar and list context.
I/O Operators in perlop?
In scalar context, evaluating a filehandle in angle brackets
yields the
next line from that file (the newline, if any, included), or
"undef" at
end-of-file or on error.
...
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.
and then, of course, scalar in perlfunc...
scalar EXPR
Forces EXPR to be interpreted in scalar context and
returns the
value of EXPR.
Marc
As Marc pointed out, using the readline operator <> in scalar context
reads only one line.
Why it is necessary here is because the above statement would normally
evaluate <> in list context. I'm a bit unclear if that is because of the
array assignment or the map function. I believe it is the map function
forcing a list context here, but I could be wrong. Even if I am,
assigning to an array definitely forces list context.
map always evaluates its first argument (EXPR or BLOCK) in list context.
This makes it possible to change the length of the returned list.
Ben
$ echo -e 'a\nb\nc\nd\ne\n' | perl -wle'
sub get_lines {
my ( $fh, $max, $aref )= @_;
my $count;
while ( ++$count <= $max and defined( my $line= <$fh> ) ) {
push @$aref, $line;
}
return $count;
}
my @lines;
get_lines +STDIN, 2, \@lines;
print for @lines;
'
a
b
--
Ruud