in reply to Initialize array

What is the program you're using which is giving you this issue? It's really difficult to diagnose a code problem without seeing code...

Replies are listed 'Best First'.
Re: Re: Initialize array
by Anonymous Monk on Jul 03, 2001 at 22:03 UTC
    The part of the program that is giving me trouble is below, as I said before it was working fine on my home computer, but when I try it on my work computer it always prints the number you select -1. For example if the user selects 7 I am wanting it to print out $lines6.
    use warnings; use strict; my @lines; my $filename = shift; open (IN, "$filename") or die ("Cannot open file :$!"); while (my $line = <IN>) { if (!($line =~ /\s*[a-qs-zA-Z]/)) { push (@lines,$line); } } close (IN) or die("Cannot close file: $!"); print "Enter link number you want to view:"; my $number1 = <STDIN>; chomp $number1; if ($number1 > $#lines | $number1 <= 0) { print "Number outside of array" } else { print "$lines[$number1-1]"; }
      Ok. Let me see if I got this right - you're complaining that if you enter 7 at home, it will print 6, but that if you enter 7 at work, it will print 7 ... ?

      First off, the indices of an array go from 0 to $#lines. So, when you do $number1 <= 0 as a boundary condition, you're already cutting off one of your useable indices.

      The second thing is that you're comparing the number they give you (from 1 .. N) to a range from (0 .. N-1). I would do a $number1--; right after the chomp.

      The third thing is that you're using | (the bit-wise OR) when I think you mean to be using || (the logical OR).

      A few style notes:

      • if (!$blah) should be written unless ($blah)
      • Never use a variable named $number1. Instead, use something like $link_num.
      • I'd change your file-reading to something like this. It's clearer exactly what you're trying to do, which is to take in all the lines, then reject a certain type of line.

        open IN, "<$filename" or die "Cannot open $filename\n"; my @lines = <IN>; close IN or die "Cannot close $filename\n"; @lines = grep !/\s*[a-qs-zA-Z]/, @lines;
      • The \s* in your regular expression is useless, in that it doesn't add any restrictiveness. Generally, you don't see \s* in matches, just substitutions.
      Hope this helps!

        Very good answer, dragonchild++! Let me add a small remark to your remark on \s* in pattern matching regexes.

        Probably what was meant was a line starting with a 'r' indented or not (assuming that we are looking at a textfile)

        # was if (!($line =~ /\s*[a-qs-zA-Z]/)) # equivalent to (as noted by dragonchild) unless ($line =~ /[a-qs-zA-Z]/) # should have been IMHO unless ($line =~ /^\s*[a-qs-zA-Z]/) # which is equivalent to (with assumption 'textfile') if ($line =~ /^\s*r/)
        Note the ^ indicating the beginning of the line. In that case the \s* is necessary to skip any indentation at the start of the line. The last statement is (in my view) much clearer - providing of course I guessed correctly at the intention of Myia ;-)

        To sum up, if you are using an anchor (like ^, $ or \G) in your pattern then \s* might be useful in a match, otherwise it isn't.

        -- Hofmator

      Instead of your if ($number > $#lines | $number <=0) section, you could try something like this:

      if (defined $lines[$number1 - 1]) { print $lines[$number1 - 1]; print "\n"; } else { print "No link at that index\n"; }

      This will check if there's a value at the spot in the array. This will benefit you if, in the future, you expand your code to delete links, or if you accidentally have blank lines in your input file.

      As always, TMTOWTDI.