Compruebe una cadena para ver si todos los caracteres son valores hexadecimales

¿Cuál es la forma más eficiente en C # 2.0 para verificar cada carácter en una cadena y devolver verdadero si son todos caracteres hexadecimales válidos y falso de lo contrario?

Ejemplo

void Test() { OnlyHexInString("123ABC"); // Returns true OnlyHexInString("123def"); // Returns true OnlyHexInString("123g"); // Returns false } bool OnlyHexInString(string text) { // Most efficient algorithm to check each digit in C# 2.0 goes here } 

 public bool OnlyHexInString(string test) { // For C-style hex notation (0xFF) you can use @"\A\b(0[xX])?[0-9a-fA-F]+\b\Z" return System.Text.RegularExpressions.Regex.IsMatch(test, @"\A\b[0-9a-fA-F]+\b\Z"); } 

Algo como esto:

(No sé C #, así que no estoy seguro de cómo recorrer los caracteres de una cadena).

 loop through the chars { bool is_hex_char = (current_char >= '0' && current_char <= '9') || (current_char >= 'a' && current_char <= 'f') || (current_char >= 'A' && current_char <= 'F'); if (!is_hex_char) { return false; } } return true; 

Código para lógica arriba

 private bool IsHex(IEnumerable chars) { bool isHex; foreach(var c in chars) { isHex = ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); if(!isHex) return false; } return true; } 

Puede hacer un TryParse en la cadena para probar si la cadena en su entiridad es un número hexadecimal.

Si se trata de una secuencia particularmente larga, podrías tomarla en fragmentos y recorrerla.

 // string hex = "bacg123"; Doesn't parse // string hex = "bac123"; Parses string hex = "bacg123"; long output; long.TryParse(hex, System.Globalization.NumberStyles.HexNumber, null, out output); 

Aquí hay una versión LINQ de la solución de yjerem arriba:

 private static bool IsValidHexString(IEnumerable hexString) { return hexString.Select(currentCharacter => (currentCharacter >= '0' && currentCharacter <= '9') || (currentCharacter >= 'a' && currentCharacter <= 'f') || (currentCharacter >= 'A' && currentCharacter <= 'F')).All(isHexCharacter => isHexCharacter); } 

Yo uso Int32.TryParse() para hacer esto. Aquí está la página de MSDN .

¿Qué tal solo?

bool isHex = text.All("0123456789abcdefABCDEF".Contains);

Esto básicamente dice: comprueba si todos los caracteres en la cadena de text existen en la cadena de valores hexadecimales válida.

Cuál es la solución más simple aún legible para mí.

(no olvides agregar using System.Linq; )

EDITAR:
Recién noté que Enumerable.All() solo está disponible desde .NET 3.5.

Publicando una versión de VB.NET de la respuesta de Jeremy , porque vine aquí mientras buscaba esa versión. Debería ser fácil convertirlo a C #.

 '''  ''' Checks if a string contains ONLY hexadecimal digits. '''  ''' String to check. '''  ''' True if string is a hexadecimal number, False if otherwise. '''  Public Function IsHex(ByVal str As String) As Boolean If String.IsNullOrWhiteSpace(str) Then _ Return False Dim i As Int32, c As Char If str.IndexOf("0x") = 0 Then _ str = str.Substring(2) While (i < str.Length) c = str.Chars(i) If Not (((c >= "0"c) AndAlso (c <= "9"c)) OrElse ((c >= "a"c) AndAlso (c <= "f"c)) OrElse ((c >= "A"c) AndAlso (c <= "F"c))) _ Then Return False Else i += 1 End If End While Return True End Function 

Una expresión regular no es muy eficiente en el mejor de los casos. El más eficiente será usar un ciclo simple for buscar a través de los caracteres de la cadena y romper el primer inválido encontrado.

Sin embargo, se puede hacer de manera muy sucinta con LINQ :

 bool isHex = myString.ToCharArray().Any(c => !"0123456789abcdefABCDEF".Contains(c)); 

No puedo garantizar la eficacia, ya que LINQ es LINQ, pero Any () debería tener un esquema de comstackción bastante optimizado.

En términos de rendimiento, lo más probable es que simplemente enumere los personajes y haga una simple verificación de comparación.

 bool OnlyHexInString(string text) { for (var i = 0; i < text.Length; i++) { var current = text[i]; if (!(Char.IsDigit(current) || (current >= 'a' && current <= 'f'))) { return false; } } return true; } 

Para saber verdaderamente qué método es más rápido, necesitarás hacer algunos perfiles.

  //Another workaround, although RegularExpressions is the best solution boolean OnlyHexInString(String text) { for(int i = 0; i < text.size(); i++) if( !Uri.IsHexDigit(text.charAt(i)) ) return false; return true; } 

En términos de tiempo del progtwigdor , probablemente sea mejor llamar a la función de análisis de cadena a entero de la plataforma (como Integer.parseInt (str, base) de Java) y ver si obtiene una excepción. Si quieres escribirlo tú mismo, y potencialmente ser más eficiente en tiempo / espacio …

Lo más eficiente, supongo, sería una tabla de búsqueda para cada personaje. Tendría una matriz de booleanos de entrada de 2 ^ 8 (o 2 ^ 16 para Unicode), cada uno de los cuales sería verdadero si es un carácter hexadecimal válido, o falso si no lo es. El código se vería algo así como (en Java, lo siento ;-):

 boolean lut[256]={false,false,true,........} boolean OnlyHexInString(String text) { for(int i = 0; i < text.size(); i++) if(!lut[text.charAt(i)]) return false; return true; } 

Esto podría hacerse con expresiones regulares, que son una forma eficiente de verificar si una cadena coincide con un patrón en particular.

Una posible expresión regular para un dígito hexadecimal sería [A-Ha-h0-9] , algunas implementaciones incluso tienen un código específico para dígitos hexadecimales, por ejemplo [[: xdigit:]] .

Puedes extender string y char utilizando algo como esto:

  public static bool IsHex(this string value) { return value.All(c => c.IsHex()); } public static bool IsHex(this char c) { c = Char.ToLower(c); if (Char.IsDigit(c) || (c >= 'a' && c <= 'f')) return true; else return false; } 

Una solución fácil sin expresiones regulares es:

VB.NET:

 Public Function IsHexString(value As String) As Boolean Dim hx As String = "0123456789ABCDEF" For Each c As Char In value.ToUpper If Not hx.Contains(c) Then Return False Next Return True End Function 

O en C #

 public bool IsHexString(string value) { string hx = "0123456789ABCDEF"; foreach (char c in value.ToUpper()) { if (!hx.Contains(c)) return false; } return true; } 

Yo uso este método:

 public static bool IsHex(this char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } 

Y esto como método de extensión C # …

 public static class StringExtensions { public static bool IsHexString(this string str) { foreach (var c in str) { var isHex = ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); if (!isHex) { return false; } } return true; } //bonus, verify whether a string can be parsed as byte[] public static bool IsParseableToByteArray(this string str) { return IsHexString(str) && str.Length % 2 == 0; } } 

Úselo así ...

 if("08c9b54d1099e73d121c4200168f252e6e75d215969d253e074a9457d0401cc6".IsHexString()) { //returns true... } 

Hice esta solución para solucionar este problema. Verifique que la cadena de Solicitud no sea nula antes de ejecutarse.

 for (int i = 0; i < Request.Length; i += 2) if (!byte.TryParse(string.Join("", Request.Skip(i).Take(2)), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _)) return false; 
 public static bool HexInCardUID(string test) { if (test.Trim().Length != 14) return false; for (int i = 0; i < test.Length; i++) if (!Uri.IsHexDigit(Convert.ToChar(test.Substring(i, 1)))) return false; return true; }**strong text** 

Solo ahora

 if (IsHex(text)) { return true; } else { return false; }