Glitch using "tolower(getch())"

Here's a mystery I'd like some help with:

In a program I'm writing that has a menu where a user types a character to select an option displayed in the menu, I ran into a glitch using the statement:

while((c = tolower(getch())) != 'q')

During execution, this statement ignores the first character but reads the second character from stdin.  Any ideas why?  

I have the following include statements in the source code:

#include <stdio.h>
#include <conio.h>
#include <ctype.h>

I tried taking the while statement apart to see what would happen in different scenarios.

If I use the following code, the first character is read from stdin, as I would expect:

c = getch();
while(tolower(c) != 'q')

But if I use the code below, the first character is ignored and the second character is read from stdin, just like the first version I listed above.

c = tolower(getch());
while(c != 'q')

My compiler is Symantec C++ v. 7.21.  The project is written and compiled as a DOS "release" program.  No warnings or errors occur at compile time or during linking.  I have not gotten any runtime errors so far.

This program is for an extra credit assignment in a C programming course I'm taking, so it's not a big deal if I don't get a solution.  I'm just really curious about why this glitch is happening.  The rest of the program works just fine.

Thanks in advance for your thoughts on this mystery.
LVL 1
zirconAsked:
Who is Participating?
 
NexialConnect With a Mentor Commented:
tolower is an unsafe macro unless you undefine the macro.

As a macro it evaluates the getch() twice:   this is perfectly legal but not what you want.

Your solution is either:
   1) #undef tolower   /* you already include ctype.h */

this will force the function to be used.

or preassign the results of getch() to a variable and do the
tolower on the variable.  i.e something like:

int
   c;
  c = getch();
  c = tolower(c);

0
 
imladrisCommented:
Nexial and imladris,

Thanks for the prompt responses.  The combination of your two responses explains the problem fully and accurately.  A a result, I'm giving Nexial an A for the answer on this question, and I'll post a question for imladris only to award an A worth 50 points for the comment.

Thanks again.
0
 
zirconAuthor Commented:
Good news! The statement

#undef tolower

did the trick.  My program now works perfectly.  

Two definitions of tolower were present in the ctype.h file:

#if !defined(_WIN32)
#define tolower(c)      (isupper(c) ? (c)+('a'-'A') : (c))

and

#ifndef __STDC__
/* additional code here */
#define _toupper(c)      ((c)-('a'-'A'))

So I'm still not sure what's causing the problem, but I think imladris is on the right track.

Thanks again.
0
 
zirconAuthor Commented:
Oops!  The second definition is:

#define _tolower(c)      ((c)+('a'-'A'))

Guess I wasn't paying close enough attention when I was copy/pasting.
0
All Courses

From novice to tech pro — start learning today.