http://www.perlmonks.org?node_id=1216483

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

The program tries to calculate the circumference of a circle, depending on the input.

#!/usr/bin/env perl use strict; use warnings; use utf8; use feature "say"; use Math::Trig; say "What is the radius?"; my $radius= <STDIN>; chomp ($radius); if ($radius==0) { say "circumference= ", $radius; } elsif ($radius<0) { say "Radius should be greater than 0"; } else { my $a = 2*pi; my $c = $a * $radius; say "circumference= ", $c }

The problem is that if the value is lower than zero, the program stops. And I want it to continue till there is a positive answer or zero.

I tried it with a submodule, but I have to switch off the strict command to make it work.

It should be easy of course, but any help is greatly appreciated.

Replies are listed 'Best First'.
Re: loop problem
by karlgoethebier (Abbot) on Jun 12, 2018 at 17:13 UTC
    "...if the value is lower than zero, the program stops..."

    Probably your program works as designed?

    As our beloved leader already mentioned there is no loop in your program.

    As an alternative you can jump to a label:

    #!/usr/bin/env perl use strict; use warnings; use feature "say"; use Math::Trig; CALC: { say "What is the radius?"; my $radius = <STDIN>; chomp($radius); if ( $radius == 0 ) { say "circumference= ", $radius; } elsif ( $radius < 0 ) { say "Radius should be greater than 0"; goto CALC; } else { my $a = 2 * pi; my $c = $a * $radius; say "circumference= ", $c; } } __END__

    Please note: Some say this style is a bad habit AKA the root of all evil.

    Best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: loop problem
by BrowserUk (Patriarch) on Jun 12, 2018 at 16:39 UTC

    Where is your loop?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
      There is no loop in this code. I tried it with a submodule. Like this:
      #!/usr/bin/env perl # use strict; use warnings; use utf8; use feature "say"; use Math::Trig; sub intro { say "What is the radius?"; our $radius= <STDIN>; chomp ($radius); our $a = 2*pi; our $c = $radius * $a } intro(); if ($radius==0) { say "circumference= ", $radius; } elsif ($radius<0) { say "Radius should be greater than 0"; intro(); } else { say "circumference= ", $c }

      But you have to switch off the strict command to make it work. And then it still doesn't work like I want it to.

      How to create the loop I want?

        I tried it with a submodule.

        In this context, the proper word for "submodule" is "subroutine."


        Give a man a fish:  <%-{-{-{-<

        What error does strict throw? Works fine for me as-is on 5.26.1.

        Anyway, here's an example of how to get what you want:

        my $radius = -1; until ($radius >= 0){ say "What is the radius?"; $radius= <STDIN>; chomp ($radius); say "radius must be >= 0. Try again..."; }
Re: loop problem
by kcott (Archbishop) on Jun 13, 2018 at 12:18 UTC

    G'day WisDomSeeKer34,

    Here's how I might tackle this:

    #!/usr/bin/env perl use strict; use warnings; use feature 'say'; use constant PI => 4 * atan2 1, 1; say 'Type radius (>=0) or just hit Return to exit.'; while (1) { print 'Radius: '; chomp(my $radius = <>); last unless length $radius; if ($radius =~ /^[+-]?(?:\d+|\d*[.]\d+)$/) { if ($radius < 0) { say "Radius [$radius] is less than zero. Try again."; next; } say 'Circumference: ', 2 * PI * $radius; } else { say "Invalid radius [$radius]. Try again."; next; } }

    Notes:

    • You don't need the utf8 pragma. Read its documentation to see what it's for; note the bold text telling you what it's not for.
    • Consider whether you really want to load a module and all of its functions. As you only wanted pi, you could have loaded just that: "use Math::Trig 'pi';". It isn't really a huge deal with a tiny script like this; however, when you start writing more substantial code, it will matter. I didn't bother with a module for this at all: I just took the first example from the constant pragma.
    • For this type of task, consider a loop that you can break out of (with last) or restart from somewhere in the middle (with next).
    • Consider the user's exit condition. I've used "just hit Return"; typing "q", "quit", "exit" are all valid but makes the user do more work. In another scenario, hitting Return might take a default value, so something different is needed to exit.
    • Note the use of print for the prompt (without newline); and the use of say for the feedback (with newline).
    • You can add another 'last' after printing the circumference if you don't want this to keep looping. Seek advice from your users on this: if they're sitting there with a long list of radii, they may not appreciate having to type the command repeatedly for each one.
    • The regex may look complicated but actually isn't. It's basically just an optional, leading sign followed by two alternatives (i.e. int or float). See perlre if this is unfamiliar.

    Example output:

    $ ./pm_1216483_loop_qanda.pl Type radius (>=0) or just hit Return to exit. Radius: 123.456 Circumference: 775.696925283163 Radius: q Invalid radius [q]. Try again. Radius: 0 Circumference: 0 Radius: +0 Circumference: 0 Radius: -0 Circumference: 0 Radius: 0.00000001 Circumference: 6.28318530717959e-08 Radius: +0.00000001 Circumference: 6.28318530717959e-08 Radius: -0.00000001 Radius [-0.00000001] is less than zero. Try again. Radius: .00000001 Circumference: 6.28318530717959e-08 Radius: +.00000001 Circumference: 6.28318530717959e-08 Radius: -.00000001 Radius [-.00000001] is less than zero. Try again. Radius: 1 Circumference: 6.28318530717959 Radius: -1 Radius [-1] is less than zero. Try again. Radius: 1. Invalid radius [1.]. Try again. Radius: .1 Circumference: 0.628318530717959 Radius: load of rubbish Invalid radius [load of rubbish]. Try again. Radius: $

    — Ken

Re: loop problem
by BillKSmith (Monsignor) on Jun 13, 2018 at 13:41 UTC
    About two weeks ago, you asked the same question Looking for a loop about another program. All of the answers that you received should apply here. Please explain why you are unable to use them.
    Bill
Re: loop problem
by rizzo (Curate) on Jun 12, 2018 at 22:27 UTC
    Another example using a loop:

    #!/usr/bin/env perl use strict; use warnings; use feature "say"; my $radius; for(;;) { say "Enter radius:"; $radius = <stdin>; last if $radius >= 0 ; say "error : radius must be >= 0"; } say "circumference: ", 2*3.14*$radius;
Re: loop problem
by monsenhor (Novice) on Jun 12, 2018 at 22:17 UTC
    #!/usr/bin/env perl use strict; use warnings; use utf8; use feature "say"; use Math::Trig; &ask; sub ask{ say "What is the radius?"; my $radius= <STDIN>; chomp ($radius); if ($radius==0) { say "circumference= ", $radius; } elsif ($radius<0) { say "Radius should be greater than 0"; &ask; } else { my $a = 2*pi; my $c = $a * $radius; say "circumference= ", $c } }
Re: loop problem
by Anonymous Monk on Jun 13, 2018 at 06:07 UTC

    I downloaded and ran what you posted exactly as is and it works fine. Perhaps you have a typo in the copy you are executing.

Re: loop problem
by Anonymous Monk on Jun 13, 2018 at 06:10 UTC

    Oops I misread your post. Never mind.

Re: loop problem
by Anonymous Monk on Jun 15, 2018 at 18:45 UTC
    Ask your teacher for help with your homework ...