tags:

views:

1910

answers:

9

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)

+7  A: 

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())

Nick
+27  A: 

Simple?

if (input.ToUpper() == input)
{
    // string is all upper
}
BoltBait
I was all excited about getting an easy best answer, too bad you beat me to it :(
Andrew G. Johnson
This evaluates 'true' for strings like "ABC1" or "*!()@". I don't know the original posters context but this solution certainly returns 'true' for strings containing non-capital letters.
Brian Ensink
Less code is better code. One way you're unnecessarily converting it to upper, the other way you're unnecessarily converting a simple == into a nine-line looping function. Optimize if profiling shows it's helpful.
Chuck
I'd go with ToUpperInvariant()
Dmitri Nesteruk
+6  A: 

Use

if (input == input.ToUpper())
M4N
+26  A: 

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;
    }
Greg Dean
This solution is better than the accepted solution (IMHO) because it doesn't need to create an unnecessary string. It may be more lines of code, but that isn't always a bad thing.
Jon Tackabury
You win some you lose some. I can't believe how many +1's the accepted answer has received.
Greg Dean
Simplicity wins over optimization, in the absence of a reason to optimize.
Robert Rossney
I agree, this answer is better than anything based on .ToUpper().
Brian Ensink
I believe this is a much better solution than the accepted one.
mc2thaH
This should be the right answer.
smack0007
What would this return on the input "FOO BAR"?
PEZ
@PEZ false, the same as his original implementation
Greg Dean
The problem with the question is "I am hoping there is an easier/quicker way to do this." Easier != quicker, if I'm divining what the poster thinks these terms mean. Dean gets my +1.
Jim Nelson
+1, Nice answer. The accepted answer isn't "bad".. but this one is better imo.
Simucal
+3  A: 

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.

Joe
A: 

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()).

Leandro López
In C# at least, == uses String.Equals() which is an ordinal comparison.
Jon Skeet
VB.Net definitely does NOT ignore case for string comparisons
Joel Coehoorn
Thank you Jon and Joel for the clarification then.
Leandro López
I would like to know why the downvote. Was I *that* wrong?
Leandro López
+19  A: 

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 => c.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 => c.IsLower(c));

or

return !input.Any(char.IsLower);
Jon Skeet
"XyZ".All(Char.IsUpper)
Tion
@Tion: Indeed... editing.
Jon Skeet
A: 

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

PEZ
seems like overkill
Greg Dean
+5  A: 

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.

Ifeanyi Echeruo