Hi.
It's good to see that you are trying and learning new ways, and I understand that you want to move forward as fast as you can. To do that you must first learn the fundamentals of Python, one of which is the Data Types.
If you look back, you'll see that I asked that you simply take some input (such as
calc = list(input(": "))
and then try to unpack that so that the elements can be checked for sanity. I also said that this could be done (the sanity checking) without using
try
/
except
. Maybe I confused you, and it's my bad if that is the case.
Take things one step at a time, check what you have and only move on to the next step once you have what you need. Right now what we need is the elements of the input object.
Objects such as a list or a string are indexed, starting at position zero and this basic code will demonstrate that. To keep it easy, we'll simply use the default return of the
input()
function, which is a
string
object, as I'm sure you know:
calc = input(": ")
position = 0
print(f"The length of the input is: {len(calc)}")
print("The index positions are...")
for char in calc:
print(f"{position:} : {char}")
position += 1
What we have there is a proof of concept; that each character of the input (
char in calc
) can be represented by a position number, starting at zero (
position = 0
) and ending at the length of said input (
len(calc)
).
From the above you should be able to see that we can access any of the input elements using its position in the object, such as
print(calc[0])
or
print(calc[1])
or
print(calc[2])
, ect.
We can prove that with:
for pos in range(len(calc)):
print(f"{pos} : {calc[pos]}")
... which says, start counting at zero and stop at the end of the input (
for pos in range(len(calc))
) and for each loop count, output the element at that position.
If you don't know about loops and the
range()
function, again, this is a 'must know' concept for you to be able to move forward, so once again use whatever learning resource you have, to better understand that.
Checking the user input is possibly the most challenging part, but as with everything, it can be (and should be) broken down into its constituent parts.
So, what are we looking for? Well, for starters, we're looking for any digit. We're also looking for the operator, so let's have some lists (just as you would with pen and paper).
digits = ['0','1','2','3','4','5','6','7','8','9']
operators = ['+','-','*','/','**','%']
Note: The same advice here, as is for loops.
I know, we're also looking for the decimal point, but we'll get to that.
As I suggested (and as you attempted) a function to check the user input, could be a good plan, so...
def check_input(ui):
"""
returns a tuple object of the user input, if said input is valid,
else returns False for (q)uit or None for an invalid input
"""
n1 = n2 = op = '' # create three string objects to store any valid input
digits = ['0','1','2','3','4','5','6','7','8','9']
operators = ['+','-','*','/','**','%']
ui = ui.lower() # change the case for any alpha character in the input
check = ui.strip() # remove any spaces from the input and assign it to a new variable
if check == 'q': # a way out for the app
return False
for char in check: #loop through the check and exit the function if any of these fail
if char not in digits\
and char not in operators\
and char != '.': return
# if we get to this point, we know we have a valid input
elif char.isdigit(): # do we have a digit?
if not op: # have we already had the operator?
n1 += char # if no, then it's a part of the first number
else: # if yes, then it's a part of the second number
n2 += char
elif char == '.': # or it could be a decimal point
if not op: # then it's a part of the first number after the decimal point
n1 += char
else: # otherwise it's a part of the second number after the decimal point
n2 += char
else: # not a digit or a decimal point, it has to be the operator
op = char
if op and n1 and n2: # if we have all the elements in place, pass them back
return op, float(n1), float(n2)
There's quite a lot going on there, so I've commented the code, but if you don't understand anything, feel free to ask.
Now that we have a valid input and we know what the numbers are, and what the operation is, we can have a function to which that information can be passed:
def calculate(n1, n2, op):
if op == "+":
result = n1 + n2
elif op == "-":
result = n1 - n2
elif op == "*":
result = n1 * n2
elif op == "/":
result = n1 / n2
elif op == "**":
result = n1 ** n2
elif op == "%":
result = n1 % n2
return result
Let's also give a user a little help, should it be needed:
def help():
print("\nHelp:")
print("Simply enter a calculation as\
\n<number><operator><number>\
\ne.g: 1+2 or 2*7 or 7/9\n")
All we now need is a 'driver' for the above functions:
print("=======<Calculator app>=======")
quit = False
while not quit: # the app will now run until quit is True
calc = input("Input Q to quit: ")
check = check_input(calc)
if check:
op = check[0]
n1 = check[1]
n2 = check[2]
result = calculate(n1, n2, op)
print(f"\nResult: {result}\n")
elif check == None:
help()
else:
print("All done.")
quit = True
I hope that you can follow this mini tutorial and that you found it helpful. If you've any questions, simply ask, and I'm sure you'll get the answers.
Note: I've checked the above code and so far as I'm aware, there are no bugs; I'll correct any that are reported.
Also, if any more experienced coder can offer me any advice on what I've done here, then I'm open to that.
Thank you.
Bug reports and fixes.
Known bug: If more than one operator is entered, the result is incorrect.
Fix: Develop this app to handle that input. This can be done in ways that include...
1. Returning a error message for such an input and abort the calculation.
2. Have the additional operation saved to some register and applied to the final calculation.