0

First of all I would like to say that this question is already related to this link (Convert ASCII string into Decimal and Hexadecimal Representations) but since I cannot add a comment, I need to ask something specific related to an answer on that thread.

The code from Jerry Coffin works for me:

for (int i=0; i<your_string.size(); i++)
    std::cout << std::hex << (unsigned int)your_string[i] << " ";

but what I would like to do is instead of printing this out via cout, I would like to store it in an unsigned int variable because I need to pass this value to another function.

My code looks like this:

unsigned int Ascii2Hex(std::string sString2Convert)
{
  unsigned int uiHexVal;
  for (int i=0; i<sString2Convert.size(); i++)
  {
    uiHexVal << std::hex << (unsigned int)sString2Convert[i];
  }
  return (uiHexVal);
}

This obviously does not work because of the "<<" operator.

How can I work my way around this?

halfer
  • 19,824
  • 17
  • 99
  • 186
Sydalmighty
  • 233
  • 2
  • 15
  • 1
    Whats the problem with just using `(unsigned int)sString2Convert[i]`? – Pradhan Jul 12 '15 at 03:09
  • 2
    Anything wrong with [`strtoul`](http://en.cppreference.com/w/cpp/string/byte/strtoul) with a base of 16? – Mark Ransom Jul 12 '15 at 03:10
  • Check this: Might help http://www.cplusplus.com/forum/beginner/89588/ – user007 Jul 12 '15 at 03:13
  • 1
    It looks like you are trying to convert a string containing hex digits back into a number. If that's the case your function is just wrong. http://stackoverflow.com/questions/1070497/c-convert-hex-string-to-signed-integer – Retired Ninja Jul 12 '15 at 03:13
  • http://stackoverflow.com/questions/5100718/integer-to-hex-string-in-c In the top ans, the return value is `stream.str()` probably you can store it in a string object! – user007 Jul 12 '15 at 03:23
  • Hi @RetiredNinja you are correct, that is my objective. I need to pass this value back to a device via a communication protocol so it has to be in a number form. – Sydalmighty Jul 13 '15 at 08:26

2 Answers2

1

Utility functions exist for this, and I believe you could use stringstreams with a similar syntax to what you actually mocked up above. Even so, there's always the quick-and-dirty way:

template <typename T> // Use only unsigned types or risk overflow
T ASCII2hex (std::string str)
{
    T ret = 0;
    for (int i = 0; i < sizeof(T) && i < str.size(); ++i)
        ret += str[i] << (8 * i);
    return ret;
}

There's also this incredibly dangerous and technically undefined but nevertheless elegant and strangely compelling solution:

template <typename T> // yadda yadda unsigned
T ASCII2hex_UNSAFE_DONT_USE_THIS_FUNCTION (std::string str)
{
    return *(T*) str.data(); // Note: overrun if str.size() < sizeof(T)!!!!
}
acwaters
  • 586
  • 3
  • 6
  • hi @acwaters thanks! this code suggestion compiled... but how do i Call it? I get compile error when I use it. sorry for my ignorance. i just don't understand. – Sydalmighty Jul 13 '15 at 08:47
  • Right! Sorry, I should have explained a bit more. The example I gave is a function template; that means that the function can be parameterized with extra information, like types, before it's called. Basically, you can do this: `char[] str = "Test";` `unsigned x = ASCII2hex (str);` `unsigned long y = ASCII2hex (str);` `unsigned char z = ASCII2hex (str);` You don't have to write a new version for each type; since they all do the same thing, you just tell it which type it'll be using, and it gives you the right answer for that type size. – acwaters Jul 13 '15 at 13:40
  • However, you could just as well write the above as an ordinary function, returning whatever type you wish. Just get rid of the `template` and replace the `T`s with, e.g., `unsigned int`. – acwaters Jul 13 '15 at 13:45
1

What Jerry Coffin's code is doing, despite the cast to unsigned int, is converting the char to a string. But usually, the operator<< of cout just thinks: "oh, char, that's a letter right..." so it prints it as the letter it represents. So to print it as a hex value instead, he casts it to an int first.

That being said, here is the problem: the code converts each character separately to an unsigned int and then prints it. But you want to put all the characters in one unsigned int. And depending on your char and int size there only fit 4 or 8 characters in an int. If it is less than this you could do:

unsigned int res=0;
res |= string[0] << 24;
res |= string[1] << 16;
res |= string[2] <<  8;
res |= string[3];

(note that here << means bitshift)

So long story short, you cannot convert the whole string unless it is really short. But when you think about it, a string is already a list of numbers (representing characters). And remember: numbers are always binary, until you print them as text.

David van rijn
  • 2,108
  • 9
  • 21
  • hi David, I think this could work. The ASCII string I am trying to convert is limited to 8 digits (ASCII letters if you may). – Sydalmighty Jul 13 '15 at 01:33
  • Hi @David Van Rijn I am having trouble with this solution since the ASCII text is more than 8 characters. I added some filling white spaces at the end but I actually just need the first 8. this is just in case the letters are not 8 characters eg: QLMJ2W the last 2 characters are white spaces. but to make sure, in the stringstream where i manipulate this value i added an extra 8 white spaces. – Sydalmighty Jul 13 '15 at 08:39
  • Well, you could put those in a 64 bit integer, and it does certainly speed up calculations, but it does make more sense to use a `char[8]` for this, or a `char[9]` with trailing zero. If you put it in an integer please use uint64_t. But (i don't know your application) i would write a small wrapper class for `char[9]` withe an `operator const char* ()` and an `operator<()` and the like. Then you could even define your own `operator>>(istream&, my8String&)` so you can easily pull them out of stdin or whatevever. – David van rijn Jul 13 '15 at 11:42