8 Replies - 1704 Views - Last Post: 08 November 2012 - 07:06 PM Rate Topic: ***** 1 Votes

#1 FallingObjects  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 06-November 12

Activate list checking if statements based on list length

Posted 07 November 2012 - 10:00 PM

Basically, what I am trying to do is make a calculator that takes user string input. I'm stuck at the point where I check if the user's input string is valid or not. I can get all the error checking working fine, but I have no idea how to prevent the "IndexError: list out of range" when it tries to check string[3] and string[4] when the list only has 3 blocks in it.

I've tried using two while loops, which is why there's this segment in it:
    if len(splitter) == 3:
        length = 3
    if len(splitter) == 5:
        length = 5



But that got me nowhere, and created an infinite return loop of error messages. Infact, it jumped my CPU usage from 25% to 100% very quickly

How can I get the program to only run the splitter[3] and splitter[4] error checking lines only if they're applicable?

Thanks.

calculator_valid = 0
while calculator_valid == 0:
    splitter = str(input("Input operands and operations: "))
    splitter = splitter.strip()
    splitter = splitter.replace('*', 'x*x')
    splitter = splitter.replace('/', 'x/x')
    splitter = splitter.replace('-', 'x-x')
    splitter = splitter.replace('+', 'x+x')
    splitter = splitter.split ('x')
    print (splitter)
    if len(splitter) == 3:
        length = 3
    if len(splitter) == 5:
        length = 5
    print(length)
#I thought spacing here would be necessary, given to the lengthy error checking segment.
        
    if (1 > len(splitter)):
        print("Please enter a valid input of operand/operator/operand or operand/operator/operand/operator/operand")
    elif not(('*') in splitter or ('/') in splitter or ('+') in splitter or ('-') in splitter):
        print("Input must include at least one operator")
    elif (splitter[0].count('.') > 1):
        print("First number error, contains multiple decimal places")
    elif (splitter[2].count('.') > 1):
        print("Second number error, contains multiple decimal places")
    elif (splitter[4].count('.') > 1):
        print("Third number error, contains multiple decimal places")        
    elif (splitter[0].startswith('.')):
        print("First number error, number starts with a decimal place")
    elif (splitter[0].endswith('.')):
        print("First number error, number ends with a decimal place")
    elif (splitter[2].startswith('.')):
        print("Second number error, number starts with a decimal place")
    elif (splitter[2].endswith('.')):
        print("Second number error, number ends with a decimal place")
    elif (splitter[4].startswith('.')):
        print("Third number error, number starts with a decimal place")
    elif (splitter[4].endswith('.')):
        print("Third number error, number ends with a decimal place") 
    else:
        calculator_valid = 1



Is This A Good Question/Topic? 0
  • +

Replies To: Activate list checking if statements based on list length

#2 fromTheSprawl  Icon User is offline

  • Monomania
  • member icon

Reputation: 513
  • View blog
  • Posts: 2,056
  • Joined: 28-December 10

Re: Activate list checking if statements based on list length

Posted 07 November 2012 - 10:21 PM

Can you give as an input and the erroneous output you're getting?
Was This Post Helpful? 1
  • +
  • -

#3 FallingObjects  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 06-November 12

Re: Activate list checking if statements based on list length

Posted 07 November 2012 - 10:39 PM

View PostfromTheSprawl, on 07 November 2012 - 10:21 PM, said:

Can you give as an input and the erroneous output you're getting?


Input is in the form of (operand)(operator)(operand) or (operand)(operator)(operand)(operator)(operand)

Example:

5*5
5+5-5
20*2
3*3.6/5

