C++: Converting Characters to Uppercase with std::toupper


  1. #include <cctype>
    
  2. Use the function

    char lowercase_char = 'a';
    char uppercase_char = std::toupper(lowercase_char);
    

    In this example, lowercase_char is converted to uppercase and stored in uppercase_char.

Key points to remember

  • The function takes an int argument and returns an int. This is because std::toupper works with the character's ASCII code internally.
  • It considers the current locale's character conversion rules. In the default "C" locale, lowercase letters (a-z) are converted to their uppercase counterparts (A-Z).
  • std::toupper only operates on a single character, not entire strings.


Example 1: Converting a character array to uppercase with a loop

#include <iostream>
#include <cstring>

int main() {
  char str[] = "Hello, world!";

  // Convert each character to uppercase using a loop
  for (int i = 0; i < strlen(str); i++) {
    str[i] = std::toupper(str[i]);
  }

  std::cout << "Original string: " << str << std::endl;
  // Output: Original string: HELLO, WORLD!

  return 0;
}

This code:

  1. Includes <iostream> for input/output and <cstring> for string manipulation functions like strlen.
  2. Defines a character array str with a string literal.
  3. Uses a for loop to iterate through each character of the string using the index i.
  4. Inside the loop, applies std::toupper to the current character str[i] and stores the uppercase version back in the array.
  5. Prints the original and converted string.
#include <iostream>
#include <string>
#include <algorithm>

int main() {
  std::string str = "This is a String.";

  // Convert the string to uppercase using std::transform
  std::transform(str.begin(), str.end(), str.begin(), ::toupper);

  std::cout << "Original string: " << str << std::endl;
  // Output: Original string: THIS IS A STRING.

  return 0;
}
  1. Includes <iostream> for input/output, <string> for string objects, and <algorithm> for the std::transform function.
  2. Defines a std::string object str with a string literal.
  3. Uses std::transform to convert the string in-place. It takes four arguments:
    • str.begin(): Iterator pointing to the beginning of the string.
    • str.end(): Iterator pointing to the end of the string (one character past the last character).
    • str.begin(): Again, iterator pointing to the beginning (output is written here).
    • ::toupper: Pointer to the std::toupper function for element-wise transformation.
  4. Prints the original and converted string.


  1. Manual ASCII conversion

    This approach leverages the fact that lowercase and uppercase letters in the ASCII table differ by 32. You can achieve the conversion by subtracting 32 for lowercase characters:

    char lowercase_char = 'a';
    int ascii_value = lowercase_char;
    if (ascii_value >= 'a' && ascii_value <= 'z') {
        ascii_value -= 32;
    }
    char uppercase_char = static_cast<char>(ascii_value);
    

    Caution
    This method is less portable and might not work correctly for non-ASCII characters or locales with different character sets.

  2. Character class functions

    The <cctype> header provides other character classification functions like islower and isupper. You can use these to conditionally apply conversion logic:

    char lowercase_char = 'a';
    if (islower(lowercase_char)) {
        lowercase_char = lowercase_char - 32;
    }
    

    This approach is slightly more verbose than std::toupper but can be useful for specific checks before conversion.

  3. Locale-aware conversion

    If you need to handle locales where uppercase conversion rules differ from the "C" locale, consider using towupper from <clocale>:

    #include <clocale>
    
    char lowercase_char = 'a';
    setlocale(LC_ALL, ""); // Set to current locale
    char uppercase_char = towupper(lowercase_char);
    

    This approach offers more flexibility for internationalization, but it adds complexity and might not be necessary for all scenarios.

Remember

  • The alternatives discussed here might be more suitable for specific situations, but they come with tradeoffs in terms of portability, complexity, and performance.
  • std::toupper is generally the recommended approach for its simplicity and efficiency unless you have specific requirements for locale awareness or custom conversion logic.