tags:

views:

5381

answers:

7

What is the most efficient way in C# 2.0 to check each character in a string and return true if they are all valid hexadecimal characters and false otherwise.

Example

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
}
+3  A: 

I use Int32.TryParse() to do this. Here's the MSDN page on it.

itsmatt
+1  A: 

In terms of programmer time, it's probably best to call your platform's string-to-integer parsing function (such as Java's Integer.parseInt(str, base)), and see if you get an exception. If you want to write it yourself, and potentially be more time/space-efficient...

Most efficient I suppose would be a lookup table on each character. You would have a 2^8 (or 2^16 for Unicode)-entry array of booleans, each of which would be true if it is a valid hex character, or false if not. The code would look something like (in Java, sorry ;-):

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;
}
Matt J
+5  A: 

You can do a TryParse on the string to test if the string in its entirity is a HexNumber

If its a particularly long string, you could take it in chunks and loop through it.

// 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);
Eoin Campbell
+6  A: 

Something like this:

(I don't know C# so I'm not sure how to loop through the chars of a string.)

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;
yjerem
I find it strange that so many people are jumping on regex for this...
Michael Burr
To a man with a hammer, every problem looks like a nail
Smashery
+7  A: 
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");
}
CMS
For speed, which the question implies, you would want to compile the regular expression instead of evaluating it continually.
Robert Paulson
To Compile or Not To Compile, That's the Question... http://tinyurl.com/6ltmxv
CMS
Isn't using a regex at all for this overkill? One day I'll have to measure it, but I can't believe it would be faster than Jeremy Ruten's solution (http://stackoverflow.com/questions/223832/check-a-string-to-see-if-all-characters-are-hexadecimal-values#223854).
Michael Burr
Indeed - quick testing (with the help of Jon Skeet's Micro Benchmark code) reveals that even using a pre-compiled regex, the straightforward technique outlined by Jeremy Ruten is about 5 times faster.
Michael Burr
Programmer efficiency v. Program efficiency. As usual, the real answer is 'it depends'. Thx for the link @CMS.
Robert Paulson
You're welcome @Robert :)
CMS
+2  A: 

Use a regular expression.

Regular Expression Quick Start

^[0-9a-fA-F]+$


Expresso, a good Regex Builder for .net gives me the following generated code. For efficiency it's best to compile the regular expression.

//  using System.Text.RegularExpressions;

/// <summary>
///  Regular expression built for C# on: Wed, Oct 22, 2008, 12:02:26 PM
///  Using Expresso Version: 3.0.2766, http://www.ultrapico.com
///  
///  A description of the regular expression:
///  
///  Beginning of line or string
///  Any character in this class: [0-9a-fA-F], one or more repetitions
///  End of line or string
///  
///
/// </summary>
public static Regex regex = new Regex(
      "^[0-9a-fA-F]+$",
    RegexOptions.CultureInvariant
    | RegexOptions.Compiled
    );



//// Split the InputText wherever the regex matches
// string[] results = regex.Split(InputText);

//// Capture the first Match, if any, in the InputText
// Match m = regex.Match(InputText);

//// Capture all Matches in the InputText
// MatchCollection ms = regex.Matches(InputText);

//// Test to see if there is a match in the InputText
// bool IsMatch = regex.IsMatch(InputText);

//// Get the names of all the named and numbered capture groups
// string[] GroupNames = regex.GetGroupNames();

//// Get the numbers of all the named and numbered capture groups
// int[] GroupNumbers = regex.GetGroupNumbers();


@CMS also commented:

To Compile or Not To Compile, That's the Question...

Robert Paulson
regex.IsMatch(inputText) is really all that is needed. Some of the Expresso generated code samples are not entirely relevant given the regular expression used, but I left them in.
Robert Paulson
+1  A: 

This could be done with regular expressions, which are an efficient way of checking if a string matches a particular pattern.

A possible regular expression for a hex digit would be [A-Ha-h0-9], some implementations even have a specific code for hex digits, e.g. [[:xdigit:]].

marcj