in reply to Array reference
rkk:
OK, let's do a little debugging. First, I took your script and added "use warnings" at the top, closed a couple curly braces, and added "my" before the @s_array. That was enough to make it compile cleanly.
When I run it, my screen fills with:
Use of uninitialized value in string eq at 1038612.pl line 21, <FILE> +line 4. Use of uninitialized value in string eq at 1038612.pl line 21, <FILE> +line 4. Use of uninitialized value in subtraction (-) at 1038612.pl line 21, < +FILE> line 4. Use of uninitialized value in subtraction (-) at 1038612.pl line 21, < +FILE> line 4.^C
It doesn't stop, so there's apparently an infinite loop. Well, let's run it under the debugger and see what the program is doing:
$ perl -d 1038612.pl Loading DB routines from perl5db.pl version 1.32 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(1038612.pl:4): open (FILE, "ip.txt") || die "can't: $!"; DB<1> n main::(1038612.pl:6): my @lines=(); DB<1> main::(1038612.pl:7): my @l1=(); DB<1> main::(1038612.pl:8): my @l2=(); DB<1> main::(1038612.pl:9): @lines=<FILE>; DB<1> main::(1038612.pl:10): my %hash=(); DB<1>
The 'n' command tells it to execute the next instruction. After that, pressing the Enter key repeats the command, so here we've just executed lines 4 through 9 and are ready to execute line 10.
The debugging session continues...
Before we run the next line, let's take a quick peek at what's in the @lines variable:
DB<1> x @lines 0 'ID1 ch1 70 mir abc xyz ch2 2050 ' 1 'ID2 ch1 90 mir abc xyz ch2 4000 ' 2 'ID3 ch1 100 mir abc xyz ch2 2045 ' 3 'ID4 ch1 120 mir abc xyz ch2 2025
The x command lets you examine a variable: It looks like @lines contains what we expect--so far, so good. Let's continue stepping through the code:
DB<2> n main::(1038612.pl:11): my $i=0; DB<2> n main::(1038612.pl:12): my $j=$i+1; DB<2> n main::(1038612.pl:13): my @arr1=(); DB<2> n main::(1038612.pl:14): my @arr2=(); DB<2> main::(1038612.pl:15): my @arr3=(); DB<2> main::(1038612.pl:16): while($j <= $#lines) main::(1038612.pl:17): { DB<2> main::(1038612.pl:19): @l1=split(/\t/,"$lines[$i]"); DB<2> main::(1038612.pl:20): @l2=split(/\t/,"$lines[$j]"); DB<2> main::(1038612.pl:21): if(abs($l2[3]-$l1[3]) <= 500 && $l1[6] e +q $l2[6]) main::(1038612.pl:22): { DB<2>
OK, we set $i to 0, and $j to 1, so now @l1 should contain the fields in line 1 and @l2 should contain the fields in line 2:
DB<2> x @l1 0 'ID1 ch1 70 mir abc xyz ch2 2050 ' DB<3> x @l2 0 'ID2 ch1 90 mir abc xyz ch2 4000 '
Oops! The data has blanks instead of tabs, so the split didn't really do much. I'll edit the input file to use tabs and try again.
/me exits perl debugging, edits file, restarts debugger and steps down to same point Now let's take a look after the edit:
DB<5> x @l1 0 'ID1' 1 'ch1' 2 70 3 'mir' 4 'abc' 5 'xyz' 6 'ch2' 7 2050 DB<6> x @l2 0 'ID2' 1 'ch1' 2 90 3 'mir' 4 'abc' 5 'xyz' 6 'ch2' 7 4000
OK, that's more like it. OK, let's see what comes next.
DB<7> n Argument "mir" isn't numeric in subtraction (-) at 1038612.pl line 21, + <FILE> line 4. at 1038612.pl line 21 Argument "mir" isn't numeric in subtraction (-) at 1038612.pl line 21, + <FILE> line 4. at 1038612.pl line 21 main::(1038612.pl:23): $hash{$lines[$j]}=1;
OK, perl complains a bit about line 21. It scrolled off the top of my window, so let's ask perl to show us line 21:
DB<7> l 21 21: if(abs($l2[3]-$l1[3]) <= 500 && $l1[6] eq $l2[6]) DB<9> x $l2[3], $l1[3] 0 'mir' 1 'mir'
OK. Now that we can see line 21 we look at the variables involved in the subtraction. Sure enough: mir isn't numeric. You forgot that arrays start at 0 rather than one. So I'll change the code to adjust your array indexes, and try again.
DB<1> main::(1038612.pl:21): if(abs($l2[2]-$l1[2]) <= 500 && $l1[5] e +q $l2[5]) main::(1038612.pl:22): { DB<1> main::(1038612.pl:23): $hash{$lines[$j]}=1; DB<1> main::(1038612.pl:24): if(!exists $hash{$lines[$i]}) main::(1038612.pl:25): { DB<1> main::(1038612.pl:26): $hash{$lines[$i]}=1; DB<1> x %hash 0 "ID2\cIch1\cI90\cImir\cIabc\cIxyz\cIch2\cI4000\cJ" 1 1
OK, we cruise right through line 21 this time, and we just added an item to %hash. So now you have line 2 as a key in the hash, with a value of 1. Looks reasonable.
DB<2> n main::(1038612.pl:27): push(@arr1,$l1[3]); DB<2> main::(1038612.pl:28): push(@arr2,$l1[7]); DB<2> main::(1038612.pl:29): push(@arr3,$lines[$i]); DB<2> main::(1038612.pl:34): push(@arr1,$l2[3]); DB<2> main::(1038612.pl:35): push(@arr2,$l2[7]); DB<2> main::(1038612.pl:36): push(@arr3,$lines[$j]) DB<2> main::(1038612.pl:19): @l1=split(/\t/,"$lines[$i]"); DB<2>
Now you're pushing stuff onto a bunch of arrays. I could check the values, but I'm expecting that the array indexes are likely to be wrong here, too. But what concerns me is that you're splitting line 1 again and putting it into array @l1 again. What's the purpose of this? You didn't change the first line, nor did you change $i, so @l1 shouldn't be changed. (Additionally, the quotes are superfluous here, as $lines[$i] is already a string.)
So as you can see, using the debugger is pretty simple, and it's an easy way to see what your code is *actually* doing. So I encourage you to step through your program. It's very instructive, as you'll start wondering why you do things in certain ways, and helps get the algorithm sorted out in your mind.
OK, now that I've done my bit, here's an observation on your code: It seems like you're trying to use @arr1, @arr2 and @arr3 to contain data that's logically tied together. If so, it would probably benefit you to get used to using an array of arrays, so each slot always has the related values you want. In other words, you can turn this:
push(@arr1,$l1[3]); push(@arr2,$l1[7]); push(@arr3,$lines[$i]); print "first item: $arr1[0], second item: $arr2[0], third item: $arr3[ +0]\n";
Into this:
push @arr, [ $l1[3], $l1[7], $lines[$i] ]; print "first item: $arr[0][0], second item: $arr[0][1], third item: $a +rr[0][2]\n";
That way, if you need to interchange two rows in your arrays, instead of this:
# swap items 1 and 3 my $temp=$arr1[1]; $arr1[1]=$arr1[3]; $arr1[3]=$temp; $temp=$arr2[1]; $arr2[1]=$arr2[3]; $arr2[3]=$temp; $temp=$arr3[1]; $arr3[1]=$arr3[3]; $arr3[3]=$temp;
you can do this:
# swap items 1 and 3 my $temp=$arr[1]; $arr[1]=$arr[3]; $arr[3]=$temp;
This way, you're swapping around an array of related items, without a bunch of copypasta.
Note: I didn't write the swaps in the best way, I did it as a beginner might. But in fact perl lets you assign a list to a list of values, so it's even easier to do it like this:
# swap items 1 and 3 ($arr[1], $arr[3]) = ($arr[3], $arr[1]);
Well, I hope you find my rambling useful in some way. Let me know if you get stuck again.
Update: Added a missing code tag, moved one sentence ("the debugging continues" moved up a line), added another sentence for clarity ("Now that we can see line 21").
...roboticus
When your only tool is a hammer, all problems look like your thumb.
|
|---|