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

hi,
im currently using this construct to read my input:

my $formel=$ARGV[0]; my ($vorzeichen_a,$a,$vorzeichen_b,$b,$vorzeichen_c, $c) = ($formel =~ + m/y= (\+|\-|) #$vorzeichen_a + (.+|) #$a + x\^2 + (\+|\-|) #$vorzeichen_b + (.+) #$b + x + (\+|\-|) #$vorzeichen_c + (.+) #$c + $/x);

the input is in the form y=ax^2+bx+c, a,b or c arent needed every time.

if tried to check if they are used like this:
(a has to be 1 if unset)

if (defined($a)) {} else { $a=1; }

but that doesnt work, the var is always defined :(
what other options do i have?

greets
metalfan

20051224 Cleaned up by Corion: Added formatting.

Replies are listed 'Best First'.
Re: if var isnt used
by tirwhan (Abbot) on Dec 24, 2005 at 10:39 UTC

    Two things:

    1. The construct (.+|) will match one or more of any character (".+")or nothing ("|)"). So if no value is given there, the regex will match on nothing and return that into $a. Nothing in this case is the empty string, which is not equivalent to undef. To test for this you could test for truth instead of definedness (if($a)), but it'd be much better to specify the fact that $a is optional with the explicit "?", i.e. (.+)? instead of (.+|). The same goes for the other places where you use "|)".
    2. Don't use the variables $a and $b like this, they are special variables (see perldoc perlvar) and you can run into strange errors when using them (or at least make your code hard to understand and maintain).
    3. Update: Check out bobfs excellent node True or False? A quick Reference Guide for more on this.


    Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
      my ($vorzeichen_a_form,$a_form,$vorzeichen_b_seit,$b_seit,$vorzeichen_c_yab, $c_yab) = ($formel =~ m/y=

      (+\-)? #$vorzeichen_a_form
      (.+)? #$a_form
      x\^2 #x^2
      (+\-.+)? #$vorzeichen_b_seit, $b_seit
      (+\-.+)? #$vorzeichen_c_yab, $c_yab
      $/x);

      it should work on these combinations:
      y=x^2 #no a, b,c
      y=-x^2

      y=1x^2 #no b,c
      y=-1x^2

      y=x^2-2 #no b
      y=-1x^2-2
      y=1x^2-2

      y=x^2-2x #no c
      y=-1x^2-2x
      y=1x^2-2x

      y=x^2-2x-2 #a,b, and c are present
      y=-1x^2-2x-2
      y=1x^2-2x-2

      ofcourse, positive values are possible
      and ofcourse my idea doesnt work :(

        I second hollis suggestion, but here's a regex that does this anyway:

        while($formel=<DATA>) { my ($vorzeichen_a_form, $a_form, $vorzeichen_b_seit, $b_seit, $vorzeichen_c_yab, $c_yab) = $formel =~ m/y\s*=\s* ([-+])? #$vorzeichen_a_form (\d+)? #$a_form x\^2\s* (?: # non-capturing parentheses ([-+])? #$vorzeichen_b_seit (\d+)? #$b_seit x\s* )? # make this part optional (?: ([-+])? #$vorzeichen_c_yab (\d+)? #$c_yab )? /x; print join(":",($vorzeichen_a_form, $a_form, $vorzeichen_b_seit, $b_seit, $vorzeichen_c_yab, $c_yab))."\n"; } __DATA__ y=x^2 #no a, b,c y=-x^2 y=1x^2 #no b,c y=-1x^2 y=x^2-2 #no b y=-1x^2-2 y=1x^2-2 y=x^2-2x #no c y=-1x^2-2x y=1x^2-2x y=x^2-2x-2 #a,b, and c are present y=-1x^2-2x-2 y=1x^2-2x-2

        A computer is a state machine. Threads are for people who can't program state machines. -- Alan Cox
Re: if var isnt used
by holli (Abbot) on Dec 24, 2005 at 15:00 UTC
    I'd like to bring Max::Expr to your attention. It parses math expressions into a tree of objects:
    use strict; use warnings; use Data::Dumper; use Math::Expr; my $e=Parse("y=ax^2+bx+c"); print Dumper ($e);
    Output:
    $VAR1 = bless( { 'Breakable' => 0, 'Val' => '=', 'Opps' => [ bless( { 'Val' => 'y', 'VarType' => 'Real' }, 'Math::Expr::Var' ), bless( { 'Breakable' => 1, 'Val' => '+', 'Opps' => [ bless( { 'Breakable' => 1, 'Val' => '+', 'Opps' => [ bless( { 'Breakable' => 1, 'Val' => '^', 'Opps' => [ bless( { 'Val' => 'ax', 'VarType' => 'Real' }, 'Math::Expr::Var' ), bless( { 'Val' => '2' }, 'Math::Expr::Num' ) ] }, 'Math::Expr::Opp' ), bless( { 'Val' => 'bx', 'VarType' => 'Real' }, 'Math::Expr::Var' ) ] }, 'Math::Expr::Opp' ), bless( { 'Val' => 'c', 'VarType' => 'Real' }, 'Math::Expr::Var' ) ] }, 'Math::Expr::Opp' ) ] }, 'Math::Expr::Opp' );


    holli, /regexed monk/
      the for your replys, have to test that.
Re: if var isnt used
by ikegami (Patriarch) on Dec 25, 2005 at 01:35 UTC

    If you want to check if it matched a 0-length string, try
    if (length($a))

    Altogether, it can be written as:
    $a = 1 if not length $a;
    or
    $a = 1 if length $a != 0;

    By the way, you shouldn't use $a and $b as variables. They mean something special to sort.

Re: if var isnt used
by secret (Beadle) on Dec 24, 2005 at 10:23 UTC
    why do you escape - ? - isn't a metacharacter except in a class so you don't need to escape it .
      What breaks if he escapes it? Nothing

        Except it causes confusion for future maintainers. "Why did he escape the question mark? Is that something I haven't learned before? Is this why I'm getting a bug, or should I look somewhere else?"

        Always try to reduce confusion for future maintainers.

            -Bryan