Trying to create a Printing Calculator program in Python, program outputs 0 infinitely

361 views Asked by At

I'm trying to make this printing calculator program in Python 2.7.8, but whenever I run it, it outputs this:

0
0
0
0

And so on. It does this infinitely and never stops. I would really appreciate any help. Here is my code. Thanks!

import msvcrt             # Windows only!
def getch():  
    return msvcrt.getch()
def putch(ch):
    msvcrt.putch(ch)

total     = 0
pendingOp = 0
print "*** Calculator ***" 
while True:
    ch = getch()
    if ch == "q": break      # quit
    if ch == "c":            # clear the display
        total = 0            
        pendingOp = 0
    elif ch == "a" or "s" or "m" or "d":  # add, subtract, multiply, divide
        pendingOp = ch       
    elif (ch >= "0" and ch <= "9"):
        newNumber = int(ch)
        if pendingOp == 0:  
            total = newNumber
        else:            
            if   pendingOp == "a": total = total + newNumber
            elif pendingOp == "s": total = total - newNumber
            elif pendingOp == "m": total = total * newNumber
            elif pendingOp == "d": total = total / newNumber
            pendingOp = 0
    print total
2

There are 2 answers

9
Peter M On

Welcome to the wonderful world of converting between different string encodings. That particular API returns a byte string which is different from Python's normal string UTF encoding, and the two won't compare. Try for example if ch == b'q'.

Another solution is to get the wide characters directly:

def getch():
    return msvcrt.getwch()

Of some question to me is that Ctrl-C is returned (on Windows, obviously), even though the API documentation for my python says it shouldn't be.

Update:

abarnert's answer seems to be the root cause. I'm leaving this answer because string encoding issues causes the same symptoms on Python 3 running in the console, and in general are a cause of similarly interesting headaches.

4
abarnert On

Your problem is that, for one reason or another, you don't have a console.

Python's msvcrt.getch is a thin wrapper around the MSVCRT function _getch. While the docs there say "there is no error return", that isn't really true. If there is no console for the app, these functions return immediately, returning -1 (cast to the appropriate type, which means you get '\xff' for getch and u'\uffff' for getwch—which is exactly what you're seeing).

So, why would there be no console?

The most common reason is that you're running the app in some GUI IDE, like IDLE or PyWin, instead of from the cmd shell (aka "DOS prompt"). You can't use msvcrt in IDLE.*

There are other possibilities, like explicitly closing or detaching from the console, but I doubt those are relevant here.

So, what can you do?

Well, if you're using IDLE, it's actually simulating command-line input on top of a Tkinter GUI. That simulation doesn't provide any way to get input a character at a time, only a line at a time. So, you could just use raw_input instead of msvcrt.getch here.

You could theoretically hook the IDLE simulated input, but that would be a lot more work than just, say, building your own Tkinter GUI (or Qt or Win32 or whatever GUI) for your app, for a lot less benefit.

Or, alternatively, you can stop running the program in IDLE. Open a cmd window and run the program with python myscript.py (or C:\Python27\python D:\mystuff\myscript.py, or whatever). If you don't know how to use the shell on Windows, this is a good time to learn.


* Well, you can call the Windows API functions to explicitly allocate a console, via ctypes or win32api. But if you do that, it's going to pop up a separate cmd shell window for you to type into anyway, it's still not going to affect IDLE's input.