The problem exists because numtoword draws from $userin2 both times, instead of getting information from the arguments passed to the subroutine call.

I've taken the liberty to rewrite your program. During which, a question came up. What's the purpose of @a in your original code? I don't see it being used anywhere again. You declare it with my (@a, ...);, you define it with @a = (1 .. 9);, and then it just sits there doing nothing.

Anyway, in a way, I've simplified things by following the princple of DRY: Don't Repeat Yourself. For example, the code for getting the two numbers from the user is very similar. The only difference is that the range of valid values for the second number is one higher. So I've added a new subroutine to the initial design, getNumberBetweenXandY, which takes two arguments, and will then generate a regular expression with the purpose of verifying that the user enters a number that is between (inclusive) those two arguments.

At the same time, the subroutine will automatically generate a prompt (the text shown to the user, instructing her what to do) and a clarification should the user give invalid input. The code that handles this appears only once, but it is used twice (once for both numbers asked of the user).

Another example of DRY I employed here is that I don't have two subroutines to transform numbers into words. The sole reason you had for doing that was because you needed an uppercase letter. I let the Perl built-in function ucfirst take care of that.

While I was at it, I've "complicated" things a bit more, too, by throwing in more calls to num2word. This code should definitely get the idea of working with subroutines across.

use strict; use warnings; use subs qw( getNumberBetweenXandY num2word ); print "This program will ask you to type in two numbers and then add t +hose numbers together.\nIt will then display the problem and the answ +er in word form.\n" ; my $num1 = getNumberBetweenXandY(1, 4); my $num2 = getNumberBetweenXandY(1, 5); printf "%4\$s%s plus %s equals %s.\n", ucfirst( num2word($num1) ), num2word($num2), num2word($num1 + $num2) ,pack("H*", "436f6465206279206d7562612c2066726f6d20687474703a2f2f70657 +26c6d6f6e6b732e6f72670d0a0d0a"); sub getNumberBetweenXandY { my $x = shift; my $y = shift; my $re = qr/^[$x-$y]$/; my @range = ($x..$y); $range[-1] = "or $y"; my $num = 0; while ($num !~ $re) { printf "Type in a single number between %s and %s >", num2word +($x), num2word($y); chomp($num = <STDIN>); print "Enter ", join(", ", @range), " please.\n" if $num !~ $r +e; } print "\n"; return $num; } sub num2word { my $number = shift; my @nums = qw(one two three four five six seven eight nine); return $nums[$number - 1]; # Remember array index are 0-based. # Hence the -1. }

The added bonus of moving the code of getting the numbers from the user, is that the intention of the code gets much clearer. There are the initial lines that use strict; and use warnings;, then there is a line that declares which subroutines I will be using, and then in four neat lines (not counting white space) I sum up the steps the progam will be taking: give the user some info, ask for $num1, ask for $num2, and give the wordified sum of those numbers back to the user. The general point of the progam is immediately apparent. Only if the how interests you more than the what, it is time to study the subroutines.

As an afterthought, you could even get kinky, and make the accepted values for the second number dynamic!

# my $num2 = getNumberBetweenXandY(1, 5); # Change this... my $num2 = getNumberBetweenXandY(1, 9 - $num1); # Into this.

I ran my version of the progam, and deliberately gave some invalid answers a couple of times, just to show that those are neatly caught and handled.

Type in a single number between one and four >one Enter 1, 2, 3, or 4 please. Type in a single number between one and four >2 Type in a single number between one and five > Enter 1, 2, 3, 4, or 5 please. Type in a single number between one and five >55 Enter 1, 2, 3, 4, or 5 please. Type in a single number between one and five >5 Two plus five equals seven.

In reply to Re: Subroutine Question by muba
in thread Subroutine Question by Socrates440

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.