CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Advanced:
Problems Displaying Data

 



mike
User

Jul 4, 2001, 1:06 PM

Post #1 of 9 (2886 views)
Problems Displaying Data Can't Post

OK,

here is my problem. I am I trying to display the data from 2 different files in the same table. The first file is for the name of the category, and the second is for the number of posts in that category. However, when it goes to print it all out, only the last line has the correct ammount of posts in it, and the others all say that there are 0 posts in that category. Here is the coding below:


$posts = "0";
open (DATA, "$userpath/$user/forums/cat.txt");
@data = <DATA>;
close DATA;
open (DATA, "$userpath/$user/forums/boarddata.txt");
@data2 = <DATA>;
close DATA;

foreach $data (@data) {


print<<"EOF";
<table width=100% border=0 cellpadding=3 cellspacing=1><tr>
<td width=50% bgcolor="$tablemid">
<img src="Board.gif" border=0 vspace=1 align="absmiddle">
<a href="http://www.site.com/board3.cgi?action=index&cat=$data">$data</a>
</td>
EOF
foreach $line4 (@data2) {
($mdate, $msub, $mfollow, $mname, $memail, $mdate, $mip, $mcat, $mmessage, $linkname, $linkurl, $imageurl) = split(/:::/,$line4);
chomp ($line4);
foreach ($line4) {
if ($mcat eq $data) {
$posts++;
print "$mcat";
}

}
}

print<<"EOF";
<td width=18% align="center" bgcolor="$tablemid"><font size=2>$posts</font></td>
<td width=21% align="center" bgcolor="$tablemid"><font size=2>??</font></td>
<td width=11% align="center" bgcolor="$tablemid"><font size=2></font></td></tr></table>
EOF
$posts = "0";
}



Then when it prints it all out, it displays the correct format for the categories, and it works fine with the last one, but all the categories before the last one display a "0" in the posts section. Any help would be appreciated.

Thanks,

Mike



mhx
Enthusiast

Jul 4, 2001, 1:54 PM

Post #2 of 9 (2882 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hi mike!

First, I guess I know what your problem is. If you have a close look at your cat.txt file you will notice that its last line isn't terminated by a newline sequence, but contains only the category. All lines above contain the category, followed by a newline sequence. That's why it works for the last category. To make it work for all characters, chomp $data before doing anything in the outer foreach loop.
Second, there's some other things in the code that seem quite strange to me (might be me ;-):
In the second foreach loop, you chomp $line4 after splitting it. You should do that before.
You only seem to need the 8th argument of the split, which is $mcat. You could therefore simplify this line to

Code
$mcat = (split /:::/, $line4)[7]

But this also isn't very good, since you're doing the same splits everytime you're running through the second loop, which is very inefficient. You should do the split only once when reading the file.
The third foreach loop seems quite unneccessary to me. Since $line4 is a scalar, the foreach loop will only loop once, furthermore the content of $line4 is never used inside the loop. So you could as well remove that loop.
Since you're using $posts as a numeric value, you should initialize it with a numeric rather than with a string. I guess it won't matter to Perl, but to the reader it makes the intention clearer. Also, you only need to initialize it once at the beginning of the outermost foreach block instead of twice, before that block and at its end.
From all these points I considered a small rewrite of your code snippet. It's untested, since I have neither your data nor the whole script. But at least you should be able to see the ideas I've just written down in form of Perl code:

Code
open DATA, "$userpath/$user/forums/cat.txt"; 
my @data = <DATA>;
close DATA;

open DATA, "$userpath/$user/forums/boarddata.txt";
my @data2 = map { chomp; [split /:::/] } <DATA>;
close DATA;

