• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1077
  • Last Modified:

Convert a char to upper case

What is the best way to make a char variable upper case? It's not that hard when I have a string (MakeUpper() is built in to CString). But it's different with just a char.

I tried
   CString(charCurrent).MakeUpper()
And got the error
   error C2120: 'void' illegal with all types

I could convert the char to a CString temporarily, convert its case, and change it back to a char. But that is inefficient, involves too many steps, and uses a temporary variable.

I can't use _strupr because it expects char *:
   error C2664: '_strupr' : cannot convert parameter 1 from 'char' to 'char *' (new behavior; please see help)

How about CharUpper(charCurrent)? The documentation says lpsz can be "single character or pointer to string". But it doesn't seem to work with my single character:
   error C2664: 'CharUpperA' : cannot convert parameter 1 from 'char' to 'char *' (new behavior; please see help)
It's like it expects a string (char *). Am I doing some thing wrong?

(Visual C++ 4.0)
0
TylerRick
Asked:
TylerRick
  • 7
  • 4
  • 2
  • +2
1 Solution
 
f4817Commented:
Hello,
Just do that
if(myChar > 90) // myChar > 'Z' ?
   myChar -= 32;
0
 
TylerRickAuthor Commented:
That would work. But I'd like something that I could use inline in an expression.

For example, I want to do this:
if (charCurrent == CharUpper(charCurrent))
to check if it is upper case. (I know I could just check if it is > 'z', but there are other times when I really need to convert a char.)

I suppose
if (charCurrent == charCurrent < 'A' ? charCurrent + 32 : charCurrent)
might work. But what if it isn't a letter? Then it wouldn't work to add 32 to the value.

0
 
f4817Commented:
BOOL IsCharUpper(char cVar)
{
if (cVar <= 'Z' && cVar >= 'A')
   return TRUE;
return FALSE;
}

void UpperChar(char & cVar)
{
cVar -= 32;
}

void LowerChar(char & cVar)
{
cVar += 32;
}

0
Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

 
stefanrCommented:
There are some WIN32 functions that will do this for you:

LPTSTR CharUpper(
   LPTSTR lpsz   // single character or pointer to string
);

LPTSTR CharLower(
   LPTSTR lpsz   // single character or pointer to string
);

Parameters
lpsz
Pointer to a null-terminated string or specifies a single character. If the high-order word of this parameter is zero, the low-order word must contain a single character to be converted.

Return Values
If the operand is a character string, the function returns a pointer to the converted string. Since the string is converted in place, the return value is equal to lpsz.

If the operand is a single character, the return value is a 32-bit value whose high-order word is zero, and low-order word contains the converted character.

There is no indication of success or failure. Failure is rare. There is no extended error information for this function; do not call GetLastError.

Remarks
Windows NT: To make the conversion, the function uses the language driver for the current language selected by the user at setup or by using the Control Panel. If no language has been selected, Windows completes the conversion by using internal default mapping. The conversion is made based on the code page associated with the process locale.

Windows 95: The function makes the conversion based on the information associated with the user's default locale, which is the locale selected by the user at setup or by using the Control Panel. Windows 95 does not have language drivers.

QuickInfo
  Windows NT: Requires version 3.1 or later.
  Windows: Requires Windows 95 or later.
  Windows CE: Requires version 1.0 or later.
  Header: Declared in winuser.h.
  Import Library: Use user32.lib.
  Unicode: Implemented as Unicode and ANSI versions on Windows NT.

I have used it like this:

void CPositionEditEx::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
   nChar = UINT(::CharUpper(LPTSTR(nChar))); // UNICODE and character set compliant.

[snip]

Hope this helps.
0
 
Answers2000Commented:
toupper in the C runtime library too (ctypes.h header)

char c = toupper( 'x' ) ;  // c will now contain 'X'

C++ runtime includes a library too
0
 
stefanrCommented:
toupper will certainly work, as long you're not using Unicode.
I would however recommend _totupper, which is a macro that evolves to toupper in ANSI, and towupper in Unicode (and to _mbctoupper in when _MBCS is defined).
0
 
TylerRickAuthor Commented:
I tried
 if (charCurrent == CharUpper(LPTSTR(charCurrent))
and got
 error C2446: '==' : no conversion from 'char *' to 'int' (new behavior; please see help)

What does LPTSTR(nChar) do? Is it meant to convert nChar to LPTSTR? And what is LPTSTR? That's char*, right?

Also, _toupper sounds like a good function that I wasn't aware of, but it won't work here because it converts the character...
 if (charCurrent == _toupper(charCurrent))

0
 
stefanrCommented:
if (charCurrent == TCHAR(CharUpper(LPTSTR(charCurrent))

or

if (int(charCurrent) == _totupper(charCurrent))

should do it.

LPTSTR is TCHAR*, which is char* in ANSI and wchar_t* in Unicode.
0
 
stefanrCommented:
By the way, LPTSTR(nChar) does a type conversion, just like the old C style (LPTSTR) nChar, or the more complex static_cast<LPTSTR>(nChar).
0
 
migelCommented:
Problem is that you give value, not pointer! But You can`t pass pointer to the single character due to ALL string functions require ASCIIZ strings (finished by zero)

You can make temporary array of chars and path it to the functions:

TCHAR arrTemp[2] = {chChar, '\0'};
::AnsiUpper(arrTemp);
chChar = arrTemp[0];
0
 
stefanrCommented:
For WIN32, AnsiUpper is obsolete. It is for compatibility reasons implemented as a macro that calls CharUpper. And it is no need to create a temporary array of chars, since the function itself understands that a char type-casted to char* is a char and not a zero terminated string.
0
 
migelCommented:
Ok, please reject my ansver.
0
 
TylerRickAuthor Commented:
Yay, that works:

if (charCurrent == TCHAR(CharUpper(LPTSTR(charCurrent)))

This probably shows my ignorance of MFC, but why do we use all those typedef'd names, like TCHAR and LPTSTR? Wouldn't it be easier to understand to just say

if (charCurrent == (char)CharUpper((char*)charCurrent)

? Is it to make cross-platform applications easier? (I'm just targeting Windows 95...)
0
 
stefanrCommented:
If you are using only Windows 95, you would most certainly do that way. I'm, however, uses Windows NT with a risk of being needed to port a lot of code to Windows CE sometime in the future. Since NT uses both ANSI and Unicode, and CE uses _only_ Unicode I go the safe way of using the typedefs and macros to ease the pain in converting code between the two character sets. It's a good habit anyway, because you never know what you are supposed to do in the future. And Unicode is faster to use under Windows NT since it uses that internally anyway. Using ANSI requires an extra step of the called ANSI functions to convert to Unicode and back again, and that costs some performance.
0
 
TylerRickAuthor Commented:
Thank you all very much for your help. I think I understand it now. Would some one like to take the credit for the answer, stefanr?
0
 
stefanrCommented:
OK! Thank you, TylerRick.
0

Featured Post

[Webinar] Kill tickets & tabs using PowerShell

Are you tired of cycling through the same browser tabs everyday to close the same repetitive tickets? In this webinar JumpCloud will show how you can leverage RESTful APIs to build your own PowerShell modules to kill tickets & tabs using the PowerShell command Invoke-RestMethod.

  • 7
  • 4
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now