views:

157

answers:

7

I have a string like this:

"00c4"

And I need to convert it to a hex value like this:

0x00c4

How would I do it?

A: 

http://www.codeproject.com/KB/string/hexstrtoint.aspx

Zafer
Your link also pointed me to using strtol
ExplodingRat
+3  A: 

The strtol function (or strtoul for unsigned long), from stdlib.h in C or cstdlib in C++, allows you to convert a string to a long in a specific base, so something like this should do:

char *s = "00c4";
char *e;
long int i = strtol (s, &e, 16);
// Check that *e == '\0' assuming your string should ONLY
//    contain hex digits.
// Also check errno == 0.
// You can also just use NULL instead of &e if you're sure of the input.
paxdiablo
IMHO you should only check, that `*e == '\0'`, checking if `e == s+strlen(s)` is overkill.
Yossarian
strtol did the job. Thank you!
ExplodingRat
Good point, @Yossarian. Whether you use this code on string with nothing but hex digits or whether yo allow spaces as well as nul bytes and so on is probably beyond the scope of the question. I should probably have left that out since it's only _one_ way of doing it and may be the wrong way depending on the string format. I'll incorporate your comment since it's a good one.
paxdiablo
@ExplodingRat, just watch out for numbers where the high bit is 1 (any one starting with `8` thru `f`). These may sign-extend to a negative number. `strtoul` is probably safer.
paxdiablo
+2  A: 

You can adapt the stringify sample found on the C++ FAQ:

#include <iostream>
#include <sstream>
#include <stdexcept>

class bad_conversion : public std::runtime_error
{
public:
  bad_conversion(std::string const& s)
    : std::runtime_error(s)
  { }
};

template<typename T>
inline void convert_from_hex_string(std::string const& s, T& x,
  bool failIfLeftoverChars = true)
{
  std::istringstream i(s);
  char c;
  if (!(i >> std::hex >> x) || (failIfLeftoverChars && i.get(c)))
    throw ::bad_conversion(s);
}

int main(int argc, char* argv[])
{
  std::string blah = "00c4";
  int input;
  ::convert_from_hex_string(blah, input);
  std::cout << std::hex << input << "\n";
  return 0;
}
Merlyn Morgan-Graham
Anyone know how you could generically specify an argument that would accept std::hex? Then this could be a more generic function. The function signature of std::hex looks sort of nasty, and wouldn't make usage obvious. I also can't immediately figure out what an empty default might look like.
Merlyn Morgan-Graham
You might want to change that input line to `i >> std::hex >> x >> std::ws` so that trailing whitespace won't trigger the exception.
sbi
sbi
@sbi: Trailing whitespace only triggers an exception when I set "failIfLeftoverChars" to true (as in my example here). Tested it out just now.
Merlyn Morgan-Graham
@Merlyn: Yes, I saw that. Still, trailing whitespaces are often allowed even when other characters aren't. Another idea would be to make `failIfLeftoverChars` an `enum` and allow a third option.
sbi
+2  A: 
#include <stdio.h>

int main()
{
        const char *str = "0x00c4";
        int i = 0;
        sscanf(str, "%x", &i);
        printf("%d = 0x%x\n", i, i);
        return 0;
}
nir
When using `%x` the input string need not be prefixed `0x`. If you use `%i` rather than `%x` it will accept decimal, hexadecimal, or octal input where hex input must be prefixed `0x` and octal prefixed with `0`. Also given the C++ tag, as similar solution using `<sstream>` could be proposed.
Clifford
What happens if I pass `"blah"` as `str` to `sscanf()`?
sbi
Well, you should check the return code of sscanf, which returns the number of successful conversions.
nir
A: 
int val_from_hex(char *hex_string) {
    char *c = hex_string;
    int val = 0;
    while(*c) {
        val <<= 4;
        if(*c >= '0' && *c <= '9')
            val += *c - '0';
        else if(*c >= 'a' && *c <= 'f')
            val += *c - 'a' + 10;
        c++;
    }
    return val;
}
sje397
@sje397: Does it take care of 'A' to 'F'?
Chubsdad
@chubsdad: no. left as an exercise for the reader :)
sje397
+1  A: 
std::string val ="00c4";
uint16_t out;
if( (std::istringstream(val)>>std::hex>>out).fail() )
{ /*error*/ }
KitsuneYMG
+1  A: 

There is no such thing as an 'actual hex value'. Once you get into the native datatypes you are in binary. Getting there from a hex string is covered above. Showing it as output in hex, ditto. But it isn't an 'actual hex value'. It's just binary.

EJP