foreach my $data (@data) {
chomp $data;

print <<"EOF";
<table width=100% border=0 cellpadding=3 cellspacing=1><tr>
<td width=50% bgcolor="$tablemid">
<img src="Board.gif" border=0 vspace=1 align="absmiddle">
<a href="http://www.site.com/board3.cgi?action=index&cat=$data">$data</a>
</td>
EOF

my $posts = 0;
foreach( @data2 ) {
$posts++ if $_->[7] eq $data;
}

print <<"EOF";
<td width=18% align="center" bgcolor="$tablemid"><font size=2>$posts</font></td>
<td width=21% align="center" bgcolor="$tablemid"><font size=2>??</font></td>
<td width=11% align="center" bgcolor="$tablemid"><font size=2></font></td></tr></table>
EOF
}

Hope all this will help you.

-- Marcus



mhx
Enthusiast

Jul 4, 2001, 10:26 PM

Post #3 of 9 (2877 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hi again!

As always, there's more than one way to do it. I've just discovered another way of getting the number of posts which seems more efficient to me than looping over the splitted data all the time. Using a hash table, with a key for each category, you can easily get the number of posts by looping over the splitted data only once. Here's what I mean in code:

Code
open DATA, "$userpath/$user/forums/cat.txt"; 
chomp( my @data = <DATA> );
close DATA;
open DATA, "$userpath/$user/forums/boarddata.txt";
my @data2 = map { chomp; [split /:::/] } <DATA>;
close DATA;

my %posts;
$posts{$_->[7]}++ foreach @data2;

foreach my $data (@data) {
$posts{$data} ||= 0; # default number of posts is zero
print <<"EOF";
<table width=100% border=0 cellpadding=3 cellspacing=1><tr>
<td width=50% bgcolor="$tablemid">
<img src="Board.gif" border=0 vspace=1 align="absmiddle">
<a href="http://www.site.com/board3.cgi?action=index&cat=$data">$data</a>
</td>
<td width=18% align="center" bgcolor="$tablemid"><font size=2>$posts{$data}</font></td>
<td width=21% align="center" bgcolor="$tablemid"><font size=2>??</font></td>
<td width=11% align="center" bgcolor="$tablemid"><font size=2></font></td></tr></table>
EOF
}

As another suggestion, you should try to use the CGI package for HTML outputs. It reads much nicer, because it's Perl actually.

-- Marcus



mike
User

Jul 5, 2001, 2:36 PM

Post #4 of 9 (2868 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hello,

Thanks so much for your help. Now here is my next project/problem lol. OK, I got all that to work, your coding was perfect. However, now I am working on displaying the links in each category. I am using my message board script that was threaded to do so, only i am displaying it a little different. Here is what I have now:

---------------------------------------------------------------------------

open (FILE, ">$datafile") || &errorman("Unable to open datafile5");
flock (FILE, 2);
print FILE "";
flock (FILE, 8);
close (FILE);
}

open (FILE, "$datafile") || &errorman("Unable to open datafile6");
&lock(FILE);
@messages = <FILE>;
&unlock(FILE);
close(FILE);

$messagecount = 0;
$threadcount = 0;



for ($a = 0; $a < @messages; $a++) {

($mnum[$a],$msub[$a],$mfollow[$a],$mname[$a],$memail[$a],$mdate[$a],$mip[$a],$mcat[$a],$message[$a],$linkname[$a],$linkurl[$a],$imageurl[$a],$chop) = split(/:::/,$messages[$a]);

$messagecount++;
if ($mfollow[$a] == 1) {
$threadcount++;
}
}




$threaded = 1;
$maximum = 1;
$maxdisplay = 50;
$displaycounter = 0;
$itzapizza = 0;
$remember = $mnum[0];
print<<"HTML";
<p><TABLE border=0 cellPadding=0 cellSpacing=2 height=1 width="100%">
<TR>
<TD>
<table align=center border=0 cellpadding=1 cellspacing=1 width="100%" bgcolor="$tabletop">
<tr>
<th align=left width="50%"><font size="2">Topic</font></th>
<th align=middle width="18%"><font size="2">Posted
By</font></th>
<th align=middle width="21%"><font size="2">Post On</font></th>
<th align=middle width="11%"><font size="2">Replies</font></th>

