user977154
user977154

Reputation: 1095

Perl code using a text file

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

Answers (8)

Joel Berger
Joel Berger

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

Toto
Toto

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

RC.
RC.

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

Zaid
Zaid

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 is 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

Simone-Cu
Simone-Cu

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

Tudor Constantin
Tudor Constantin

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

Dan
Dan

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

Christopher Neylan
Christopher Neylan

Reputation: 8272

Try:

open (FILE, 'census2008.txt') or die $!;

The open may be failing without you knowing it.

Upvotes: 1

Related Questions