Perl-код с использованием текстового файла - PullRequest
2 голосов
/ 11 декабря 2011

Почему мой Perl-код ничего не печатает?Я работаю над этим уже некоторое время, и я использую текстовый файл, который содержит тонну различных данных, каждый из моих массивов разделен запятой, означающей, что это столбец.

это мойкод:

#!/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

Ответы [ 8 ]

4 голосов
/ 11 декабря 2011

Лучший инструмент, который вам здесь поможет, это use strict; use warnings;.Обязательно ставьте его в начале каждого сценария, который вы пишете, так как это сэкономит вам массу времени на отладку тривиальных проблем.

Здесь есть пара i, в которых отсутствует их $ sigil.

Также рассмотрите возможность изучения поваренной книги по структуре данных Perl: perldoc perldsc.Массив хешей (технически hashrefs) будет более масштабируемым выбором структуры данных для хранения ваших данных.

1 голос
/ 11 декабря 2011

Помимо использования Text :: CSV, как предлагали другие, просто для забавы я переписал код так, как мог бы его написать. Он включает в себя множество предложений, сделанных здесь, и несколько моих личных стилей. Если у вас есть какие-либо вопросы по этому поводу, пожалуйста, задавайте. Также, если вы можете опубликовать пример данных, я могу проверить, работает ли он.

#!/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

Если у вас есть возможность установить Perl версии 5.14 или выше, вы можете использовать еще более четкий синтаксис, где push может напрямую ссылаться на ссылки, а each может давать рассматриваемый индекс, а также значение .

#!/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

Наконец, вот реализация, использующая Tie::Array::CSV, которую я написал, чтобы иметь возможность использовать файл CSV точно так же, как 2D-массив в Perl (то есть массив ArrayRefs). Он использует Text::CSV для анализа и Tie::File для доступа к линии. Это означает, что вам не нужно хранить все данные в памяти, как в предыдущих примерах.

#!/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
1 голос
/ 11 декабря 2011

Вы должны отменить буфер stdout.

Добавьте следующее после #!/usr/bin/perl

$| = 1;

Сказав это, вот еще пара вещей, которые я бы предложил:

1.) Как минимум use strict; (также рекомендуется use warnings)

Strict заставит вас использовать «my» для объявления переменных, где вы этого еще не сделали.Я не могу сказать вам, сколько раз я видел, как программист ищет и ищет ошибку, которую легко обнаружить при включении строгой проверки.(Опечатки в именах переменных являются общими)

2.) Используйте следующую команду для открытия

open($FILE, "<", 'census2008.txt') || die("Cannot open file!");

Это не только сообщит вам, если файл не может быть открыт для записи (из-за использования die), но использование $FILE вместо необработанного дескриптора файла приведет к автоматическому закрытию файла, когда он выходит из области видимости.

1 голос
/ 11 декабря 2011

Когда вы печатаете что-либо, завершение этого символа новой строкой приведет к немедленной печати, в противном случае текст отправляется в буфер печати, но буфер не очищается.

1 голос
/ 11 декабря 2011

Попробуйте:

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

Открытие может быть неудачным, если вы этого не знаете.

0 голосов
/ 11 декабря 2011

В строке есть проблема:

if($SumLevArray[$i] == " 040"){

Эта строка имеет значение true для многих значений $SumLevArray[$i], т. Е. "40", "040", " 00040 "

, если $SumLevArray[$i] является целым числомэта строка должна быть:

if($SumLevArray[$i] == 40){

, если $SumLevArray[$i] - строка, эта строка должна быть:

if($SumLevArray[$i] eq " 040"){
0 голосов
/ 11 декабря 2011

Для доступа к массиву вы используете i вместо $ i в качестве индекса.Кроме того, я не понимаю, что вы хотите делать внутри цикла while.

0 голосов
/ 11 декабря 2011

Попробуйте изменить первые строки кода на:

#!/usr/bin/perl

use strict;
use warnings;

$| = 1; #

open (FILE, 'census2008.txt');

После устранения появляющихся ошибок / предупреждений все должно быть в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...