in reply to Stdin for just numbers.

If you really want to go with this sort of "extended dialog" via stdin, you should check out Term::ReadLine.

Here's one way to structure things so that the coding is easier. (I'm just going with basic usage in this example - the module has various options and extra methods to make things easier for the person who is typing, such as keeping a history of responses, so they can be recalled and reused, etc. Notice that Term::ReadLine strips off the newline characters for you.)

#!/usr/bin/perl use strict; use warnings; use Term::ReadLine; my $term = Term::ReadLine->new(); my @prompts = ( "the starting amount", "your current age", "the age you want to retire", "amount deposited per year", "the annual interest rate", "expected retirement money" ); my %responses; for my $prompt ( @prompts ) { my $response = ''; until ( $response =~ /^\d+$/ ) { $response = $term->readline( "Enter $prompt: " ); last unless defined( $response ); if ( $response =~ /\D/ ) { warn "Numeric answers only, please. Try again.\n"; } elsif ( $prompt eq "the age you want to retire" and $response < $responses{"your current age"} ) { warn sprintf( "We can't change the past. Give me a number +> %d\n", $responses{"your current age"} ); $response = ""; } } $responses{$prompt} = $response if ( defined( $response )); } printf "\nThank you for your %d answers\n", scalar keys( %responses ); for ( @prompts ) { print " $_ : $responses{$_}\n" if ( exists( $responses{$_} )); }
(There are different "flavors" of Term::ReadLine that you can use; your perl version probably has a "default" version that will suit your needs.)

Replies are listed 'Best First'.
Re^2: Stdin for just numbers.
by BillKSmith (Monsignor) on Mar 16, 2015 at 13:30 UTC
    A module is definitely the way to go. I would prefer IO::Prompt::Hooked. It works on all operating systems and provides validation and retry.
    Bill

      You could also use IO::Prompter, which I only recently learned about.

      #!/usr/bin/perl use strict; use warnings; use feature qw/say/; use IO::Prompter; my %responses = (); my @prompts = ( ["startamount", "the starting amount", ""], ["startage", "your current age", ""], ["endage", "the age you want to retire", sub { $_ >= $r +esponses{'startage'} } ], ["yearlydeposit", "amount deposited per year", ""], ["annualinterest", "the Annual interest rate", ""], ["expectedmoney", "Expected Retirement Money", ""], ); foreach my $prompt (@prompts) { $responses{$prompt->[0]} = prompt "Enter $prompt->[1]:", -num => $ +prompt->[2] } foreach (sort keys %responses) { say "$_: $responses{$_}"; }

      There's probably a better way of specifying empty constraints -- though the OP will likely some constraints that goes beyond "it's a number" imposed on most of the input.

      ++ for recommending my module (IO::Prompt::Hooked). I actually implemeneted a solution to the OP's question using IO::Prompt::Hooked last night, and it looked (in my opinion) great. ...but it became late, and I was too tired to submit a post around it. :)

      Anyway, this is exactly the sort of thing that IO::Prompt::Hooked aims to simplify.


      Dave