Reputation: 370
I'm trying to accomplish a task which I did in another programming language, but Perl seems a bit different and I'm struggling.
I need to build a basic database and this database should hold the strings according to their first letter.
For example, when I give this input : SQL AHT NFK IOS C64 SQL AHT END
The desired output would be :
A – E: AHT C64
F – J: IOS
K – O: NFK
P – T: SQL
U – Z:
But when I give, for example, AAA BBB END, I get tons of errors and all of them are very similar:
Argument "AAA" isn't numeric in addition (+) at proje.pl line 76 <STDIN> line 3.
I'm putting all the code because I don't have any idea what is the reason of this error. I've checked other questions but I didn't help me a lot.
use warnings;
sub doesExistInDatabase {
my ($abbreviation) = @_;
my @database = @_;
my $boolean = 0;
for(my $c = 1; $c < 20; $c++){
for(my $d = 0; $d < 5; $d++){
if($database[$c][$d] eq ($abbreviation)){
$boolean = 1;
}
}
}
return $boolean;
}
$database[0][0] = "A-E";
$database[0][1] = "F-J";
$database[0][2] = "K-O";
$database[0][3] = "P-T";
$database[0][4] = "U-Z";
for(my $i = 1; $i < 20; $i++){
for(my $k = 0; $k < 5; $k++){
$database[$i][$k] = "";
}
}
@numberOfElements = (0,0,0,0,0);
while($numberOfElements[0] < 20 and $numberOfElements[1] < 20 and $numberOfElements[2] < 20
and $numberOfElements[3] < 20 and $numberOfElements[4] < 20){
my $abbreviation = <STDIN>;
chomp($abbreviation);
my @chars = split //, $abbreviation;
my $existing = doesExistInDatabase($abbreviation, @database);
if($abbreviation eq "END"){
last;
}
if($existing == 0){
if($chars[0] eq "A" or $chars[0] eq "B" or $chars[0] eq "C" or
$chars[0] eq "D" or $chars[0] eq "E"){
$numberOfElements[0]++;
$database[$numberOfElements[0]][0] = $abbreviation;
}
if($chars[0] eq "F" or $chars[0] eq "G" or $chars[0] eq "H" or
$chars[0] eq "I" or $chars[0] eq "J"){
$numberOfElements[1]++;
$database[$numberOfElements[1]][0] = $abbreviation;
}
if($chars[0] eq "K" or $chars[0] eq "L" or $chars[0] eq "M" or
$chars[0] eq "N" or $chars[0] eq "O"){
$numberOfElements[2]++;
$database[$numberOfElements[2]][0] = $abbreviation;
}
if($chars[0] eq "P" or $chars[0] eq "Q" or $chars[0] eq "R" or
$chars[0] eq "S" or $chars[0] eq "T"){
$numberOfElements[3]++;
$database[$numberOfElements[3]][0] = $abbreviation;
}
if($chars[0] eq "U" or $chars[0] eq "V" or $chars[0] eq "W" or
$chars[0] eq "X" or $chars[0] eq "Y" or $chars[0] eq "Z"){
$numberOfElements[4]++;
$database[$numberOfElements[4]][0] = $abbreviation;
}
}
}
print("\n$database[0][0]: ");
for(my $x = 1; $x < $numberOfElements[0]+1; $x++){
printf(" " + $database[$x][0]);
}
print("\n$database[0][1]: ");
for(my $x = 1; $x < $numberOfElements[0]+1; $x++){
printf(" " + $database[$x][1]);
}
print("\n$database[0][2]: ");
for(my $x = 1; $x < $numberOfElements[0]+1; $x++){
printf(" " + $database[$x][2]);
}
print("\n$database[0][3]: ");
for(my $x = 1; $x < $numberOfElements[0]+1; $x++){
printf(" " + $database[$x][3]);
}
print("\n$database[0][4]: ");
for(my $x = 1; $x < $numberOfElements[0]+1; $x++){
printf(" " + $database[$x][4]);
}
Upvotes: 0
Views: 3382
Reputation: 6553
You can make your code a lot more readable and avoid those multidimensional arrays and C-style loops at the same time. A simple stringwise comparison is all you need in order to sift your terms into buckets:
use strict;
use warnings;
use Data::Dump;
sub bucketize {
my %buckets = (
'A-E' => {},
'F-J' => {},
'K-O' => {},
'P-T' => {},
'U-Z' => {},
);
for my $term (@_) {
for my $bucket (reverse(sort(keys(%buckets)))) {
if ($term gt $bucket) {
$buckets{$bucket}{$term}++;
last;
}
}
}
return \%buckets;
}
my $hash_ref = bucketize(qw(SQL AHT NFK IOS C64 SQL AHT));
dd($hash_ref);
Output:
{
"A-E" => { AHT => 2, C64 => 1 },
"F-J" => { IOS => 1 },
"K-O" => { NFK => 1 },
"P-T" => { SQL => 2 },
"U-Z" => {},
}
Upvotes: 2
Reputation: 3777
In perl the operator for string concatenation is . (period) not + (plus) which you have used:
printf(" " + $database[$x][0])
Should be:
printf(" " . $database[$x][0])
Or just:
print " $database[$x][0]"
When you have more knowledge of perl, maybe you'll want to take a look at this solution:
my(@group,%group) = qw(A-E F-J K-O P-T U-Z);
while(<>){
my $abbr=$_; chomp($abbr);
$group{$_}{$abbr}++ for grep $abbr=~/^[$_]/i, @group;
}
print "$_: ".join(" ",sort keys %{$group{$_}})."\n" for @group;
Test:
for i in SQL AHT NFK IOS C64 SQL AHT END AAA BBB END PERL;do echo $i;done|perl program.pl
A-E: AAA AHT BBB C64 END
F-J: IOS
K-O: NFK
P-T: PERL SQL
U-Z:
Upvotes: 0