Reputation: 31
I'm trying to find the number of positive (P) and negative integers (N), number of words with all lower case characters(L),all upper case characters(F), Number of words with the first character capital and the rest of characters lower case(U). List of words in alphabetical order together with the line number and the filename of each occurrence The following example illustrates the output of the program on sample input.
Hello! world my friend. ALI went to school. Ali has -1 dollars and 10 TL
Hello there my friend. VELI went to school. Veli has 10,
dollars and -10,TL
After you run your program,
>prog.pl file1 file2
the output you get is as follows:
N=2
P=2
L=18
F=4
U=4
-----------
ali file1 (1 1)
and file1 (2) file2 (2)
dollars file1 (2) file2 (2)
friend file1 (1) file2 (1)
has file1 (1) file2 (1)
hello file1 (1) file2 (1)
my file1 (1) file2 (1)
school file1 (1) file2 (1)
there file2 (1)
tl file1 (2) file2 (2)
to file1 (1) file2 (1)
veli file2 (1 1)
went file1 (1) file2 (1)
world file1 (1)
I tried to fill the entries,could you help me to deal with it?
#!/usr/bin/perl
$N= 0 ;
$P= 0 ;
$L= 0 ;
$F= 0 ;
$U= 0 ;
foreach __________ ( ____________) {__________________
or die("Cannot opened because: $!") ;
$lineno = 0 ;
while($line=<>) {
chomp ;
$lineno++ ;
@tokens = split $line=~ (/[ ,.:;!\?]+/) ;
foreach $str (@tokens) {
$N++ if ($str =~ /^-\d+$/) ;
$P++ if ($str =~ /^\d+$/) ;
$L++ if ($str =~ /^[a-z]+$/) ;
$F++ if ($str =~ /^[A-Z][a-z]+$/) ;
$U++ if ($str =~ /^[A-Z]+$/) ;
if ($str =~ /^[a-zA-Z]+$/) {
$str =~ __________________;
if ( (____________________) || ($words{$str} =~ /\)$/ ) ) {
$words{$str} = $words{$str} . " " . $file . " (" . $lineno ;
}
else {_______________________________________;
}}}}
close(FH) ;
foreach $w (__________________) {
if ( ! ($words{$w} =~ /\)$/ )) {
$words{$w} = ______________________;
}}}
print "N=$N\n" ;
print "P=$P\n" ;
print "L=$L\n" ;
print "F=$F\n" ;
print "U=$U\n" ;
print "-----------\n" ;
foreach $w (sort(keys(%words))) {
print $w," ", $words{$w}, "\n";
}
Upvotes: 0
Views: 164
Reputation: 69244
Here's how I'd write that program. But it won't get you many marks as it's a long way from the "fill in the blanks" approach that your teacher is using. But that's good, because your teacher's Perl is very dated.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my ($N, $P, $L, $F, $U);
my %words;
while (<>) {
my @tokens = split /[^-\w]+/;
foreach my $token (@tokens) {
$N++ if $token =~ /^-\d+$/;
$P++ if $token =~ /^\d+$/;
next unless $token =~ /[a-z]/i;
$L++ if $token eq lc $token;
$U++ if $token eq uc $token;
$F++ if $token eq ucfirst lc $token;
push @{$words{lc $token}{$ARGV}}, $.;
}
close ARGV if eof;
}
say "N=$N";
say "P=$P";
say "L=$L";
say "F=$F";
say "U=$U";
for my $word (sort { $a cmp $b } keys %words) {
print "$word ";
for my $file (sort { $a cmp $b } keys %{$words{$word}} ) {
print "$file (", join(' ', @{$words{$word}{$file}}), ') ';
}
print "\n";
}
Upvotes: 0
Reputation: 107040
A few hints, and I'll let you get on your way...
Perl has what is called a diamond operator. This operator opens all files placed on the command line (which is read into the @ARGS
array), and reads them line-by-line.
use strict;
use warnings;
use autodie;
use feature qw(say);
while my $line ( <> ) {
chomp $line;
say "The line read in is '$line'";
}
Try this program and run it as you would your program. See what happens.
Next, take a look at the Perl documentation for variables related to file handles. Especially take a look at the $/
variable. This variable is what used to break records. It's normally set to a new-line, so when you read in a file, you read it in line-by-line. You may want to try that. If not, you can fall back onto something like this:
use strict;
use warnings;
use autodie;
use feature qw(say);
while my $line ( <> ) {
chomp $line;
@words = split /\s+/, $line;
for my $word ( @words ) {
say "The word is '$word'";
}
}
Now you can use a hash to track which words were in each file and how many times. You can also track the various types of words you've mentioned. However, please don't use variables such as $U
. Use $first_letter_uppercase
. This will have more meaning in your program and will be less confusing for you.
Your teacher is teaching you the way Perl was written almost 30 years ago. This was back before God created the Internet. (Well, not quite. The Internet was already 10 years old, but no one outside of a few academics had heard of it). Perl programming has greatly evolved since then. Get yourself a good book on Modern Perl (that is Perl 5.x).
The pragmas at the beginning of my program (the use statements) do the following:
use strict
- Use strict syntax. This does several things, but the main thing is to make sure you cannot use a variable unless you first declare it. (using most likely my
). This prevents mistakes such as putting $name
in one place, and referring to $Name
in another place.use warnings
- This warns you of basic errors such as you're attempting to use a variable that isn't defined. By default, Perl assumes the variable is a null string or equal to zero if you use it in an arithmetic context. When you attempt to print or check a variable that hasn't been assigned a value. It probably means you have a logic mistake.The above two pragmas will catch 90% of your errors.
use autodie
- This will cause your program to automatically die in many circumstances. For example, you attempt to open a none existent file for reading. This way, you don't have to remember to check each instance of whether or not certain operations succeeded of failed.use feature qw(say)
- This allows you to use say
instead of print
. The say
command is just like print
, but automatically adds a new line on the end. It can make your code way cleaner and easier to understand.For example:
print "N=$N\n" ;
vs.
say "N=$N" ;
Upvotes: 2