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

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

i cant figure out why my elsif statement isnt being executed it just executes the first if statement, im new to perl hehe

#!/usr/bin/perl use warnings; print "do you want to print the program's\n", "1. default strings in r +everse order\n", "2. or enter your own to be reversed ?\n"; print "chose options 1 or 2\n"; $an1 = 1; $an2 = 2; $choice = <STDIN>; if ($choice = $an2) { print "enter your own strings\n"; chomp(@lines = <STDIN>); @result = reverse(@lines); foreach $line1 (@result){ $line1 .= "\n"; } print "@result"; } elsif ($choice = $an1) { @proglines = reverse(qw ( wrda vzc rregr zfgr bzfgzffg rergrge d fgsrg + rwer ds vsgsrg )); foreach $line (@proglines) { $line = "\t$line"; $line .= "\n"; } print "@proglines"; }

Replies are listed 'Best First'.
Re: elsif statement not being evaluated
by 2teez (Vicar) on Nov 18, 2012 at 06:27 UTC

    Hi jonagondos,
    check this in your code:

    if ( $choice = $an2 ) { ... } elsif ( $choice = $an1 ) { ... }
    I suppose you want to use
    if ( $choice == $an2 ) { ... } elsif ( $choice == $an1 ) { ... }
    You are assigning to variable $choice, the value of the variable $ans2 using the assignment operator '=' .
    So, whatsoever, value inputted was replaced by the value of variable $ans2.
    In which case variable $choice value is ALWAYS evaluate to 2 the pre-defined value of variable $ans2, so your elsif(){...} statement is not being evaluated.

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
      oh gosh i feel stupid... i was using the assignment operator

        Happens to everyone using C or languages inheriting or stealing from C. But you can make the compiler / interpreter complain loudly if you make sure the constant is on the left side of the operator:

        if ($answer=42) { # $answer is now always 42 ... } if (42=$answer) { # "Can't modify constant item in scalar assignment" ... }

        This won't help when you compare two variables, but in your case, the variables $an1 and $an2 aren't variable, but constant. So make them constant, either by using Readonly or by using constant:

        use Readonly; Readonly my $fortytwo => 42; # note: =>, not = ... if ($fortytwo=$answer) { # "Modification of a read-only value attempte +d" ... }
        use constant FORTYTWO => 42; # note: =>, not = ... if (FORTYTWO=$answer) { # "Can't modify constant item in scalar assign +ment" ... }

        Or, in this trivial case, get rid of $an1 and $an2 and use 1 and 2.

        I prefer Readonly over constant, because Readonly just makes the variables readonly, with no surprises, whereas constant (ab)uses the perl optimizer and implements the constants as functions returning a constant value. This has some nasty side effects documented in Readonly.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        jonagondos,

        You're just human and new to Perl!

        And when you're an expert, just remember someone else will be 'new to Perl'!

        You're on your way...Ed

        "Well done is better than well said." - Benjamin Franklin

Re: elsif statement not being evaluated
by eyepopslikeamosquito (Archbishop) on Nov 18, 2012 at 11:09 UTC

    Since I assume you are new to Perl and to programming, permit me to give you some general advice:

    • Take care with your indenting
    • In addition to "use warnings", add "use strict"

    Your code could be written more simply like this:

    use strict; use warnings; print <<'JONAG'; Do you want to print the program's 1. default strings in reverse order 2. or enter your own to be reversed ? Choose option 1 or 2 or q to quit JONAG my $choice = <STDIN>; chomp $choice; if ($choice eq 'q') { print "quitting\n"; exit; } # This is the default value. my @lines = qw( wrda vzc rregr zfgr bzfgzffg rergrge d fgsrg rwer ds v +sgsrg ); if ($choice == 2) { print STDERR "enter your own strings\n"; chomp(@lines = <STDIN>); } foreach my $line (reverse @lines) { print "\t$line\n"; }

    First notice that I replaced:

    print "do you want to print the program's\n", "1. default strings in r +everse order\n", "2. or enter your own to be reversed ?\n";
    with:
    print <<'JONAG'; Do you want to print the program's 1. default strings in reverse order 2. or enter your own to be reversed ? Choose option 1 or 2 or q to quit JONAG
    which is easier to read and maintain. This uses a feature of Perl called "here-documents". See perlop (search for << in the "Quote-Like Operators" section).

    I added the lines:

    chomp $choice; if ($choice eq 'q') { print "quitting\n"; exit; }
    The chomp is to remove the newline before checking whether $choice is equal to 'q' or not. Note that I used the "alphabetic" operator eq rather than the numeric equivalent ==. In Perl, the "alphabetic" version of an operator (in this case eq) compares the two operands as if they are strings, while the "punctuation" version (in this case ==) compares them numerically. For example, "01" eq "1" is false because the strings are of different length, while "01" == "1" is true because, numerically, they both evaluate to one. See perlop ("Equality Operators" section) for more information.

    I set the default value via:

    my @lines = qw( wrda vzc rregr zfgr bzfgzffg rergrge d fgsrg rwer ds v +sgsrg );
    Note the "my" variable declaration, which is required by "use strict". Variables declared with "my", known as "lexical variables", are known from the point of declaration to end of scope. This protects you from many common booboos, such as mis-spelling a variable name, and generally makes the code easier to understand and maintain by explicitly limiting variable scope. See strict for details.

    Finally, I reorganized the code to remove unnecessary code duplication (see DRY). That is, the "user entered" data just sets the @lines array. Nothing more. That guarantees that the identical code is used for both the default case and the user-entered case. Your original code had slightly different code for the two cases. Also, your code was needlessly altering the array. For example, instead of your:

    foreach $line (@proglines) { $line = "\t$line"; $line .= "\n"; } print "@proglines";
    which needlessly changes the @proglines array, you can simply print the formatted lines without changing the @proglines array like so:
    foreach my $line (@proglines) { print "\t$line\n"; }
    or even:
    print map { "\t$_\n" } @proglines;
    if you want to get fancy.

    Update: as for why you should use strict, I found these nodes:

Re: elsif statement not being evaluated
by Anonymous Monk on Nov 18, 2012 at 06:22 UTC