检查字符串以查看是否所有字符都是十六进制值

本文关键字:字符 十六进制 字符串 是否 检查 | 更新日期: 2023-09-27 17:48:49

C# 2.0 中检查字符串中的每个字符并在它们都是有效的十六进制字符时返回 true 的最有效方法是什么,否则返回 false?

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
}

检查字符串以查看是否所有字符都是十六进制值

像这样:

(我不懂 C#,所以我不确定如何遍历字符串的字符。

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;

上述逻辑代码

private bool IsHex(IEnumerable<char> 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;
}
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");
}

您可以对字符串执行 TryParse,以测试整个字符串是否为十六进制数。

如果它是一个特别长的字符串,你可以把它分成块并循环遍历它。

// 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);

那只是:

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

这基本上是说:检查text字符串中的所有字符是否都存在于有效的十六进制值字符串中。

这对我来说是最简单的仍然可读的解决方案。

(不要忘记添加using System.Linq;(

编辑:
刚刚注意到Enumerable.All()仅在 .NET 3.5 之后可用。

我使用Int32.TryParse()来做到这一点。 这是它的 MSDN 页面。

下面是上面yjerem解决方案的LINQ版本:

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

发布杰里米答案的 VB.NET 版本,因为我在寻找这样的版本时来到这里。 应该很容易将其转换为 C#。

''' <summary>
'''   Checks if a string contains ONLY hexadecimal digits.
''' </summary>
''' <param name="str">String to check.</param>
''' <returns>
'''   True if string is a hexadecimal number, False if otherwise.
''' </returns>
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

正则表达式在最好的时候不是很有效。最有效的方法是使用纯for循环来搜索字符串的字符,并在找到的第一个无效字符上中断。

但是,可以使用 LINQ 非常简洁地完成此操作:

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

我不能保证效率,因为 LINQ 就是 LINQ,但 Any(( 应该有一个相当优化的编译方案。

就性能而言,最快的可能是简单地枚举字符并进行简单的比较检查。

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;
}

要真正知道哪种方法最快,您需要进行一些分析。

    //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;
    }

程序员时间而言,最好调用平台的字符串到整数解析函数(例如Java的Integer.parseInt(str,base((,看看是否出现异常。 如果你想自己写,并且可能更省时/空间......

我想最有效的是每个字符的查找表。 您将有一个 2^8(或 Unicode 为 2^16(条目的布尔数组,如果它是有效的十六进制字符,则每个数组都是真的,如果不是,则为 false。 代码看起来像(在 Java 中,对不起 ;-(:

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;
}

没有正则表达式的简单解决方案是:

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

或者在 C# 中

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

这可以通过正则表达式来完成,正则表达式是检查字符串是否与特定模式匹配的有效方法。

十六进制数字

的正则表达式可能是 [A-Ha-h0-9],有些实现甚至有十六进制数字的特定代码,例如 [[:xdigit:]]。

您可以使用如下内容扩展字符串和字符:

    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;
    }

我使用这种方法:

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

这是 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;
    }
}

这样用...

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

我制定了这个解决方案来解决这个问题。在执行之前检查请求字符串是否不为 null。

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**

现在,只有

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