0
def parse(expression):
    operators= set("*/+-")
    numbers= set("0123456789")#not used anywhere as of now
    opExtrapolate= []
    numExtrapolate= []
    buff=[]
    for i in expression:
        if i in operators:
            if len(buff) >0: #prevents buff if multiple operators
                numExtrapolate.append(''.join(buff))
            buff= []
            opExtrapolate.append(i)
            opExtrapolation=opExtrapolate
        else:
            buff.append(i)


    numExtrapolate.append(''.join(buff))

    numExtrapolation=numExtrapolate
    print(numExtrapolation)
    print("z:", len(opExtrapolation))
    return numExtrapolation, opExtrapolation

def errors():

    numExtrapolation,opExtrapolation=parse(expression)
    #Error for muliple operators
    if (len(numExtrapolation) ==3) and (len(opExtrapolation) !=2):
        print("Bad1")
    if (len(numExtrapolation) ==2) and (len(opExtrapolation) !=1):
        print("Bad2")
    #

I posted similar code in an older question however the premise for questions is different in this post.

The code above takes a mathematical input entered in a variable expression by the user and it splits it into operands and operators. The errors function will later print errors if the input is incorrect.

Input would look something like this , where the operators can only be in the set("*/+-") and operands are real numbers. so an example input would be 45/23+233

With the help of an SO user I was able to get one of the errors to work(error for multiple operators), but I am having trouble implementing a few more error messages.

1)If the input contains items that are not numbers or not the allowed operators then an error message is displayed

2)If a user enters a number such as .23 or something like 554. where there is no number before the decimal place or after the decimal place then a different error is displayed.(note that a number like 0.23 is fine).

3)If the user attempts to divide by zero an error is displayed.

::What I have tried:

In the else statement of parse(), I tried to put conditions on buff.append(i) so that it would only run that code if buff.isdigit()==true but I got errors saying that there were no digits in buff. I also tried creating a set called "numbers"(in code below) and limiting buff.append(i) to that set through a for statement similar to the initial for statement. But unfortunately nothing worked. Any and all help would be appreciated.

Please don't introduce large amounts of code more advanced than the code below. I am trying to fix a problem, not completely change my code. Thanks for all your help.

5
  • it is however the error implementation is extra, not sure if i would get a bonus on it. The decimal part is mandatory though. Commented Nov 2, 2012 at 18:17
  • 2
    This will be a lot easier if you build a Context Free Grammar instead of this rule based system Commented Nov 2, 2012 at 18:19
  • Through the implications of the answers to this post I'm hoping to learn how to manipulate lists that I create(such as in parse() above) and limit them to certain conditions, that is, to limit the type of input that can be stored in the lists I create. Commented Nov 2, 2012 at 18:19
  • I second @Austin's comment ... this is well suited to a CFG ... Commented Nov 2, 2012 at 18:36
  • @Austin Can you provide some sort of example with respect to the OP? I hav never heard of CFG, I clicked the link and still don't understand exactly how I would implement it. Commented Nov 2, 2012 at 18:57

2 Answers 2

2

You can use regular expressions to do these checks:

  1. If the input contains items that are not numbers or not the allowed operators then an error message is displayed

    if not re.match(r'[\d.*/+\- ]+$', expression):
        print("Bad3")  # Characters exist that are not allowed
    

    Explanation: [\d.*/+\- ] will only match digits, your operators, and spaces, the + means to allow one or more of those characters, and the $ matches at the very end of the string. re.match() starts at the beginning of the string so this means that only those characters are allowed.

  2. If a user enters a number such as .23 or something like 554. where there is no number before the decimal place or after the decimal place then a different error is displayed.(note that a number like 0.23 is fine).

    if re.search(r'(?<!\d)\.|\.(?!\d)', expression):
        print("Bad4")  # There is a '.' without a digit before or after it
    

    Explanation: \. in a regex matches a literal '.' character. The | in the middle is an alternation, so the regex will match if the expression on either side of it matches. (?<!\d) means that the previous character is not a number, and (?!\d) means that the next character is not a number, so this regex means "match a '.' that is not preceeded by a digit OR match a '.' that is not followed by a digit".

  3. If the user attempts to divide by zero an error is displayed.

    if re.search(r'/ *[0.]+(?![.\d])', expression):
        print("Bad5")  # Division by 0
    

    Explanation: This matches / followed by any number of spaces, then one or more 0 or . characters, so this will match if anywhere in expression you have something like / 0, / 0.0, or / 0.00. The (?![.\d]) means that the next character can't be a digit or ., which will prevent you from matching something like / 0.4.

Sign up to request clarification or add additional context in comments.

4 Comments

re.x codes are beyond my scope, are there any simpler commands(that will prob. make the code longer) that might also work? If not, then can you possibly explain in detail what is inside the re.x codes and what they mean. If I can't use it, it wont hurt to understand it.
Really nice. I am learning something tonight . Probably a bit complex compared to his programming skills though :s
Added explanation to the regular expressions.
Regular expressions can be complicated, but they are absolutely the best and simplest way to do the kinds of checks you're looking for OP. Understanding the syntax in those re.match and re.search calls is really the tricky part, and it's all explained here.
1

I will give you some indications, but not solve it for you :). If you need more, ask a precise question and I'll answer it.

The answers I give you are NOT directly related with your code.

You can test if a string variable can be an integer by trying to cast it :

try:
    var2 = int(var)

I let you see what Error it gives

For a version that doesn't use try, you can look at the isdigit method

You can see if a string variable if one of your operator by checking it

if (var in ["+", "-", "/", "*"])

to check even more, you can look at the variable's length first

if len(var) != and ... see above

To check if a user inputs something like .543 and refuse it, and can look at the first element of your string variable :

if myvar[0] is ".":

To check if your user wants to divide by 0, you can simply check whether the last number is equals to 0

if int(myvar) == 0:

All these expect you to be able to get operators and numbers first though.

The other solution would be to use regular expressions to perform these checks before parsing your numbers and operators. It seems quite complex compared to the exercise you are trying to achieve though as it is homework. Might be a good idea to look at them anyway.

8 Comments

can you provide an example that doesn't use "try" as I am limited to the code I can use. I can mostly use string.manipulators and whatever is in the OP code.
Sorry, I read use instead of doesn't use. Hum, not really sure how to do that.
That last point you mentioned about regular expressions to parse numbers is the type of thing I am looking into doing since it uses basic code, can you expand on that topic. The mention of the decimal place code is also useful and I can use it since somewhere else in my code I already split my code into separate strings.
I gave you the simplest possible solution, and F.J provided you the "correct" way to do that. His solution is better, as it can be performed before assuming anything about the structure of your input. It is also more complex. Simply choose what seems right in your case ;)
how would I implement an isdigit() function to check for false and then do something?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.