I'm not getting wrong output, I'm getting error messages in console/python:
File "Location", line(#),
in <module>
elif(splitter[4].count('.') > 1):
IndexError: list index out of range

When I enter a string with only 2 operands and 1 operator in it (3*3)

Since the program works completely fine when I enter 2 operands and 2 operators, I assume that it has something to do with referencing splitter[4] when it doesn't exist.
Was This Post Helpful? 0
  • +
  • -

#4 fromTheSprawl  Icon User is offline

  • Monomania
  • member icon

Reputation: 513
  • View blog
  • Posts: 2,056
  • Joined: 28-December 10

Re: Activate list checking if statements based on list length

Posted 07 November 2012 - 11:11 PM

Yep, that's probably it. Why not throw in a few other ifs that will wrap around your validation depending on the size?

if(len<3&&len>1):
    #validation for two operands and an operator
elif(len==n&&splitter[n].stuff)
    #do validation here



But you know, you should maybe think of another way to do this, like RegEx. If there's redundancy in code, there might be a way to improve it.
Was This Post Helpful? 1
  • +
  • -

#5 FallingObjects  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 06-November 12

Re: Activate list checking if statements based on list length

Posted 08 November 2012 - 10:20 AM

I was debating adding two extra blocks to the list no matter what, but that may work too.
Was This Post Helpful? 0
  • +
  • -

#6 FallingObjects  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 06-November 12

Re: Activate list checking if statements based on list length

Posted 08 November 2012 - 11:32 AM

        
if splitter[0] not in ".0123456789":
     print("Please enter a valid first number")  



I'm having problems with the above code now. It doesn't want to seem to accept numbers with decimal points as a valid input.

Input: 0.5
Output: Please enter a valid first number

Input 5
Output: n/a, code doesn't trigger the if statement

I'm pretty sure I'm making a stupid basic mistake here, aren't I?
Was This Post Helpful? 0
  • +
  • -

#7 fromTheSprawl  Icon User is offline

  • Monomania
  • member icon

Reputation: 513
  • View blog
  • Posts: 2,056
  • Joined: 28-December 10

Re: Activate list checking if statements based on list length

Posted 08 November 2012 - 06:47 PM

What's the in for? I think yours will check if the number isn't in the whole string, so if splitter[0] = 0.5, it will print the whole thing, since there's no 0.5 on your string validator. Here's a sample:
>>> if n not in ".01234567890.5":
...     print("Hey!")
... else:
...     print("Hey hey hey!")
...
Hey hey hey!



See? It was located inside the String.


You can check for numbers easily if you use type checking:
>>> def checkIfValidNumber(num):
...     if type(num) == int or type(num) == float:
...             return True
...     else:
...             return False
...
>>> checkIfValidNumber('a')
False
>>> checkIfValidNumber(1)
True
>>> checkIfValidNumber(1.321)
True



If you're not allowed to use type, let us know. Also, you can use RegEx which will exponentially lessen your code and make things easier for you, but you should learn it first. It's worthwhile, and I think all programmers should learn it. Everything's awesome with the power of RegEx! ^^

This post has been edited by fromTheSprawl: 08 November 2012 - 06:51 PM

Was This Post Helpful? 1
  • +
  • -

#8 FallingObjects  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 06-November 12

Re: Activate list checking if statements based on list length

Posted 08 November 2012 - 06:51 PM

I actually JUST finished my program before you posted that. You've been a lot of help, and it's greatly appreciated.

If you're curious as to what my whole program is, here's the code.

#Constants used in main()
MIN_LENGTH = 3
MAX_LENGTH = 5

#The multiply function converts two arguments into floating point numbers, and then multiplies them.
def multiply(first, second):
    result = float(first) * float(second)
    return(result)

#The division function converts two arguments into floating point numbers, and then divides the first by the second.
def division(first, second):
    result = float(first) / float(second)
    return(result)

#The addition function converts two arguments into floating point numbers, and then adds them.
def addition(first, second):
    result = float(first) + float(second)
    return(result)

#The subtraction function converts two arguments into floating point numbers, and then subtracts the first by the second.
def subtraction(first, second):
    result = float(first) - float(second)
    return(result)

#The one_operator function solves an input that has one operator in it.
def one_operator(string):
        if '*' in string:
            print ("The answer is", multiply(string[0], string[2]))
        elif '/' in string:
            print ("The answer is", division(string[0], string[2]))
        elif '-' in string:
            print ("The answer is", subtraction(string[0], string[2]))
        elif '+' in string:
            print ("The answer is", addition(string[0], string[2]))  

#The two_operators function solves an input that has two operators in it.
def two_operators(string):
        if '*' in string[1]:
            string[0] = (multiply(string[0],string[2]))#Sets the first place value if the first operator is *     
        if '/' in string[1]:
            string[0] = (division(string[0],string[2]))#Sets the first place value if the first operator is /           
        if '*' in string[3] and not('+' in string[1] or '-' in string[1]):
            print("The answer is", multiply(string[0],string[4]))#Prints the value if both operators are / or *
        if '/' in string[3] and not('+' in string[1] or '-' in string[1]):
            print("The answer is", division(string[0],string[4]))#Prints the value if both operators are / or *            
        if '*' in string[3]:
            string[2] = (multiply(string[2],string[4]))#Sets the second place value if the second operator is *
        if '/' in string[3]:
            string[2] = (division(string[2],string[4]))#Sets the second place value if the second operator is /
        if '+' in string[1] and ('*' in string[3] or '/' in string[3]):
            print("The answer is", addition(string[0],string[2]))#Prints the value if the second operator is / or *, and the first operator is +
        if '-' in string[1] and ('*' in string[3] or '/' in string[3]):
            print("The answer is", subtraction(string[0],string[2]))#Prints the value if the second operator is / or *, and the first operator is -
        if '+' in string[1]:
            string[0] = (addition(string[0],string[2]))#Sets the first place value if the first operator is +
        if '-' in string[1]:
            string[0] = (subtraction(string[0],string[2]))#Sets the first place value if the first operator is -
        if '+' in string[3]:
            print("The answer is", addition(string[0],string[4]))#Prints the result if the second operator is +
        if '-' in string[3]:
            print("The answer is", subtraction(string[0],string[4]))#Prints the result if the second operator is -

            
#Determines which one of the operator functions needs to be used, and executes the needed function.    
def determine_operators(string):
    if len(string) == 3:
        one_operator(string)
    if len(string) == 5:
        two_operators(string)
        
#Error checker if the input entered is in form <operand><operator><operand>.
def length_3(string):
    if (string[0].count('.') > 1):
        print("First number error, contains multiple decimal places")
        return(0)
    elif (string[2].count('.') > 1):
        print("Second number error, contains multiple decimal places")
        return(0)
    elif ((string[0].startswith('.')) or (string[0].endswith('.'))):
        print("First number error, number cannot start or end in a decimal place")
        return(0)
    elif ((string[2].startswith('.')) or (string[2].endswith('.'))):
        print("Second number error, number cannot start or end in a decimal place")
        return(0)
    elif not(('*') in string or ('/') in string or ('+') in string or ('-') in string[1]):
        print("Non valid input for first operator"),
        return(0)
    else:
        return(1)
    
#Error checker if the input entered is in form <operand><operator><operand><operator><operand>.    
def length_5(string):
    if (string[0].count('.') > 1):
        print("First number error, contains multiple decimal places")
        return(0)
    elif (string[2].count('.') > 1):
        print("Second number error, contains multiple decimal places")
        return(0)
    elif (string[4].count('.') > 1):
        print("Third number error, contains multiple decimal places")
        return(0)
    elif ((string[0].startswith('.')) or (string[0].endswith('.'))):
        print("First number error, number cannot start or end in a decimal place")
        return(0)
    elif ((string[2].startswith('.')) or (string[2].endswith('.'))):
        print("Second number error, number cannot start or end in a decimal place")
        return(0)
    elif ((string[4].startswith('.')) or (string[4].endswith('.'))):
        print("Third number error, number cannot start or end in a decimal place")
        return(0)
    elif not(('*') in string or ('/') in string or ('+') in string or ('-') in string[1]):
        print("Non valid input for first operator")
        return(0)
    elif not(('*') in string or ('/') in string or ('+') in string or ('-') in string[3]):
        print("Non valid input for second operator")
        return(0)
    else:
        return(1)

#Checks if the entered input is in the correct format, and contains at least one operator.
def input_check(string):
        if not((len(string) == MIN_LENGTH) or (len(string) == MAX_LENGTH)):
            print("""Invalid input: please enter a valid format of:
<operand><operator><operand>
OR
<operand><operator><operand><operator><operand>
""")
            return(0)
        elif not(('*') in string or ('/') in string or ('+') in string or ('-') in string):
            print("Input must include at least one operator")
            return(0)
        else:
            return(1)
    
#Main function, uses the input_check function to check that the user has entered valid format.
#Once the format is valid, it uses the required error checking function based on length (1 or 2 operators) to check if there is valid numeric/operator input.
#Once that is in the valid format, it then uses the determine_operators function to solve the equation entered and returns the result.
def main():
    calculator_valid = 0
    while calculator_valid == 0:
        calculator = str(input("Input operands and operations: "))
        print("You entered", calculator)
        calculator = calculator.strip()
        calculator = calculator.replace('*', 'x*x')
        calculator = calculator.replace('/', 'x/x')
        calculator = calculator.replace('-', 'x-x')
        calculator = calculator.replace('+', 'x+x')
        calculator = calculator.split ('x')
        while ('') in calculator:
            calculator.remove('')
        calculator_valid = input_check(calculator)
        if len(calculator) == 3:
            calculator_valid = length_3(calculator)
        if len(calculator) == 5:
            calculator_valid = length_5(calculator)
    determine_operators(calculator)

main()


Was This Post Helpful? 1
  • +
  • -

#9 fromTheSprawl  Icon User is offline

  • Monomania
  • member icon

Reputation: 513
  • View blog
  • Posts: 2,056
  • Joined: 28-December 10

Re: Activate list checking if statements based on list length

Posted 08 November 2012 - 07:06 PM

Congratulations! Yep, I like posts here that post the finished product. Good job. ^^
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1