c++,stl。将具有 rgb 颜色的字符串转换为 3 个 int 值?
Posted
技术标签:
【中文标题】c++,stl。将具有 rgb 颜色的字符串转换为 3 个 int 值?【英文标题】:c++, stl. Convert string with rgb color to 3 int values? 【发布时间】:2013-08-23 08:39:23 【问题描述】:字符串看起来像“#123456”,结果应该是:
int r = 0x12;
int g = 0x34;
int b = 0x56;
或者简单地在 c++ 中这个任务的逆操作:
How to convert RGB int values to string color
我知道我可以将当前字符串拆分为 3 个子字符串,但是如何将它们实现为十六进制值?
【问题讨论】:
见std::stoi和朋友们。 @juanchopanza:这些函数没有一种方便的方法来处理非十进制数,是吗? @juanchopanza: 看起来我的库不完整或被删减了,我没有这个功能 @KerrekSB 对我来说足够方便。int i = std::stoi("0x20", 0, 16);
或 int i = std::stoi("20", 0, 16);
.
@user2083364 它需要 C++11 库支持。根据您的编译器,您可能必须打开它,或者您可能根本没有它。
【参考方案1】:
使用标准库的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';
【讨论】:
【参考方案2】:你应该先得到数字,去掉#。
然后,你可以使用字符串流:
#include <sstream>
...
using namespace std;
stringstream ss("123456");
int num;
ss >> hex >> num;
最后通过除法得到各个分量:
// 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;
编辑: 不知道 std::stoi(C++11 可用)。感谢@juanchopanza。有了它,您可以更改代码的第一部分:
#include <string>
...
using namespace std;
int num = stoi("123456", 0, 16);
int r = ....
【讨论】:
这是不正确的。 E57139 显示 (229, 87, 144) 但在 Photoshop 和使用计算器时显示为 (229, 113, 57)。我的意思是你在 std::stoi 之前的代码 把所有出现的 0xff 换成 0x100 我会批准的 已修复,抱歉。 请注意,std::stoi
系列函数自 C++11 起可用。可能值得一提。
正如我已经提到的,我的编译器是 Apple LLVM 编译器 4.2。如何检测它是否使用c++11?【参考方案3】:
您可以创建三个子字符串,将它们转换为整数,然后使用 std::hex?
见this。
【讨论】:
【参考方案4】:将每个部分都包含在字符串中后,使用strtol()
将其转换为数字。确保使用 16 作为“基础”参数,因为您的值是十六进制的。
【讨论】:
【参考方案5】:在将字符串分成 3 个单独的数字后尝试 sscanf()。
【讨论】:
【参考方案6】:这是一个幼稚的解决方案:
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;
如果您在其他地方验证了您的输入,您可以将最后一个函数缩写为仅表示 return str_to_hex(...), ... ;
。
或者,您根本不需要拆分字符串:
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;
除了自制的str_to_hex
函数,您还可以使用标准库的转换函数,例如std::strtoul(s.substring(1), nullptr, 16)
。
【讨论】:
为什么要重写一个已经以多种方式完成的函数,比如将字符串转换为十六进制的函数? @rcrmn:无聊?渴望权力、黄金和中立?对引用字符串 API 缺乏信心? 哦,对了。那你就可以走了!但它们大多工作得很好。 @rcrmn:我(和许多其他人)真正缺少的一件事是以统一的方式引用现有字符串(和数组)的方法。对于string_ref
和array_ref
类有几个提议(我认为Boost 有一个),但当然这样的类不会像大多数标准容器那样是“拥有价值”,所以它需要用户的特别关注。但这将是非常值得拥有的。小字符串优化可能会使我对s.substring(1)
的使用相当有效,但是......有时人们觉得它应该做得更好:-)
嗯,是的,但是为操作所需的内容编写如此多的代码有点太费力了。不过,我可以看到string_ref
和类似类的使用。感谢您的参考,有时人们只是坚持提供的内容,而不寻找其他可能更好的可能性。【参考方案7】:
反之亦然:uint8_t 三元组转字符串
#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();
【讨论】:
以上是关于c++,stl。将具有 rgb 颜色的字符串转换为 3 个 int 值?的主要内容,如果未能解决你的问题,请参考以下文章