Ответ 1
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");
}
Каков наиболее эффективный способ в С# 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
}
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");
}
Что-то вроде этого:
(Я не знаю С#, поэтому я не уверен, как прокручивать строки строки.)
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;
}
Вы можете сделать TryParse в строке, чтобы проверить, является ли строка в ее entirity шестнадцатеричным числом.
Если это особенно длинная строка, вы можете взять ее в куски и пройти через нее.
// 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);
Я использую Int32.TryParse()
для этого. Здесь находится страница MSDN.
Вот версия LINQ yjerem выше:
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-версии ответ Джереми, потому что я пришел сюда, ища такую версию. Должно быть легко преобразовать его в С#.
''' <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 isHex = text.All("0123456789abcdefABCDEF".Contains);
В основном это говорит: проверьте, существуют ли все символы в строке text
в строке допустимых шестнадцатеричных значений.
Какое из них является самым простым и доступным для чтения решением.
(не забудьте добавить using System.Linq;
)
EDIT:
Просто заметили, что Enumerable.All()
доступен только с .NET 3.5.
С точки зрения производительности самый быстрый, скорее всего, просто перечислит символы и проведет простую проверку сравнения.
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 (или 2 ^ 16 для Unicode) -entry из булевых, каждый из которых будет истинным, если он является допустимым шестнадцатеричным символом, или 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;
}
Это можно сделать с помощью регулярных выражений, которые являются эффективным способом проверки соответствия строки конкретному шаблону.
Возможное регулярное выражение для шестнадцатеричной цифры будет [A-Ha-h0-9], некоторые реализации даже имеют конкретный код для шестнадцатеричных цифр, например. [[: Xdigit:]].
Вы можете расширить строку и char, используя следующую команду:
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;
}
Легкое решение без регулярных выражений:
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
Или в С#
public bool IsHexString(string value)
{
string hx = "0123456789ABCDEF";
foreach (char c in value.ToUpper()) {
if (!hx.Contains(c))
return false;
}
return true;
}
Я использую этот метод:
public static bool IsHex(this char c)
{
return (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F');
}
И это как метод расширения С#...
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...
}
Я сделал это решение для решения этой проблемы. Убедитесь, что перед выполнением строки запроса не имеет значения.
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;
}