0
#!/usr/bin/perl
use strict;
use warnings;

sub paragraph
{
open my $file, "<", "dict.txt" or die "$!";
my @words = <$file>;
close $file;

print "Number of lines:";
my $lines = <>;

print "Max words per line:";
my $range = <>;

for(my $i = 0; $i<$lines; $i++){
    my $wordcount = int(rand($range));

        for(my $s = 0; $s<=$wordcount; $s++){
            my $range2 = scalar(@words);
            my $word = int(rand($range2));
            print $words[$word]." ";

                if($s==$wordcount){
                    print "\n";}
                    }
                    }
                    }
paragraph;

I'm trying to learn programming, so I just wrote this simple script.

When running this code, I am getting use of uninitialized value errors... I can't figure out why, but I sure I am just overlooking something.

3
  • Why are you trying to read from FILE? Using > in the call to open opens the handle only for writing. Commented Jan 11, 2011 at 2:38
  • Could you briefly explain what do you want the script to do? Commented Jan 11, 2011 at 2:46
  • Oh yeah. I'm merely trying to read a dictionary file into an array, choose words from that array at random, and print those words out into a paragraph whose number if lines and approximate line length is specified by the user. ------------ And Anon, should i be using "<"? I've changed it to open(FILE, "dict.txt") since and its still not working. --------- And the exact error is "Use of uninitialized value within @words in concatenation (.) or string at poemgen.pl line 19, <> line 2. ". Commented Jan 11, 2011 at 2:49

2 Answers 2

3

These two lines open the dict.txt file for writing and then try to read from it.

open FILE, ">dict.txt" or die $!;
my @words = <FILE>;

Since you can't read from a write-only file, it fails. If the file was writable, then it is empty now - sorry about your nice word list. Suggestion:

open my $file, "<", "dict.txt" or die "$!";
my @words = <$file>;
close $file;

Also, please learn to indent your braces in an orthodox fashion, such as:

sub go
{
    print "Number of lines:";
    my $lines = <>;
    print "Max words per line:";
    my $range = <>;
    for (my $i = 0; $i<$lines; $i++){
        my $wordcount = int(rand($range));
        for (my $s = 0; $s<$wordcount; $s++){
            my $range2 = 23496;
            my $word = int(rand($range2));
            my $chosen = @words[$word];
            print "$chosen ";
            if ($s=$wordcount){
                print "\n";
            }
        }
    }
}

Also leave a space between 'if' or 'for' and the open parenthesis.

Your assignment if ($s = $wordcount) probably isn't what you intended; however, the condition if ($s == $wordcount) will always be false since it is in the scope of a loop with the condition $s < $wordcount. You need to rethink that part of your logic.

On average, you should choose a better name for your function than go. Also, it is probably better to invoke it as go();.


When I test compile your script, Perl warns about:

Scalar value @words[$word] better written as $words[$word] at xx.pl line 19.

You should fix such errors before posting.

You have:

my $range2 = 23496;
my $word = int(rand($range2));

Unless you have more than 23,496 words in your dictionary, you will likely be accessing an uninitialized word. You should probably use:

my $range2 = scalar(@words);

That then just leaves you with some logic problems to resolve.


Given 'dict.txt' containing:

word1
word2
word3
word4
nibelung
abyssinia
tirade
pearl

And 'xx.pl' containing:

#!/usr/bin/env perl

use strict;
use warnings;

open my $file, "<", "dict.txt" or die $!;
my @words = <$file>;
close $file;

sub go
{
    print "Number of lines: ";
    my $lines = <>;
    print "Max words per line: ";
    my $range = <>;
    my $range2 = scalar(@words);
    for (1..$lines)
    {
        for (1..$range)
        {
            my $index = int(rand($range2));
            my $chosen = $words[$index];
            chomp $chosen;
            print "$chosen ";
        }
        print "\n";
    }
}

go();

When I run it, I get:

$ perl xx.pl
Number of lines: 3
Max words per line: 4
word4 word3 word4 nibelung 
abyssinia pearl word1 tirade 
word3 word1 word3 word2 
$
Sign up to request clarification or add additional context in comments.

5 Comments

I'm still getting the error. "Use of uninitialized value within @words in concatenation (.) or string at".....
Yeah I noticed, I rewrote it to <= That should work...right? Also, the script still doesn't work haha. Any reason why that should be? Thanks
Yeah, I fixed that scalar issue (I think) after posting. The dictionary I used was the one standard with the my os, found in usr/shared/dict... I'm fairly certain that is the length, but even after trying your fix I was still met with the error "Use of uninitialized value within @words in concatenation (.) or string at paragen.pl line 23, <> line 2"------ Line 23 looks like this now: print $words[$word]." ";
Oh wow, Im stupid haha. I seems that I was trying to load an "alias" of the dictionary file... hehe. Silly mac conventions huh? :P Well I really appreciate all of your help. Thanks a lot!
Oh...I see...yes...I've not bothered with aliases where I do 'work'; I use them where I play, occasionally. When I moved 'dict.txt' to 'dict.original' and then created 'dict.txt' as an alias via Finder, then I got a 47KiB file (wow!) that opened with open (cat) but was 'garbage'...Don't use aliases on MacOS X! When all else fails, print out what is in your array that you read in. You might be better off chomping as you read, though as you might be reading 23K words and printing a few dozen, maybe chomping on demand is in fact more efficient.
1

Some more bugs:

        if($s=$wordcount){

You need == here.

3 Comments

Oh yeah, thanks. Any idea why I'm getting that error though? Any insight would be greatly appreciated
you should use $words[$word] to access array value. Perl is human language-like, @ means these/those, $ means the. When you refer to a single element in an array, you change from @ to $.
Yeah, I did that awhile back... I shouldve edited my orignal post reflecting that... Sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.