Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Oky My teacher has asked us to take a text file that he has created and count the number of paragraphs, sentances, and vowels, Then take the words that start with consonants and UC them. Then take words that start with vowels and lc them.

I have written what I thought would be correct however I keep getting these errors:

Name "main::para" used only once: possible typo at Dadis_Tanya_lab3.pl line 8.

Name "main::sen" used only once: possible typo at Dadis_Tanya_lab3.pl line 13.

Name "main::vow" used only once: possible typo at Dadis_Tanya_lab3.pl line 19.

and I don't know what it means by used only once.

Here is my code below. Please help a new perl student.

#!/usr/bin/perl -w %count = ("vow",0,"con",0,"word",0,"para",0,"sen",0); while ( <> ) { $b = <>; if ( length($b = $_) != 0 ) { $para++; } $a = $_; while ( $a =~ /[.?!]/) { $sen++; $a = $'; } $a = $_; while ( $a =~ /[aeiou]/i ) { $vow++; $a = $'; } } while ( <> ) { $a = $_; while ( $a =~ /\b([a-z],[^aieou])/i) { $str = $` . uc($1); $a = $'; } $a = $_; while ( $a =~ /\b([aeiou])/i) { $str = $` . lc($1); $a = $'; } } print $b; print $a; foreach $value (keys %count) { print "$value"; } $ *lab3.pl lab3.txt

Replies are listed 'Best First'.
Re: New perl student... feeling stupid
by FouRPlaY (Monk) on May 18, 2001 at 20:57 UTC
    What's happend is that you've created a hash %count to contain all your information, but in your code, you use scalar variables $vow, $para, etc, etc.

    What you want is $count{'vow'}++ for vowels, $count{'para'}++ for paragraphs, etc, etc...



    FouRPlaY
    Learning Perl or Going To die() Trying

      Hrmmm I see... and I changed my code to reflect your advice.. it makes sence to me, however, now my program just hangs. It will start to run the program but there is no out put. it just sits there.

      Thanks for your help by the way..

      I really apreciate it.

      I am really new to perl. tanya

        the "diamond" operator <> attempts to read a line from the file whose name you pass on the command line. (e.g. ./myscript.pl file.txt) If you pass more than one filename on the command line, it will loop over all the lines in each file.

        Read up on <> in perldoc perlop

        If it runs out of command-line arguments and you try to read from it, then it attempts to read from STDIN (in this context, the keyboard). What your code is doing is reading in the file once, on the first pass. You think it's going to read it again when you say  while ( <> ) {, but what it's actually doing is attempting to read another file whose name was passed to it on the command line. But there is no such thing, so it just sits there expecting input from the keyboard (Control-D is the symbol for "end of file", so try hitting that a few times and see what happens).

        Moral of the story: don't do it that way =) Loop through the file *once* and do all your counting on that one run through it.

        HTH

        perl -e 'print "How sweet does a rose smell? "; chomp ($n = <STDIN>); +$rose = "smells sweet to degree $n"; *other_name = *rose; print "$oth +er_name\n"'
(boo) Re: New perl student... feeling stupid
by boo_radley (Parson) on May 18, 2001 at 21:04 UTC
    this is a very accurate and concise error :)
    see, you have, for instance
    $vow++
    but you never bother to print it out, or manipulate it in any fashion.
    I imagine you'd want to put it into the "vow" bucket in your hash called count, and then print that out later, but I'm really just guessing there.
    To sum up, you're getting this error message becuase you really are using these variables only once!

    updated : corrected typeo

Re: New perl student... feeling stupid
by mirod (Canon) on May 18, 2001 at 22:29 UTC

    You have more problems than just this one I am afraid.

    As I don't want to solve the exercise for you here is just a piece that should put you on the right tracks::

    #!/usr/bin/perl -w use strict; # in addition to using -w this will # help you find more errors # if you use strict then you have to declare your variables, usually u +sing my my %count = ("para",0,"sen",0); while ( <> ) # read a record (a line here) and set $_ { # a paragraph is any line that has at least one non-space characte +r if ( /\S/ ) { $count{para}++; } # the g modifier allows you to loop through the string # matching successive occurences of the pattern while ( /[.?!]/g) { $count{sen}++; } # use s/// to substitute the pattern # \w is a word character, # $1 is the text that was matched between the () # /g does the substitution for all matches in the string # /e evaluates the right part expression lc($1) s/([aeiou]\w*)/lc($1)/eig; } # this is how you print a hash foreach my $value (keys %count) { print "$value: $count{$value}\n"; }

    You should be able to finish the assignement from there. But you'd better figure out exactly what this snippet is doing and why or it might be difficult for you to answer questions from your teacher as to what goes on there.

    I have a question for the regexp experts by the way, I thought you needed to backslash the . in the character class, but it seems that it works fine (matching just the dot character) without it. Is this a new behaviour (I am using 5.6.1) or was . just '.' in a character class in older versions?

      A period in a character class has always matched a literal period. Character classes have their own set of metacharacters, unrelated to the regular expression metacharacters.
      In a character class, a dot is a dot. Outside of the brackets, though, it is a wildcard.
Re: New perl student... feeling stupid
by AidanLee (Chaplain) on May 18, 2001 at 21:00 UTC
    try perldiag for information on warnings and errors you recieve. Hint: it's being raised because you have the -w switch turned on (this is a good thing. trust me.)
Re: New perl student... feeling stupid
by diarmuid (Beadle) on May 18, 2001 at 22:13 UTC
    oops... I think you have gone astray somewhere there ...

    firstly just declare the hash

    my (%count);
    Now where you have $para++;$sen++;$vow++; replace them with$count{'para'}++; etc....

    Finally in your print statement you need both the key (para,sen,vow) and the values (2,5 ,whatever )so replace print "$value"; with print "$value : $count{$value};
    You should probably replace the $value with $key because it is misleading (it actually is the key and not/ the value.

    What you were doing was creating 3 new variables which had nothing to do with your script.

    I just had a look at the rest of you script and it's a bit of a mess :-) I dont have time now but here's how I would count the sentences and vowels

    undef $/; while(<>){ my @chars=split(//,$_); foreach my $char (@chars) { $count{'vow'}++ if(/[aeiou]/); $count{'sen'}++ if(/\./); }
    Diarmuid