237

I have an input string and I want to verify that it contains:

  • Only letters or
  • Only letters and numbers or
  • Only letters, numbers or underscore

To clarify, I have 3 different cases in the code, each calling for different validation. What's the simplest way to achieve this in C#?

p.campbell
  • 98,673
  • 67
  • 256
  • 322
Bab Yogoo
  • 6,669
  • 6
  • 22
  • 17
  • RegEx is slower than a direct character check. You can write an extension method or use one that's already written such as the [Extensions.cs](https://www.nuget.org/packages/Extensions.cs) NuGet package that makes it as simple as: For example: "abcXYZ".IsAlphabetic() will return True whereas "abc123".IsAlphabetic() will return False. – Cornelius J. van Dyk Jan 20 '21 at 13:12

12 Answers12

356

Only letters:

Regex.IsMatch(input, @"^[a-zA-Z]+$");

Only letters and numbers:

Regex.IsMatch(input, @"^[a-zA-Z0-9]+$");

Only letters, numbers and underscore:

Regex.IsMatch(input, @"^[a-zA-Z0-9_]+$");
Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
303
bool result = input.All(Char.IsLetter);

bool result = input.All(Char.IsLetterOrDigit);

bool result = input.All(c=>Char.IsLetterOrDigit(c) || c=='_');
Muhammad Hasan Khan
  • 34,648
  • 16
  • 88
  • 131
  • 7
    I would be curious to know which one faster yours (LINQ) or the one from Philippe Leybaert (Regex)? – nam Dec 27 '15 at 04:39
  • 10
    @nam Running a test against the CMU Pronunciation Dictionary (all letters only, average length 7.4 chars), this is 1.8x faster than compiled `Regex` for all letters, and 3x faster than compiled `Regex` for all letters with `IgnoreCase` option (!). – NetMage May 15 '18 at 18:11
  • 2
    The accepted answer uses uncompiled Regex, that will be even slower. I prefer the LINQ solution, thanks for posting it :) – Berend Engelbrecht Jun 26 '20 at 07:38
  • 1
    Note: While this is certainly a good option, it will _not_ return the same result as the RegEx-based approach. This will use unicode categories to determine what a "letter" is, so it will match stuff like Umlauts, accented characters and more. – diredev Oct 26 '21 at 08:32
  • 1
    For anyone searching for letters + spaces, use this: input.All(x => char.IsLetter(x) || x == ' '); – College Code Mar 28 '22 at 18:24
  • var startsWithLetter = Char.IsLetter(input[0]); will complement this solution if you need it. – Austin Rhymer Dec 02 '22 at 14:29
55

Letters only:

Regex.IsMatch(theString, @"^[\p{L}]+$");

Letters and numbers:

Regex.IsMatch(theString, @"^[\p{L}\p{N}]+$");

Letters, numbers and underscore:

Regex.IsMatch(theString, @"^[\w]+$");

Note, these patterns also match international characters (as opposed to using the a-z construct).

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
26

For those of you who would rather not go with Regex and are on the .NET 2.0 Framework (AKA no LINQ):

Only Letters:

public static bool IsAllLetters(string s)
{
    foreach (char c in s)
    {
        if (!Char.IsLetter(c))
            return false;
    }
    return true;
}

Only Numbers:

    public static bool IsAllDigits(string s)
    {
        foreach (char c in s)
        {
            if (!Char.IsDigit(c))
                return false;
        }
        return true;
    }

Only Numbers Or Letters:

    public static bool IsAllLettersOrDigits(string s)
    {
        foreach (char c in s)
        {
            if (!Char.IsLetterOrDigit(c))
                return false;
        }
        return true;
    }

Only Numbers Or Letters Or Underscores:

    public static bool IsAllLettersOrDigitsOrUnderscores(string s)
    {
        foreach (char c in s)
        {
            if (!Char.IsLetterOrDigit(c) && c != '_')
                return false;
        }
        return true;
    }
Gaff
  • 5,507
  • 3
  • 38
  • 49
  • This is more readable to me than Regex. For `IsAllLetters(string s)`, a shorthand way of doing this without a foreach statement could be `return s.All(c => Char.IsLetter(c))`. Note: this would require `using System.Linq;` – Ian Davis Mar 11 '22 at 19:52
9

I think is a good case to use Regular Expressions:

public bool IsAlpha(string input)
{
    return Regex.IsMatch(input, "^[a-zA-Z]+$");
}

public bool IsAlphaNumeric(string input)
{
    return Regex.IsMatch(input, "^[a-zA-Z0-9]+$");
}

public bool IsAlphaNumericWithUnderscore(string input)
{
    return Regex.IsMatch(input, "^[a-zA-Z0-9_]+$");
}
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
6

You can loop on the chars of string and check using the Char Method IsLetter but you can also do a trick using String method IndexOfAny to search other charaters that are not suppose to be in the string.

Baget
  • 3,318
  • 1
  • 24
  • 44
2

Iterate through strings characters and use functions of 'Char' called 'IsLetter' and 'IsDigit'.

If you need something more specific - use Regex class.

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
1

I added a check so that I could only get the Alphabets and white spaces. You can repeat the for loop after the second if statement to validate the string again.

bool check = false;

Console.WriteLine("Please Enter the Name");
name=Console.ReadLine();

