navwin » Tech Talk » Beyond the Basics » Problem in foreach loop
Beyond the Basics
Post A Reply Post New Topic Problem in foreach loop Go to Previous / Newer Topic Back to Topic List Go to Next / Older Topic
Christopher
Moderator
Member Rara Avis
since 1999-08-02
Posts 8296
Purgatorial Incarceration

0 posted 2003-02-09 01:41 AM



Ok - this works beautifully if I put the HTML in the script itself, as in:

     -----

print qq~Content-type: text/html\n\n~;

print qq~first part of html~;

     run second foreach loop
          print $line;

print qq~first part of html~;

     -----

However, when I tried the following (to use templates for easier design changes and cleaner code), I get nothing, just a blank page.

By process of elimination, I've determined that the problem lies with the multiple foreach loops. I can see that there's something that's no gellin', but can't understand why.

     -----

sub outputView {
    
    #Format 1st part of page
    header();
        
    openFile($filePath = "_templates/massmailview1.htm");
        my @first = @index;
            foreach $line(@first) { print $line; }
    
    #Print page with all addys in list
    openFile($filePath = "$mailPath");
        my @users = @index;
            
            #Set total to zero for recount
            $total = 0;
                foreach $line(@users) {
                    chomp($line);
                    $total = $total + 1;
                    $total = sprintf("%4d", $total);
                    $total =~tr/ /0/;
                    
                    #Format lines to allow for deletion or to email the person
                    print qq~<img src="http://countlesshorizons.com/imgs/1.gif" width="1" height="1" hspace="25"> <font size="-2" color="#ff0000"><b>$total: <a href="massmail.pl?action=delete&email=$line&place=view" title="Delete address: $line"><img src="http://countlesshorizons.com/imgs/x.gif" width="10" height="10" border="0"></a> </b></font><a class="fam" href="mailto: $line" title="Email: $line">$line</a><br>~;
                    
                }#End foreach $line @ users
                                
    #Format 2nd part of page
    openFile($filePath = "_templates/massmailview1.htm");
        my @third = @index;
            foreach $line(@third) { print $line; }
                                
}#End SR outputView();

© Copyright 2003 C.G. Ward - All Rights Reserved
Ron
Administrator
Member Rara Avis
since 1999-05-19
Posts 8669
Michigan, US
1 posted 2003-02-09 02:20 AM


Your code looks fine, if I make a few assumptions about what's happening outside the routine. Your call to openFile is a bit, uh, unusual.

If it was me, I'd start putting in some "tags" to track the progress of the program. Right after your call to header(), put in a print "<p>outputView started</p>" so you know the routine is at least being called. After each openFile, I'd probably put in a print "<p>$index[0]</p>" to make sure the array is being filled. Things like that. It's a little easier to step through the program with tags and whole lot easier than debugging a blank screen.

Oh, and when you get a blank screen, make sure you take the extra step to View Source in the browser. Could be your program is sending something other than legitimate HTML and the browser just isn't displaying it?

(I'm guessing, just based on experience, but the most likely error in your code is the path to your templates files. Your openFile routine "should" be doing some error-checking, of course, to determine if the file exists. You might also see if you need to escape the underscore character? I've never used it in a file path, so I'm not sure. At any rate, the file path is where I'd concentrate initially.)

Christopher
Moderator
Member Rara Avis
since 1999-08-02
Posts 8296
Purgatorial Incarceration
2 posted 2003-02-09 03:13 AM


Once again, you are not only very helpful, but right as well. :o)

It DID have to do with the way I was calling to open a file. The sub for that looks like follows:

     -----

# openFile($filePath = "??");
sub openFile {
    my $filePath = $_[0];
    open (HANDLE, "$filePath") || die "Couldn't open $filePath: $!";
    @index = <HANDLE>;
    close (HANDLE);
    return @index;
}#end SR openFile

     -----

I'm thinking there was an error due to the "HANDLE" being repeated inside itself, without ? Not sure, but I am starting now to do as you suggested (as far as printing the values) so I can keep track.


Since I have you here (lol), is there a way to use an "or" function outside of having to use numerical values? I've tried things like:

     ------

