std::isupper(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

🌸 std::isupper(3) β€” the uppercase vibe check

okay so bestie, we're looking at std::isupper from the C++ Standard Library (std::isupper(3), iykyk) and honestly? she's a little icon. simple, iconic, does exactly one thing. let's get into it πŸ’…


✨ NAME ✨

std::isupper β€” literally just std::isupper. that's the whole name. she said "my name is my name" and honestly? respect 🫢


✨ SYNOPSIS ✨

bestie it lives in this header right here:

Defined in header <cctype>
int isupper( int ch );

that's it. one function. one int. no cap. ✨


✨ DESCRIPTION ✨

so what does she do? ok so std::isupper checks whether the character you handed her is an uppercase character, as classified by the currently installed C locale. like, the locale that's active right now, not some hypothetical one. πŸ’…

in the default "C" locale, std::isupper returns a nonzero value only for the uppercase letters:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

that's the whole squad. 26 of them. iconic behavior, no notes. πŸ‘‘

and here's a cute little guarantee she comes with: if std::isupper returns a nonzero value, then it is guaranteed that std::iscntrl, std::isdigit, std::ispunct, and std::isspace all return zero for the same character in the same C locale. so like, an uppercase letter can't also be a digit. obviously. but it's nice that the standard says it out loud fr fr. 🌸

⚠️ the behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF. so like. don't do that. 😭

✨ PARAMETERS ✨

  • ch β€” the character to classify. that's the whole parameter list. she's low maintenance bestie πŸŽ€

✨ RETURN VALUE ✨

  • Non-zero value if the character is an uppercase letter πŸ’–
  • zero otherwise πŸ¦‹

that's it. that's the return value. nonzero = yes girl, zero = not today.


✨ NOTES ✨

ok so this is the part where you actually need to pay attention, because this applies to like all other functions from <cctype>, not just our girl. the behavior of std::isupper is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. ⚠️

to use these functions safely with plain chars (or signed chars), convert the argument to unsigned char first:

bool my_isupper(char ch)
{
    return std::isupper(static_cast<unsigned char>(ch));
}

see how she did that? static_cast<unsigned char> first, then the call. that's the move. periodt. πŸ’…

similarly β€” and this is the part everyone gets wrong, bestie β€” they should not be used directly with standard algorithms when the iterator's value type is char or signed char. instead, convert the value to unsigned char first:

int count_uppers(const std::string& s)
{
    return std::count_if(s.begin(), s.end(),
                      // static_cast<int(*)(int)>(std::isupper) // wrong
                      // [](int c){ return std::isupper(c); } // wrong
                      // [](char c){ return std::isupper(c); } // wrong
                         [](unsigned char c){ return std::isupper(c); } // correct
                        );
}

look at those three wrongs and that one correct. the correct one is the lambda taking unsigned char. the other three are giving "trust me bro" and they are not it. πŸ™ˆ the comment says it, the comment does not lie. iykyk.


✨ EXAMPLE ✨

run this code, she's cute:

#include <cctype>
#include <clocale>
#include <iostream>

int main()
{
    unsigned char c = '\xc6'; // letter Γ† in ISO-8859-1

    std::cout << "isupper(\'\\xc6\', default C locale) returned "
              << std::boolalpha << (bool)std::isupper(c) << '\n';

    std::setlocale(LC_ALL, "en_GB.iso88591");
    std::cout << "isupper(\'\\xc6\', ISO-8859-1 locale) returned "
              << std::boolalpha << (bool)std::isupper(c) << '\n';

}

✨ POSSIBLE OUTPUT ✨

isupper('\xc6', default C locale) returned false
isupper('\xc6', ISO-8859-1 locale) returned true

LOOK AT THAT. same character, two locales, two different answers. that's locale behavior for you bestie, she contains multitudes 🌈✨


✨ SEE ALSO ✨

  • isupper(std::locale) β€” checks if a character is classified as uppercase by a locale (function template) πŸ¦‹
  • iswupper β€” checks if a wide character is an uppercase character (function) πŸ’œ
  • C documentation for isupper πŸ“š

🌟 the big ASCII vibe chart 🌟

ok bestie this is the character classification chart that comes with the page. every row shows the decimal / hexadecimal / octal range, the characters in it, and then the flags in column order. the column names as printed are:

ASCII values  characters  iscntrl  isprint  isspace  isblank  isgraph  ispunct  isalnum  isalpha  isupper  islower  isdigit  isxdigit
decimal  hexadecimal  octal  iswcntrl  iswprint  iswspace  iswblank  iswgraph  iswpunct  iswalnum  iswalpha  iswupper  iswlower  iswdigit  iswxdigit

and here are the rows, β‰ 0 meaning nonzero and 0 meaning zero. each row has 12 values in the order iscntrl isprint isspace isblank isgraph ispunct isalnum isalpha isupper islower isdigit isxdigit:

0–8      \x0–\x8      \0–\10      control codes (NUL, etc.)                    β‰ 0  0   0   0   0   0   0   0   0   0   0   0
9        \x9          \11         tab (\t) whitespaces                         β‰ 0  0   β‰ 0  β‰ 0  0   0   0   0   0   0   0   0
10–13    \xA–\xD      \12–\15     (\n, \v, \f, \r)                             β‰ 0  0   β‰ 0  0   0   0   0   0   0   0   0   0
14–31    \xE–\x1F     \16–\37     control codes                                β‰ 0  0   0   0   0   0   0   0   0   0   0   0
32       \x20         \40         space                                        0   β‰ 0  β‰ 0  β‰ 0  0   0   0   0   0   0   0   0
33–47    \x21–\x2F    \41–\57     !"#$%&'()*+,-./                            0   β‰ 0  0   0   β‰ 0  β‰ 0  0   0   0   0   0   0
48–57    \x30–\x39    \60–\71     0123456789                                   0   β‰ 0  0   0   β‰ 0  0   β‰ 0  0   0   0   β‰ 0  β‰ 0
58–64    \x3A–\x40    \72–\100    :;<=>?@                                      0   β‰ 0  0   0   β‰ 0  β‰ 0  0   0   0   0   0   0
65–70    \x41–\x46    \101–\106   ABCDEF                                       0   β‰ 0  0   0   β‰ 0  0   β‰ 0  β‰ 0  β‰ 0  0   0   β‰ 0
71–90    \x47–\x5A    \107–\132   GHIJKLMNOPQRSTUVWXYZ                         0   β‰ 0  0   0   β‰ 0  0   β‰ 0  β‰ 0  β‰ 0  0   0   0
91–96    \x5B–\x60    \133–\140   [\]^_`                                       0   β‰ 0  0   0   β‰ 0  β‰ 0  0   0   0   0   0   0
97–102   \x61–\x66    \141–\146   abcdef                                       0   β‰ 0  0   0   β‰ 0  0   β‰ 0  β‰ 0  0   β‰ 0  0   β‰ 0
103–122  \x67–\x7A    \147–\172   ghijklmnopqrstuvwxyz                         0   β‰ 0  0   0   β‰ 0  0   β‰ 0  β‰ 0  0   β‰ 0  0   0
123–126  \x7B–\x7E    \172–\176   {|}~                                         0   β‰ 0  0   0   β‰ 0  β‰ 0  0   0   0   0   0   0
127      \x7F         \177        backspace character (DEL)                    β‰ 0  0   0   0   0   0   0   0   0   0   0   0

see how row 65–70 is the only place where the isupper column goes β‰ 0? that's our girl's whole territory bestie. ABCDEF gets the β‰ 0 in isupper AND isxdigit because hex is a thing. she's multifaceted. πŸ’…πŸ”₯


and that's the whole page! source is cppreference.com, dated 2024.06.10, and honestly she ate. now go forth and always static_cast<unsigned char> before you call her, bestie β€” your future self will thank you πŸ«ΆπŸ’–βœ¨πŸŽ€πŸ¦‹

mwah πŸ’‹

πŸ“¦ where this page comes from