7

i would like to know if it's possible check if one letter of a string is capitalized. Other way to see it, if all letters in the string are uppercase or lowercase. Example:

string a = "aaaaAaa"; 
string b = "AAAAAa"; 

if(??){ //Cheking if all the string is lowercase
   cout << "The string a contain a uppercase letter" << endl;
}
if(??){ //Checking if all the string is uppercase
       cout << "The string b contain a lowercase letter" << endl;
}
CinCout
  • 9,486
  • 12
  • 49
  • 67
  • Check out `isupper` and `islower`. They will help you a lot. – NathanOliver Nov 08 '16 at 21:03
  • From your example input, both `a` and `b` contain an uppercase and both contain a lowercase. What should distinguish them? My question is when will uppercase check apply and when will lowercase check apply? – alvits Nov 08 '16 at 21:06

3 Answers3

13

you can use standard algorithm std::all_of

if( std::all_of( str.begin(), str.end(), islower ) ) { // all lowercase
}
Slava
  • 43,454
  • 1
  • 47
  • 90
  • 2
    `std::islower` hmm? – Hatted Rooster Nov 08 '16 at 21:09
  • 3
    If you invert the condition: `!std::any_of(str.begin(), str.end(), isupper)`, you would have early return. – Mikhail Nov 08 '16 at 21:10
  • 1
    @GillBates std::islower is ambiguous with the version from ``, requiring the user to static cast to the simple version. – krzaq Nov 08 '16 at 21:12
  • @Mikhail but it is not equal, different result if for example the string has not letters – Slava Nov 08 '16 at 21:13
  • @krzaq If locale is included, that is – Hatted Rooster Nov 08 '16 at 21:16
  • @GillBates Afaik all standard headers are free to include other standard headers... – krzaq Nov 08 '16 at 21:17
  • if string contains numbers in any position of the string, will affect it to the condition result? –  Nov 08 '16 at 21:46
  • 1
    @jean yes, condition I wrote means `true if all symbols are lowercase letters`, what @Mikhail wrote `false if any of symbols is a uppercase letter`. Obviously result would be different for non letters. What is viable result is up to you. – Slava Nov 08 '16 at 22:03
  • @Slava I can't compile this algorithm, i'm using a little program to test, but it give error: ‘all_of’ was not declared in this scope if ( !all_of(aux.begin(), aux.end(), &::isupper) ). I'm ussing c++ -g main.cpp and i have #include –  Nov 08 '16 at 22:18
  • @jean as stated in documentation it is available for c++11 or later, so add flag `-std=c++11` if you compile with gcc – Slava Nov 08 '16 at 22:26
  • I hope this comment isn't too pedantic, but the example is missing a closing parenthesis: ` if (std::all_of(str.begin(), str.end(), islower)) { // all lowercase }` – Nexus Software Systems Apr 23 '21 at 01:44
4

This can be easily done with lambda expressions:

if (std::count_if(a.begin(), b.end(), [](unsigned char ch) { return std::islower(ch); }) == 1) {
    // The string has exactly one lowercase character
    ...
}

This assumes that you want to detect exactly one uppercase/lowercase letter, as per your examples.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1. `count_if` is redundant, `any_of` fits better. 2. Lambda itself is redundant, just `std::islower` would be ok. – Mikhail Nov 08 '16 at 21:08
  • @Mikhail This [compiles and runs with lambda](http://ideone.com/qU2sLB) and [fails to compile without it](http://ideone.com/SmtZGG). – Sergey Kalinichenko Nov 08 '16 at 21:10
  • Yeah, I see, as mentioned here: http://stackoverflow.com/questions/40496334/check-if-string-has-letter-in-uppercase-or-lowercase#comment68237169_40496404 – Mikhail Nov 08 '16 at 21:16
  • @Mikhail As far as `any_of` goes, both OP's examples show exactly one upper/lower case letter, suggesting to me that he wants to see if there's exactly one such character. I added a note to that effect. Thank you for the comments! – Sergey Kalinichenko Nov 08 '16 at 21:17
  • @Mikhail, we need the lambda to convert to `unsigned char` (not doing so is Undefined Behaviour - see your usual reference for `std::islower`). – Toby Speight Sep 24 '19 at 15:09
4

Use all_of in concert with isupper and islower:

if(all_of(a.begin(), a.end(), &::isupper)){ //Cheking if all the string is lowercase
    cout << "The string a contain a uppercase letter" << endl;
}
if(all_of(a.begin(), a.end(), &::islower)){ //Checking if all the string is uppercase
    cout << "The string b contain a lowercase letter" << endl;
}

demo

Alternatively, use count_if, if you want to check the number of letters matching your predicate.

krzaq
  • 16,240
  • 4
  • 46
  • 61
  • 1
    The `&::isupper` trick is nice! [I tried compiling without it](http://ideone.com/SmtZGG) and got a rather cryptic error back. Now I understand it's because of an overload. – Sergey Kalinichenko Nov 08 '16 at 21:14
  • You should be using `` and thus `std::islower` in C++ code. More importantly, it's dangerous to pass plain char to `std::islower()` - always convert to unsigned before promoting to `int`. – Toby Speight Sep 24 '19 at 15:02
  • @TobySpeight Why is it dangerous to pass plain char to `std::islower`? I can't think of a scenario where it could cause problems. [the standard](http://eel.is/c++draft/cctype.syn) defines `` to be identical to ``, with the added bonus that there is no overload conflict if you include ``. – krzaq Sep 24 '19 at 15:43
  • 2
    The C++ Standard defers to the C Standard for these headers; it says, *In all cases the argument is an `int`, the value of which shall be representable as an `unsigned char` or shall equal the value of the macro `EOF` . If the argument has any other value, the behavior is undefined.* That's because it can be implemented using the character as an index into an array - negative characters can then index out of bounds. See [Do I need to cast to unsigned char before calling toupper(), tolower(), et al.?](/a/21805970/4850040) – Toby Speight Sep 24 '19 at 15:53
  • Ok, in your previous comment you mentioned conversion to unsigned (int), which would be the default. Though, if anything, just converting to `unsigned char` might be well-defined, but will give nonsensical results. If we're wrapping `::islower`, I'd rather execute it only for positive values, e.g. `[](char c){ return c < 0 ? c : islower(c); }` – krzaq Sep 24 '19 at 16:16