</tr>
<tr>
<td colspan="4">
HTML

for ($b = 0; $b < @messages; $b++) {
if ($form{'cat'} eq $mcat[$b]) {
if ($mfollow[$b] > 1) {

$itzapizza++;

}

else {

unless ($b == 0 || $threaded == 0) {


if ($itzapizza == 0) {

print "0\n";

}

else {

print "$itzapizza\n";
$itzapizza = 0;

}
print<<"HTML";
</font></td></tr></table>
HTML

$remember = $mnum[$b];

}

$displaycounter++;



print<<"EOF";
<table width=100% border=0 cellpadding=3 cellspacing=1><tr>
<td width=50% bgcolor="$tablemid">
<img src="SmallMessage.gif" border=0 vspace=1 align="absmiddle">
<a href="http://yoursite.com/forums/board3.cgi?action=display&num=$remember&user=$user">$msub[$b]</a>
</td>
<td width=18% align="center" bgcolor="$tablemid"><font size=2><a href=\"mailto:$memail[$b]\">$mname[$b]</a></font></td>
<td width=21% align="center" bgcolor="$tablemid"><font size=2>$mdate[$b]</font></td>
<td width=11% align="center" bgcolor="$tablemid"><font size=2>
EOF


}

if ($displaycounter >= $maxdisplay && $maximum == 1) {
$b = @messages; }

}

unless (@messages == 0 || $threaded == 0) {


if ($itzapizza == 0) {

print "0";

}

else {

print "$itzapizza";

}

print<<"HTML";
</font></td></tr></table>
</td>
</tr>
</table>
</TD>
</TR>
<TR>
</TABLE>

<P><table align=center border=0 cellpadding=1 cellspacing=1 width="100%" bgcolor="$tabletop">
<tr>
<td width="50%"><font size="1">All
times are EST</font></td>
<td align=right width="50%"><font size="2"><b>Powered by <a href="http://www.blabla.com" target="_blank">Blabla</a></b></font></td>
</tr>
</table>
<p>


HTML
&bot;
&stats3;
exit;
}
}
print<<"EOF";
</td>
</tr>
</table>
</TD>
</TR>
<TR>
</TABLE>

<P><table align=center border=0 cellpadding=1 cellspacing=1 width="100%" bgcolor="$tabletop">
<tr>
<td width="50%"><font size="1">All
times are EST</font></td>
<td align=right width="50%"><font size="2"><b>Powered by <a href="http://www.blabla.com" target="_blank">Blabla</a></b></font></td>
</tr>
</table>
<p>




EOF


---------------------------------------------------------------------------


Now, the problem is that it doesn't count the replies anymore, and it takes too long to load. Once you click the link it takes you to the page with the correct threaded info, like the replies and everything are there, but it doens't count the stuff on the main topic page which the coding I have pasted above. I hope you can help me, it is keeping me very frustrated at the moment. :) Thanks,

Mike





mhx
Enthusiast

Jul 6, 2001, 12:41 PM

Post #5 of 9 (2854 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hi mike,

sorry to tell you, but I'm stuck with your code. Even after throwing out nearly all HTML and after reformatting the code and replacing several parts to make it easier to understand for me, I just cannot figure what this code is supposed to do.
It would be of great help if you could supply me with an input file ($database) and if you could tell me what exactly the output is supposed to look like. Since the script does nothing but in a certain way converting the $database file into HTML, these should be sufficient information.
Another hint: if you name your variables other than $itzapizza, perhaps others also might get a slight idea what this could be used for ;-)
Perhaps it helps you a bit, here's the code I've reconstructed up to now (this is actually the part where I understand what the script is doing):

Code
my @fields = qw(num sub follow name email date ip cat 
message linkname linkurl imageurl);

open FILE, $datafile or errorman("cannot open $datafile: $!\n");
lock(FILE);

