Reputation: 1095
Why is my perl code not printing out anything? I have been working on this for a while now and i am using a text file which has a ton of different data which each on of my arrays are sepearated by a comma meaning it is a column.
this is my code:
#!/usr/bin/perl
open (FILE, 'census2008.txt');
my @SumLevArray;
my @StNameArray;
my @CtyNameArray;
my @PopEstimateArary;
my @BirthsArray;
my @DeathsArray;
$i = 0;
$temp = 0;
$lowestBirthRates = 100000000;
$highestBirthRates = 0;
$size = 0;
while (<FILE>)
{
chomp;
($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push (@SumLevArray, $sumlev);
push (@StNameArray, $stname);
push (@CtyNameArray, $ctyname);
push (@PopEstimateArary, $popestimate2008);
push (@BirthsArray, $births2008);
push (@DeathsArray, $deaths2008);
}
$size = @BirthsArray;
while ($i < $size)
{
if($SumLevArray[$i] == " 040"){
$temp = $BirthsArray[$i]/$PopEstimateArary[$i]/541;
if(($lowestBirthRates > $temp) &&($temp > 0)){
$lowestBirthRates = $temp;
}
if($highestBirthRates < $temp){
$highestBirthRates = $temp;
}
}
$i = $i + 1;
}
print "\n";
print "Lowest birth rate in LOW-STATE: ";
print $lowestBirthRates;
print " per 541\n";
print "Highest birth rate in HIGH-STATE: ";
print $highestBirthRates;
print " per 541\n";
print "In Washington:\n";
print " Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541\n";
print " Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541\n";
close (FILE);
exit
Upvotes: 2
Views: 180
Reputation: 20280
Beyond using Text::CSV as others have suggested, just for fun I have rewritten the code as I might have written it. It includes many of the suggestions made here and a few of my personal style choices. If you have any questions about it please ask. Also if you can post some sample data, I can check to see that it works.
#!/usr/bin/env perl
use strict;
use warnings;
my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;
my $filename = 'census2008.txt';
open (my $fh, '<', $filename) or die "Cannot open $filename: $!";
my %data;
while (<$fh>) {
chomp;
my ($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push (@{$data{SumLev}}, $sumlev);
push (@{$data{StName}}, $stname);
push (@{$data{CtyName}}, $ctyname);
push (@{$data{PopEstimate}}, $popestimate2008);
push (@{$data{Births}}, $births2008);
push (@{$data{Deaths}}, $deaths2008);
}
my $i = 0;
my $size = @{$data{Births}};
while ($i < $size) {
if ( $data{SumLev}[$i] eq " 040" ){
#if ( $data{SumLev}[$i] == 40 ){
my $temp = $data{Births}[$i] / $data{PopEstimate}[$i] / 541;
if( $lowestBirthRates > $temp && $temp > 0 ){
$lowestBirthRates = $temp;
}
if ( $highestBirthRates < $temp ){
$highestBirthRates = $temp;
}
}
$i++;
}
print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT
if you have the luxury of having Perl version 5.14 or greater installed, you can use an even clearer syntax, where push
can take references directly, and where each
can give the index in question as well as the value.
#!/usr/bin/env perl
use strict;
use warnings;
use 5.14.0;
my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;
my $filename = 'census2008.txt';
open (my $fh, '<', $filename) or die "Cannot open $filename: $!";
my %data = (
SumLev => [],
StName => [],
CtyName => [],
PopEstimate => [],
Births => [],
Deaths => [],
);
while (<$fh>) {
chomp;
my ($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push ($data{SumLev}, $sumlev);
push ($data{StName}, $stname);
push ($data{CtyName}, $ctyname);
push ($data{PopEstimate}, $popestimate2008);
push ($data{Births}, $births2008);
push ($data{Deaths}, $deaths2008);
}
while (my ($i, $births) = each $data{Births}) {
if ( $data{SumLev}[$i] eq " 040" ){
#if ( $data{SumLev}[$i] == 40 ){
my $temp = $births / $data{PopEstimate}[$i] / 541;
if( $lowestBirthRates > $temp && $temp > 0 ){
$lowestBirthRates = $temp;
}
if ( $highestBirthRates < $temp ){
$highestBirthRates = $temp;
}
}
}
print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT
Finally here is an implementation using Tie::Array::CSV
which I wrote to be able to use a CSV file just like a 2D array in Perl (i.e. Array of ArrayRefs). It uses Text::CSV
to do the parsing and Tie::File
to do line access. This means that you don't need to store all the data in memory like in the previous examples.
#!/usr/bin/env perl
use strict;
use warnings;
use Tie::Array::CSV;
my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;
my $filename = 'census2008.txt';
tie my @data, 'Tie::Array::CSV', $filename
or die "Cannot tie $filename: $!";
foreach my $row (@data) {
my ($sumlev, $stname, $ctyname, $popest, $births, $deaths) = @$row;
if ( $sumlev eq " 040" ){
#if ( $sumlev == 40 ){
my $temp = $births / $popest / 541;
if( $lowestBirthRates > $temp && $temp > 0 ){
$lowestBirthRates = $temp;
}
if ( $highestBirthRates < $temp ){
$highestBirthRates = $temp;
}
}
}
print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT
Upvotes: 1
Reputation: 91373
There is a problem in the line:
if($SumLevArray[$i] == " 040"){
This line is evaluated to true for many values of $SumLevArray[$i]
ie "40", "040", " 00040 "
if $SumLevArray[$i]
is an integer, this line should be:
if($SumLevArray[$i] == 40){
if $SumLevArray[$i]
is a string, this line should be:
if($SumLevArray[$i] eq " 040"){
Upvotes: 0
Reputation: 28197
You should unbuffer stdout.
Add the following after #!/usr/bin/perl
$| = 1;
Having said that, here are a couple other things I would suggest:
1.) At minimum use strict;
(use warnings
is also advised)
Strict will force you to use "my" to declare your variables where you don't already do so. I can't tell you the number of times I've seen a programmer search and search for a bug that is easily detectable when turning on strict checking. (Typos on var names is a common one)
2.) Use the following for open
open($FILE, "<", 'census2008.txt') || die("Cannot open file!");
This will not only inform you if a file can't be opened for writing (due to the use of die
),
but using $FILE
instead of a raw file handle will cause the file to be closed automatically when it
goes out of scope.
Upvotes: 1
Reputation: 37136
The best tool to help you out here is use strict; use warnings;
. Make it a point to put it at the top of every script you write as it will save you a ton of time debugging trivial issues.
Here, there are a couple of i
s that are missing their $
sigil.
Also, consider studying the Perl data structure cookbook: perldoc perldsc
. An array of hashes (technically hashrefs) would be a more scalable choice of data structure to store your data.
Upvotes: 4
Reputation: 1129
To access the array you use i instead of $i as index.
Beyond this, I don't understand what you want to do inside the while loop.
Upvotes: 0
Reputation: 26861
Try modifying your first lines of code to:
#!/usr/bin/perl
use strict;
use warnings;
$| = 1; #
open (FILE, 'census2008.txt');
After solving the errors/warnings that are appearing, all should be ok.
Upvotes: 0
Reputation: 10786
When you print something, ending it with a newline will cause it to be printed immediately, otherwise the text goes to the print buffer but the buffer is not flushed.
Upvotes: 1
Reputation: 8272
Try:
open (FILE, 'census2008.txt') or die $!;
The open may be failing without you knowing it.
Upvotes: 1