for (int i = 0; i < name.Length; i++)
{
    if (name[i]>='a' && name[i]<='z' || name[i]==' ')
    {
        check = true;
    }
    else
    {
        check = false;
        break;
    }

}

if (check==false)
{
    Console.WriteLine("Enter Valid Value");
    name = Console.ReadLine();
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
1

I haven't yet seen a solution using pattern matching:

public static bool ContainsOnlyLetters(this string input)
{
    bool isValid = true;

    for (int i = 0; isValid && i < input.Length; i++)
    {
        isValid &= input[i] is >= 'A' and <= 'Z' or >= 'a' and <= 'z';
    }

    return isValid;
}

or if you really really hate readable code:

public static bool ContainsOnlyLetters(this string input)
{
    bool isValid = true;
    for (int i = 0; i < input.Length && (isValid &= input[i] is >= 'A' and <= 'Z' or >= 'a' and <= 'z'); i++);
    return isValid;
}
Frederik Hoeft
  • 1,177
  • 1
  • 13
  • 37
0

Recently, I made performance improvements for a function that checks letters in a string with the help of this page.

I figured out that the Solutions with regex are 30 times slower than the ones with the Char.IsLetterOrDigit check.

We were not sure that those Letters or Digits include and we were in need of only Latin characters so implemented our function based on the decompiled version of Char.IsLetterOrDigit function.

Here is our solution:

internal static bool CheckAllowedChars(char uc)
    {
        switch (uc)
        {
            case '-':
            case '.':
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
            case 'G':
            case 'H':
            case 'I':
            case 'J':
            case 'K':
            case 'L':
            case 'M':
            case 'N':
            case 'O':
            case 'P':
            case 'Q':
            case 'R':
            case 'S':
            case 'T':
            case 'U':
            case 'V':
            case 'W':
            case 'X':
            case 'Y':
            case 'Z':
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                return true;
            default:
                return false;
        }
    }

And the usage is like this:

 if( logicalId.All(c => CheckAllowedChars(c)))
 { // Do your stuff here.. }
0

Please find the method to validate if char is letter, number or space, otherwise attach underscore (Be free to modified according your needs)

public String CleanStringToLettersNumbers(String data)
{
    var result = String.Empty;

    foreach (var item in data)
    {
        var c = '_';

        if ((int)item >= 97 && (int)item <= 122 ||
            (int)item >= 65 && (int)item <= 90 ||
            (int)item >= 48 && (int)item <= 57 ||
            (int)item == 32)
        {
            c = item;
        }

        result = result + c;
    }

    return result;
}
0

Use this to scan each CHARACTER of the STRING.

You can add SWITCH STATEMENT after 1 IF STATEMENT if you want to include "many" characters aside from 'SPACE'.

string myInput = string.Empty;
bool check = false; 

// Loops the input module
while (check is false)
{
    Console.WriteLine("Enter Letters Only");
    myInput = Console.ReadLine();

    // Loops the SCANNING PROCCESS of each character of the string
    for (int i = 0; i < myInput.Length; i++)                  
    {
        // Prints current scanning proccess 1 by 1(character by character) inside the string
        Console.WriteLine("Checking Character \"{0}\" ",myInput[i]);
        
        // Letters only     
        if (Char.IsLetter(myInput[i]))
        {
            check = true;
        }
        
        // Includes "SPACE" character
        else if (myInput[i] == ' ')
        {
            check = true;
        }
        else
        {
            check = false;
            Console.WriteLine("wrong input. \"{0}\" is not a string", myInput[e]);
            Console.WriteLine("pls try again");
            // Exits from loop of scanning proccess due to unwanted input
            break;        
        }  
    }
    // Ends SCANNING of 1 CHARACTER inside the string
} 
Console.WriteLine("Input Approved: \"{0}\"", myInput);
Console.WriteLine("Press any key to exit");
Console.ReadKey();

OUTPUT: With FALSE Input

Enter Letters Only
Agent 47
Checking Character "A"
Checking Character "g"
Checking Character "e"
Checking Character "n"
Checking Character "t"
Checking Character " "
Checking Character "4"
Oops. "4" is not a Valid Input
pls try again

Enter Letters Only

OUTPUT: Without FALSE Input

Enter Letters Only
Agent Forty Seven
Checking Character "A"
Checking Character "g"
Checking Character "e"
Checking Character "n"
Checking Character "t"
Checking Character " "
Checking Character "F"
Checking Character "o"
Checking Character "r"
Checking Character "t"
Checking Character "y"
Checking Character " "
Checking Character "S"
Checking Character "e"
Checking Character "v"
Checking Character "e"
Checking Character "n"
Input Approved: "Agent Forty Seven"
Press any key to exit

Or SWITCH STATEMENT only, if you only want to include "some" CHARACTERS from LETTER category & "some" CHARATERS from DIGIT category.

switch (myInput[e])
{ 
    case 'a':
    case 'b':
    case 'c':
    case 'd': 
    case '1':
    case '2':
    case '3':
    case '!':
    case '@': 
    case '#':  
        check = true;
        break; 
    default:
        check = false;
        Console.WriteLine("Oops, \"{0}\" is not a string", myInput[i]);
        Console.WriteLine("pls try again\n");
        break;
}
if (check == false) break ;