# The following map will create an array of hashes from the
# $datafile. This means each message will be stored as a hash
# table (with keys from @fields), and references to these
# hash tables are provided in the array @data. This makes
# the for-loop unneccessary, except for thread counting.
# Instead of keeping an endless amount of arrays, we just
# have one array. To access the 'imageurl' of the 5th
# message, just use '$data[4]{imageurl}', for instance.

my @data = map {
chomp; my @f = split /:::/;
scalar { map { $_ => shift @f } @fields }
} <FILE>;

unlock(FILE);
close FILE;

# Uncomment the following lines if you need $messagecount
# and $threadcount

# my $messagecount = scalar @data;

# my $threadcount;
# foreach( @data ) {
# $threadcount++ if $_->{follow} == 1;
# }

# Uncomment any needed global

# my $threaded = 1;
# my $maximum = 1;
# my $maxdisplay = 50;
# my $displaycounter = 0;
# my $itzapizza = 0;
# my $remember = $data[0]{num};

foreach( @data ) {
next unless $form{cat} eq $_->{cat};

#
# I'm not quite sure what the input looks like
# and what output is expected. I'm stuck!!!
#
}

-- Marcus



mike
User

Jul 6, 2001, 12:56 PM

Post #6 of 9 (2853 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hi,

OK, what exactly do you need to know? Here is a sample of the data file:
---------------------------------------------------------------------------

25:::testing:::1:::mike:::cgoe2003@aol.com:::06/18/01 at 13:38:06:::198.81.17.13:::Common_Questions:::hey::: :::::::::
26:::Re: testing:::2:::Mike:::cgoe2003@aol.com:::07/03/01 at 02:01:25:::172.182.221.103:::Common_Questions:::hey::::::::::::
24:::yo:::1:::mike:::cgoe2003@aol.com:::06/03/01 at 00:00:32:::172.182.196.245:::Chat:::testing::::::::::::

---------------------------------------------------------------------------

$itzapizza is supposed to be the number of replies to each post. Anyways, here is what the table foreach one should print out like:

---------------------------------------------------------------------------

<table width=100% border=0 cellpadding=3 cellspacing=1><tr>
<td width=50% bgcolor="$tablemid">
<img src="SmallMessage.gif" border=0 vspace=1 align="absmiddle">
<a href="http://site.com/forums/board3.cgi?action=display&num=$remember&user=$user">$msub[$b]</a>
</td>
<td width=18% align="center" bgcolor="$tablemid"><font size=2><a href=\"mailto:$memail[$b]\">$mname[$b]</a></font></td>
<td width=21% align="center" bgcolor="$tablemid"><font size=2>$mdate[$b]</font></td>
<td width=11% align="center" bgcolor="$tablemid"><font size=2>$Replies</font></td></tr></table>


---------------------------------------------------------------------------

If you need any other part of the coding or the output let me know. I have been working on this for the last 2 days, and I am stumped. Plus my code is a little messy so.. anyways how it works is just like WWW board. It is threaded and keeps track like that with follow-ups under the actual post. The follow-ups just have a number higher than 1. I am sure you could see that with the coding. But anyways, thanks a lot and if you need anything else let me know.

Mike




mhx
Enthusiast

Jul 6, 2001, 2:58 PM

Post #7 of 9 (2850 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hi Mike,

Thanks for the input file, it made some things a lot clearer to me. Seeing data that I can parse as a human makes it easier for me when parsing it with Perl.
I've extended the script I just posted so it will display the correct number of replies to a message. Since this is what you were interested in, I stopped here and let the part of re-implementing HTML and such stuff up to you.
My script runs well from the commandline, which is why I defined the %form hash and the $datafile above. Inserting your HTML at the points indicated or even modifying your own script should not be too complicated as you're in that more than I am.
If you should anyway have some questions, feel free to ask!

Code
#!/bin/perl -w 
use strict;
use warnings;

my $datafile = 'database.dat';
my %form = ( cat => 'Common_Questions' );

my @fields = qw(num sub follow name email date ip cat
message linkname linkurl imageurl);

