Detecting if a string is all CAPS

C#String

C# Problem Overview


In C# is there a way to detect if a string is all caps?

Most of the strings will be short(ie under 100 characters)

C# Solutions


Solution 1 - C#

No need to create a new string:

bool IsAllUpper(string input)
{
    for (int i = 0; i < input.Length; i++)
    {
        if (!Char.IsUpper(input[i]))
             return false;
    }

    return true;
}

Edit: If you want to skip non-alphabetic characters (The OP's original implementation does not, but his/her comments indicate that they might want to) :

   bool IsAllUpper(string input)
    {
        for (int i = 0; i < input.Length; i++)
        {
            if (Char.IsLetter(input[i]) && !Char.IsUpper(input[i]))
                return false;
        }
        return true;
    }

Solution 2 - C#

I like the LINQ approach.

If you want to restrict it to all upper case letters (i.e. no spaces etc):

return input.All(c => char.IsUpper(c));

or using a method group conversion:

return input.All(char.IsUpper);

If you want to just forbid lower case letters:

return !input.Any(c => char.IsLower(c));

or

return !input.Any(char.IsLower);

Solution 3 - C#

Simple?

if (input.ToUpper() == input)
{
    // string is all upper
}

Solution 4 - C#

Make sure your definition of capitalization matches .Nets definition of capitalization.

ToUpper() in .Net is a linguistic operation. In some languages capitalization rules are not straight forward. Turkish I is famous for this.

// Meaning of ToUpper is linguistic and depends on what locale this executes
// This test could pass or fail in ways that surprise you.
if (input.ToUpper() == input) 
{
    // string is all upper
}

You could use

// Meaning of ToUpper is basically 'ASCII' ToUpper no matter the locale.
if (input.ToUpper(CultureInfo.InvariantCulture) == input) 
{
    // string is all upper
}

You may be tempted to save memory doing character by character capitalization

MSDN cautions against this

for(int i = 0; i < input.Length; i++) {
   if(input[i] != Char.ToUpper(input[i], CultureInfo.InvariantCulture)) {
     return false;
   }
}

The above code introduces a bug. Some non English 'letters' require two .net characters to encode (a surrogate pair). You have to detect these pairs and capitalize them as a single unit.

Also if you omit the culture info to get linguistic capitalization you are introducing a bug where in some locales your home brew capitalization algorithm disagrees with the the .net algorithm for that locale.

Of course none of this matters if your code will never run outside English speaking locales or never receive non English text.

Solution 5 - C#

Use

if (input == input.ToUpper())

Solution 6 - C#

I would convert the string to all caps (with ToUpper) then compare that to the original (using Equals). Should be doable in one line of code.

return s.Equals(s.ToUpper())

Solution 7 - C#

If this needs to have good perf, I'm assuming it happens a lot. If so, take your solution and do it a few million times and time it. I suspect what you've got is better than the other solutions because you aren't creating a new garbage collected object that has to be cleaned up, and you can't make a copy of a string without iterating over it anyways.

Solution 8 - C#

You can also call the Windows function that tells you the makeup of your string.

GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, s, s.Length, ref characterTypes);

You supply it a UInt16 array the same length as your string, and it fills each element with a bitwise combination of flags:

  • C1_UPPER (0x0001): Uppercase
  • C1_LOWER (0x0002): Lowercase
  • C1_DIGIT (0x0004): Decimal digits
  • C1_SPACE (0x0008): Space characters
  • C1_PUNCT (0x0010): Punctuation
  • C1_CNTRL (0x0020): Control characters
  • C1_BLANK (0x0040): Blank characters
  • C1_XDIGIT (0x0080): Hexadecimal digits
  • C1_ALPHA (0x0100): Any linguistic character: alphabetical, syllabary, or ideographic. Some characters can be alpha without being uppercase or lowercase
  • C1_DEFINED (0x0200): A defined character, but not one of the other C1_* types

So if you examined the string:

> Hello, "42"!

You would get the results

> [0x210, 0x301, 0x382, 0x302, 0x302, 0x302, 0x210, 0x248, 0x210, 0x284, 0x284, 0x210, 0x210]

Which breaks down to:

|            | H | e | l | l | o | , |   | " | 4 | 2 | " | ! |
|------------|---|---|---|---|---|---|---|---|---|---|---|---|
| Defined    | X | X | X | X | X | X | X | X | X | X | X | X |
| Alpha      | x | x | x | x | x |   |   |   |   |   |   |   |
| XDigit     |   | x |   |   |   |   |   |   | x | x |   |   |
| Blank      |   |   |   |   |   |   | x |   |   |   |   |   |
| Cntrl      |   |   |   |   |   |   |   |   |   |   |   |   |
| Punct      |   |   |   |   |   | x |   |   |   |   | x | x |
| Space      |   |   |   |   |   |   | x |   |   |   |   |   |
| Digit      |   |   |   |   |   |   |   |   | x | x |   |   |
| Lower      |   | x | x | x | x |   |   |   |   |   |   |   |
| Upper      | x |   |   |   |   |   |   |   |   |   |   |   |

Solution 9 - C#

Another approach

return input.Equals(input.ToUpper(), StringComparison.Ordinal)

Solution 10 - C#

I think the following:

bool equals = (String.Compare(input, input.ToUpper(), StringComparison.Ordinal) == 0)

Will work also, and you can make sure that the comparison is made without taking into account the string casing (I think VB.NET ignores case by default). O even use String.CompareOrdinal(input, input.ToUpper()).

Solution 11 - C#

Regular expressions comes to mind. Found this out there: http://en.csharp-online.net/Check_if_all_upper_case_string

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStubbornMuleView Question on Stackoverflow
Solution 1 - C#Greg DeanView Answer on Stackoverflow
Solution 2 - C#Jon SkeetView Answer on Stackoverflow
Solution 3 - C#BoltBaitView Answer on Stackoverflow
Solution 4 - C#Ifeanyi EcheruoView Answer on Stackoverflow
Solution 5 - C#M4NView Answer on Stackoverflow
Solution 6 - C#NickView Answer on Stackoverflow
Solution 7 - C#JoeView Answer on Stackoverflow
Solution 8 - C#Ian BoydView Answer on Stackoverflow
Solution 9 - C#Eduardo MirandaView Answer on Stackoverflow
Solution 10 - C#Leandro LópezView Answer on Stackoverflow
Solution 11 - C#PEZView Answer on Stackoverflow