【问题标题】:Is there a way to detect how many digits were entered in a hex literal in C++?有没有办法检测在 C++ 中的十六进制文字中输入了多少数字?
【发布时间】:2014-03-18 22:14:07
【问题描述】:

这就是我问的原因:

uint32_t Color::hex(uint32_t a_hex, bool a_readAlphaBits /*= false*/) {
    A = (a_readAlphaBits ? ((a_hex >> 24) & 0xFF) / 255.0f : 1.0f);
    R = (((a_hex >> 16) & 0xFF) / 255.0f);
    G = (((a_hex >> 8) & 0xFF) / 255.0f);
    B = (((a_hex)& 0xFF) / 255.0f);
    return hex();
}

0xFF0000 读取为 RGB 时表示纯红色,但读取为 RGBA 时为 0x00FF0000,这意味着 alpha 位是完全透明的。

因为我想让用户输入 RGB RGBA,而我不知道在编译或运行时无法自动区分 0x00000000 和 0x000000,所以我必须添加一个“readAlphaBits”如果设置为 true 将读取额外位的标志,否则默认为 1.0f。

理想情况下,我希望自动检测到这一点。有谁知道如何确定文字的书写方式?

我有一个想法,涉及基于宏的区分

#define C_HEX(x) 0xFF##x

因此,如果有人输入 C_HEX(000000) 或 C_HEX(00000000),它将以这样的方式添加前缀,即在六位时,完全限定值将是 32 位,而在八位时,它将是 40。我没有t 尝试过,但即使它可以在编译时区分调用,我也不希望这样做,我认为无论如何在这种情况下使用标志可能会更好。如果用户忘记输入该宏,即使我可以根据提供的值的内存布局检测到它丢失,它也会有点蹩脚。

但在检测方面我想不出太多其他的了。

停下来!

编辑:

理想的调用代码如下所示(我有一个类似的基于十六进制的颜色构造函数):

  • 颜色(0xFF0000); //红色 rgba,alpha 为 1.0
  • 颜色(0x88FF0000); //红色 rgba,alpha 为 .533333333

【问题讨论】:

  • 考虑使用 C++11 用户定义文字
  • 这听起来很可怕......为什么不实例化像 rgb(FF0000)rgba(00FF0000) 这样的类来编码文字类型
  • 用户定义的文字可以做到,但是你必须解析十六进制。只需将 00 定义为不透明并将 alpha 放在高位就容易得多。
  • @M2tM:好的,那为什么不拥有两个函数 rgbrgba,它们都返回Color?要求程序员决定是否添加那个字母是不是太过分了?
  • @M2tM 我们显然对优雅有不同的看法;)

标签: c++ hex bit-manipulation rgb


【解决方案1】:

我有两个建议,都不是完美的。

首先是修改您的原始函数,使 alpha 值 00 导致默认 alpha 为 1.0:

uint32_t Color::hex(uint32_t a_hex, bool a_readAlphaBits = false) {
    A = a_readAlphaBits || (a_hex & 0xff000000) ? ((a_hex >> 24) & 0xFF) / 255.0f : 1.0f;
    R = ((a_hex >> 16) & 0xFF) / 255.0f;
    G = ((a_hex >> 8) & 0xFF) / 255.0f;
    B = ((a_hex)& 0xFF) / 255.0f;
    return hex();
}

如果您想要任何完全透明的颜色,则必须指定额外的参数。

现在您可以使用宏来指定两个参数,按位数进行。

#define C_HEX(x) 0x##x, (sizeof(#x)>7)

【讨论】:

  • 接受这一点,因为我认为执行 a_readAlphaBits 的建议非常好 || alpha 位不为零。
  • 很好,我没想过使用预处理器。难道你不能也将FF 连接到开头吗?如果数字已经是 8 位长,无符号整数模算术只会将其删除。我想虽然它是有效的 C/C++,但它会导致您不想禁用的警告。
【解决方案2】:

无需依赖 C++11 或更高版本,您只需将其作为字符串读取并解析即可。 它当然比替代方案慢一点,但由于它只需要根据用户输入进行评估,因此速度在这里不是一个因素。一个优点是它比使用宏和位移更容易理解和维护。

【讨论】:

    【解决方案3】:

    在 C++11 中,您可以使用文字模板运算符:

    template< char ... c >
    rgba_type operator "" _rgb ();
    

    或原始文字运算符:

    rgba_type operator "" _rgb ( char * token, std::size_t len );
    

    但是你不得不麻烦地解析十六进制数字,如果你想在编译时(而不是运行时)发生这种情况,它必须是constexpr。这在即将到来的 C++14 中不那么痛苦了,但完全触摸十六进制数字可能是矫枉过正。

    让用户指定ARGB 更合理,零是不透明的,这样他们就可以省略高位。如果您的应用程序格式错误,您可以让一个更简单的用户定义文字为您翻译它:

    constexpr rgba_type operator "" _rgb ( unsigned long long argb_opaque )
        { return ( ~ argb_opaque >> 24 ) & 0x000000FF
                  | ( argb_opaque << 8 ) & 0xFFFFFF00; ) }
    

    【讨论】:

    • 谢谢!是的,默认情况下将 0 设置为不透明是我的第一个想法,但部分问题在于这不是一种非常标准的颜色识别方法。我支持 RGB+RGBA 十六进制值的部分原因是能够从其他应用程序复制/粘贴。当我翻转 alpha 位时,我会失去它(即使在颜色代码中不常见 alpha)。您能否详细说明一下 constexpr 在这里可能有何帮助,以及 rgba_type 将如何在最终调用语法中使用?
    • 我不明白最后两个问题。
    • 您能否提供一个最终颜色(HEXVALUEWITHYOURSUGGESTION_FOR_RGB_AND_RGBA_ON_SEPARATE_LINES)的示例?您能否详细说明触摸十六进制数字的工作原理,或者我可以在哪里进一步了解这种方法?你暗示它,但不要详细说明。 :3
    • @M2tM 我说这会很痛苦。你自己一个人。它看起来像0xRRGGBBAA_color,而不是像函数调用。 (实际上x 是可选的;它是您需要解析的一部分。)
    猜你喜欢
    • 2010-09-29
    • 1970-01-01
    • 2016-11-12
    • 2020-02-27
    • 2020-01-19
    • 2021-09-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多