open FILE, $datafile or errorman("cannot open $datafile: $!\n");
# lock(FILE);

# The following map will create an array of hashes from the
# $datafile. This means each message will be stored as a hash
# table (with keys from @fields), and references to these
# hash tables are provided in the array @data. This makes
# the for-loop unneccessary, except for thread counting.
# Instead of keeping an endless amount of arrays, we just
# have one array. To access the 'imageurl' of the 5th
# message, just use '$data[4]{imageurl}', for instance.

my @data = map {
chomp; my @f = split /:::/;
scalar { map { $_ => shift @f } @fields }
} <FILE>;

# unlock(FILE);
close FILE;

# Uncomment the following lines if you
# need $messagecount and $threadcount

# my $messagecount = scalar @data;

# my $threadcount;
# foreach( @data ) {
# $threadcount++ if $_->{follow} == 1;
# }

my $maximum = 1;
my $maxdisplay = 50;
my $displaycounter = 0;

my $reply;
my $remember = undef;

#
# Print HTML header here
#

foreach( @data ) {
# Ignore foreign categories
next unless $form{cat} eq $_->{cat};

# Increment reply counter and proceed
# with next iteration if we have follow-ups
++$reply and next if $_->{follow} > 1;

# Exit the loop if we reach limit
last if ++$displaycounter >= $maxdisplay && $maximum;

# Print the remembered thread beginning
PrintTopicLine( $remember, $reply ) if defined $remember;

# Reset the reply counter and remember the current entry
$reply = 0; $remember = $_;
}

# Print the leftover entry
PrintTopicLine( $remember, $reply ) if defined $remember;

#
# Print HTML footer here
#



### SUBS ###################################################

sub PrintTopicLine
{
my($data, $reply) = @_;

# Print HTML table entry
print "$data->{num}: $data->{sub} ($reply replies)\n";
}

-- Marcus



mike
User

Jul 6, 2001, 3:29 PM

Post #8 of 9 (2847 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hello,

OK, I am a little uncertain about a few things. OK, first, should I just make a separate script for this section, because I think it will be easier with all the strict tags and everything. Second, where this tag is:

my %form = ( cat => 'Common_Questions' );

how do I make it so that when it is called by

display.cgi?cat=CATNAME it will show it the correct category instead of Common_Questions. I am not very familiar with the strict call, so I need a little help. So do I need a parse tag at the top too, like


read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/</</ig;
$value =~ s/>/>/ig;
$value =~ s/\n/
/ig;
$form{$name} = $value;
}


or is it not necessary? I am very confused.

Thanks,

Mike




mhx
Enthusiast

Jul 6, 2001, 3:50 PM

Post #9 of 9 (2842 views)
Re: Problems Displaying Data [In reply to] Can't Post

Hi Mike,


In Reply To
OK, I am a little uncertain about a few things. OK, first, should I just make a separate script for this section, because I think it will be easier with all the strict tags and everything.

The fact that I used strict is mainly because I always use strict (except for tools not exceeding two lines of code ;-). I strongly recommend using strict, along with the -w switch. If your script doesn't run under strict and you don't want to patch it, that's no problem. Code that runs fine under strict runs as fine without. So it's up to you if you merge the code into your existing script or if you create a separate one.

In Reply To
Second, where this tag is:
my %form = ( cat => 'Common_Questions' );
how do I make it so that when it is called by
display.cgi?cat=CATNAME it will show it the correct category instead of Common_Questions.

As I said, this was only inserted for testing. If you want to parse CGI requests, use the CGI package. It is very well documented, see perldoc CGI. Using the non-OO interface of the CGI package, you can get the category by just saying

Code
use CGI qw(:standard); 
#
# lots of useful code
#
$category = param('cat');

Then, replace the line

Code
  next unless $form{cat} eq $_->{cat};

by

Code
  next unless $category eq $_->{cat};

Have a look at the CGI package. Far too many people still don't use it. It's the best help you can get when you write CGI scripts!
Hope this helps.

-- Marcus


 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives