0

The string looks like "#123456" and the result should be:

int r = 0x12;
int g = 0x34;
int b = 0x56;

or simply the inverse for this task in c++:

How to convert RGB int values to string color

I know that I can split the current string into 3 substrings but how to implement them as hex values?

Community
  • 1
  • 1
user2083364
  • 744
  • 1
  • 7
  • 20

7 Answers7

6

Use the standard library's std::hex:

#include <iostream>
#include <sstream>

int main()
{
   // The hex code that should be converted ...
   std::string hexCode;
   std::cout << "Please enter the hex code: ";
   std::cin >> hexCode;

   // ... and the target rgb integer values.
   int r, g, b;

   // Remove the hashtag ...
   if(hexCode.at(0) == '#') {
      hexCode = hexCode.erase(0, 1);
   }

   // ... and extract the rgb values.
   std::istringstream(hexCode.substr(0,2)) >> std::hex >> r;
   std::istringstream(hexCode.substr(2,2)) >> std::hex >> g;
   std::istringstream(hexCode.substr(4,2)) >> std::hex >> b;

   // Finally dump the result.
   std::cout << std::dec << "Parsing #" << hexCode 
      << " as hex gives (" << r << ", " << g << ", " << b << ")" << '\n';
}
Phidelux
  • 2,043
  • 1
  • 32
  • 50
4

You should first get the number, stripping the #.

Then, you can use stringstream:

#include <sstream>

...

{
  using namespace std;
  stringstream ss("123456");
  int num;

  ss >> hex >> num;
}

And finally get each component by dividing:

// Edit: I did it from memory and got it wrong, its % 0x100, not % 0xff.
int r = num / 0x10000;
int g = (num / 0x100) % 0x100;
int b = num % 0x100;

Edit: didn't know about std::stoi (available with C++11). Thanks @juanchopanza for it. With it you can change the first part of the code:

#include <string>

...
{
  using namespace std;
  int num = stoi("123456", 0, 16);

  int r = ....
}
rorlork
  • 523
  • 5
  • 15
0

You could make three substrings, convert them to ints and then use std::hex?

See this.

Community
  • 1
  • 1
Cornel Verster
  • 1,664
  • 3
  • 27
  • 55
0

Once you have each part in a string, use strtol() to convert it to a number. Make sure to use 16 as the "base" parameter since your values are in hex.

Ari
  • 21
  • 4
0

Try sscanf() after splitting your string into 3 seperated numbers.

Verim
  • 1,065
  • 9
  • 17
0

Here's a naive solution:

unsigned int str_to_hex(char const * p, char const * e) noexcept
{
    unsigned int result = 0;
    while (p != e)
    {
        result *= 16;
        if ('0' <= *p && *p <= '9') { result += *p - '0';  continue; }
        if ('A' <= *p && *p <= 'F') { result += *p + 10 - 'A'; continue; }
        if ('a' <= *p && *p <= 'f') { result += *p + 10 - 'a'; continue; }
        return -1;
    }
}

std::tuple<unsigned char, unsigned char, unsigned char>
str_to_col(std::string const & s)
{
    if (str.length() != 7 || s[0] == '#') { /* error */ }

    auto r = str_to_hex(str.data() + 1, str.data() + 3);
    auto g = str_to_hex(str.data() + 3, str.data() + 5);
    auto b = str_to_hex(str.data() + 5, str.data() + 7);

    if (r == -1 || g == -1 || b == -1) { /* error */ }

    return {r, g, b};
}

If you validated your input elsewhere, you could abbreviate the last function to say only return { str_to_hex(...), ... };.


Alternatively, you don't need to split the strings at all:

std::string s = "#123456";

auto n = str_to_hex(s.data() + 1, s.data() + 7);

auto r = n / 0x10000, g = (n / 0x100) % 0x100, b = n % 0x10000;

Instead of the homebrew str_to_hex function you could also use the standard library's conversion functions, such as std::strtoul(s.substring(1), nullptr, 16).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Why re-write a function that is already done in so many ways like the one that converts a string to hex? – rorlork Aug 23 '13 at 08:56
  • @rcrmn: Boredom? Lust for power, gold and neutrality? Lack of faith in referential string APIs? – Kerrek SB Aug 23 '13 at 08:57
  • Oh right. Then you are good to go! But they mostly work quite well. – rorlork Aug 23 '13 at 09:22
  • @rcrmn: One thing I (and many others) am really missing is a way to reference existing strings (and arrays) in a uniform way. There've been several proposals for `string_ref` and `array_ref` classes (I think Boost has one), but of course such a class would not be an "owning value", as most of the standard containers are, so it would need special attention from users. But it would be well worth having. Small-string optimization would probably make my use of `s.substring(1)` fairly efficient, but... sometimes one feels that it should be done better :-) – Kerrek SB Aug 23 '13 at 09:25
  • Well, yes, but it's a little too much effort to write so much code for what the op needed. I can see the use of the `string_ref` and similar classes, though. Thanks for the reference, sometimes one just sticks to what it's given and doesn't look for other, maybe better, possibilities. – rorlork Aug 23 '13 at 09:35
0

And the other way around: uint8_t triplet to string

#include <string>
#include <iostream>
#include <sstream>

std::string to_hex_string(uint8_t red, uint8_t green, uint8_t blue) {
    // r, g, b -> "#RRGGBB"
    std::ostringstream oss;
    oss << '#';
    oss.fill('0');
    oss.width(6);
    oss << std::uppercase << std::hex << ((red << 16) | (green << 8) | blue);
    return oss.str();
}
hp3
  • 3
  • 2