[C/C++11]_[初級]_[如何轉換帶井號的#十六進位制顏色字串到數值]

infoworld發表於2020-12-25

場景

  1. 表示顏色的RGB值,一般有兩種方法,一種是使用使用數值表示RGB(255,255,255),一種是使用字串#FE07AB.那麼字串形式的表示如何得到r,g,b各值的數值大小呢?

說明

  1. <WinGDI.h>裡有對RGB巨集的定義, 其實就是一個24位元組的值,每個顏色值佔用8位元組。

    #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
    
  2. C++11出現之前,十六進位制字串轉換為數值並沒有stoi這種方便的標準函式,有了這個函式,通過設定_Base16,我們可以讓函式理解字串為十六進位制字串,並相應的轉換為十進位制數值。

    inline int stoi(const string& _Str, size_t *_Idx = 0,int _Base = 10)
    
    inline long stol(const string& _Str, size_t *_Idx = 0,int _Base = 10)
    
  3. 在只支援C++98的編譯器裡,沒有stoi函式,我們也可以裡用std::stringstream字串流來轉換,而不需要判斷並轉換字串裡的每個字元。看例子。

例子

test-hex-to-int.cpp

#include "utils.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sstream>
#include <tuple>
#include <math.h>

using namespace std;

static int ConvertHexToInt(const char* buf,size_t bufSize)
{
    std::stringstream ss;
    ss << std::hex;
	ss.write(buf,bufSize);
	int result = 0;
	ss >> result;
	return result;
}

std::tuple<int,int,int> ColorHexToRGBCpp98(const char* str)
{
	if(str == NULL)
		return std::make_tuple(0,0,0);
	
	if(*str == '#')
		str += 1;

	static const int kLen = 6;
	if(strlen(str) != kLen)
		return std::make_tuple(0,0,0);

	auto r = ConvertHexToInt(str,2);
	auto g = ConvertHexToInt(str+2,2);
	auto b = ConvertHexToInt(str+4,2);
	return std::make_tuple(r,g,b);	
}

std::tuple<int,int,int> ColorHexToRGBCpp11(const char* str)
{
	if(str == NULL)
		return std::make_tuple(0,0,0);
	
	if(*str == '#')
		str += 1;

	static const int kLen = 6;
	if(strlen(str) != kLen)
		return std::make_tuple(0,0,0);

	auto r = std::stoi(std::string(str,2),0,16);
	auto g = std::stoi(std::string(str+2,2),0,16);
	auto b = std::stoi(std::string(str+4,2),0,16);
	return std::make_tuple(r,g,b);	
}

int main(int argc, char const *argv[])
{
    Utils::Log("hello","world");
    int r,g,b;
	std::tie(r,g,b) = ColorHexToRGBCpp98("FFFFFF");
    Utils::Print("===========ColorHexToRGBCpp98(FFFFFF)==============");
	Utils::Log("r",r);
    Utils::Log("g",b);
    Utils::Log("b",b);

	std::tie(r,g,b) = ColorHexToRGBCpp98("FE07AB");
    Utils::Print("============ColorHexToRGBCpp98(FE07AB)=============");
	Utils::Log("r",r);
    Utils::Log("g",b);
    Utils::Log("b",b);

	std::tie(r,g,b) = ColorHexToRGBCpp11("FFFFFF");
    Utils::Print("===========ColorHexToRGBCpp11(FFFFFF)==============");
	Utils::Log("r",r);
    Utils::Log("g",b);
    Utils::Log("b",b);

	std::tie(r,g,b) = ColorHexToRGBCpp11("FE07AB");
    Utils::Print("============ColorHexToRGBCpp11(FE07AB)=============");
    Utils::Log("r",r);
    Utils::Log("g",b);
    Utils::Log("b",b);
    getchar();
    return 0;
}

utils.h

#ifndef UTILS_H
#define UTILS_H

#include <iostream>

struct Utils{
    template<typename K,typename T>
    static void Log(K k,T t){
        std::cout << k << "=" << t << std::endl;
    }

    template<typename T>
    static void Print(T t){
        std::cout << t << std::endl;
    }

    template<typename K,typename T>
    static void LogHex(K k,T t){
        std::cout << k << "=" << std::hex <<  t << std::endl;
    }
};


#endif 

輸出

hello=world
===========ColorHexToRGBCpp98(FFFFFF)==============
r=255
g=255
b=255
============ColorHexToRGBCpp98(FE07AB)=============
r=254
g=171
b=171
===========ColorHexToRGBCpp11(FFFFFF)==============
r=255
g=255
b=255
============ColorHexToRGBCpp11(FE07AB)=============
r=254
g=171
b=171

相關文章