if ($refURL eq $ad1 || $ad2 || $ad3) {do something}

if ($refURL eq ($ad1 || $ad2 || $ad3)) {do something}

     ------

I've also tried it using "or", but it doesn't work. Any suggestions? I've worked "around" it, by including every referrer I want allowed (and this also applies to several other places, not just the referrer one), but it's clumsy. Just curious.

Thanks Ron,

Chris

Ron
Administrator
Member Rara Avis
since 1999-05-19
Posts 8669
Michigan, US
3 posted 2003-02-09 06:35 AM


There shouldn't be any errors or problems with the way you've used the HANDLE variable. It comes into scope (is created) and then immediately goes out of scope (is destroyed) two lines later. When the routine is called later, HANDLE is simply recreated as a brand new variable (and then destroyed again). That's exactly what you want.

Your openFile routine has two potential problems. Neither is "wrong," per se, but I think they could cause unpredictable side-effects.

The call to openFile does not have to be an assignment. Instead of openFile($filePath = "_templates/massmailview1.htm"); it would be perfectly acceptable to just use openFile("_templates/massmailview1.htm"); . Whatever you place between the parens will be pushed into the $_ array for the openFile routine to retrieve, whether it's the contents of a variable or a literal string. You are doing the assignment and the passing in the same step, in the same set of parens, which suggests an assumption that one (the assignment) will always be performed before the other (throwing it into the $_ array). We both know what they say about assumptions.  

The second potential problem is, I suspect, a more serious one. There are two ways to get a value out of a Perl function. One is to use global variables that can be seen throughout the whole module. That appears to be what you are doing with @index. The other way is to use the return operator to pass the variables back to the calling program. Uh, that ALSO appears to be what you're doing with @index. You really need to choose one or the other.

I would make one tiny, teeny change to the openFile routine, changing the line @index = <HANDLE>; to my @index = <HANDLE>;, which means it is no longer a global variable. The calling subroutine can no longer access the file array directly, but must rather perform an assignment to get it. The correct way to call openFile, now, would be:

my @first = openFile("\_templates/massmailview1.htm");

Whatever is in the calling parens, in this case a literal string, is thrown into the $_ array by Perl. The openFile routine immediately grabs that value from $_[0] and assigns it to the my variable $filePath. openFile does its thing and at the end of the routine uses the return operator to throw the @index file array contents on the stack. Note that it is the CONTENTS of the local @index array and not the actual array. That's an important concept because, at that point, it no longer even HAS a name. It's just a list of values in a specific order. When Perl exits the openFile routine, it goes back to the calling program and performs the assignment operator. The contents that were saved onto the stack are then assigned to the @first array. It again has a name, albeit a different one. This is a much more efficient use of memory, which probably doesn't matter, but more importantly, it is far less ambiguous about what you expect Perl to do.

(Notice, too, that the literal string I'm passing to openFile has the underscore character escaped with a backslash. There are many special characters that require escaping if you are going to pass them in a literal double-quoted string. And obvious one is the $ character. If you don't escape it, Perl thinks it's the beginning of a variable name. I honestly don't know if the underscore requires escaping. But I think it might.)

Finally, yes, you can use multiple OR operators, but each one must be an explicit comparison.

if ( ($refURL eq $ad1) || ($refURL eq $ad2) || ($refURL eq $ad3) ) { do something }

hth  

Midnitesun
Deputy Moderator 1 Tour
Member Empyrean
since 2001-05-18
Posts 28647
Gaia
4 posted 2003-02-09 12:13 PM


I love it when you guys talk in foreach.
It reads like digital love poetry.

Post A Reply Post New Topic ⇧ top of page ⇧ Go to Previous / Newer Topic Back to Topic List Go to Next / Older Topic
All times are ET (US). All dates are in Year-Month-Day format.
navwin » Tech Talk » Beyond the Basics » Problem in foreach loop

Passions in Poetry | pipTalk Home Page | Main Poetry Forums | 100 Best Poems

How to Join | Member's Area / Help | Private Library | Search | Contact Us | Login
Discussion | Tech Talk | Archives | Sanctuary