C + + 中的整数到十六进制字符串

“ HTTP”方案用于通过 HTTP 协议定位网络资源。本节定义了 http URL 的方案特定的语法和语义。”http://www.w3.org/Protocols/rfc2616/rfc2616.html

http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]

如何在 C + + 中将整数转换为十六进制字符串?

我可以找到一些方法来做到这一点,但他们似乎主要是针对 C。在 C + + 中似乎没有一种本地化的方法可以做到这一点。这是一个非常简单的问题,虽然,我有一个 int,我想转换成一个十六进制字符串,以后打印。

449962 次浏览

最后,我建议这样一个函数:

template< typename T >
std::string int_to_hex( T i )
{
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
return stream.str();
}

只要把它打印成十六进制数:

int i = /* ... */;
std::cout << std::hex << i;
int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30

使用 std::stringstream将整数转换为字符串,并使用它的特殊操作器设置基数。例如:

std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();

它是有效的: 参见 维基百科RFC 1738(3.3. HTTP)RFC 3986(3. 语法组件)

你可以试试下面的方法,很有效。

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;


template <class T>
string to_string(T t, ios_base & (*f)(ios_base&))
{
ostringstream oss;
oss << f << t;
return oss.str();
}


int main ()
{
cout<<to_string<long>(123456, hex)<<endl;
system("PAUSE");
return 0;
}
() {

对于那些发现许多/大多数 ios::fmtflags都不能与 std::stringstream一起工作的人来说,还是喜欢科内尔在很久以前发布的模板思想的,下面的工作相对简洁:

#include <iomanip>
#include <sstream>




template< typename T >
std::string hexify(T i)
{
std::stringbuf buf;
std::ostream os(&buf);




os << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2)
<< std::hex << i;


return buf.str().c_str();
}




int someNumber = 314159265;
std::string hexified = hexify< int >(someNumber);
Cout < < to _ string < long > (123456,hex) < < endl;

为了使它更轻更快,我建议使用直接填充的字符串。

template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1) {
static const char* digits = "0123456789ABCDEF";
std::string rc(hex_len,'0');
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
rc[i] = digits[(w>>j) & 0x0f];
return rc;
}
系统(「暂停」) ; 报税表0;

代号:

#include <iomanip>
#include <sstream>
...
string intToHexString(int intValue) {


string hexStr;


/// integer value to hex-string
std::stringstream sstream;
sstream << "0x"
<< std::setfill ('0') << std::setw(2)
<< std::hex << (int)intValue;


hexStr= sstream.str();
sstream.clear();    //clears out the stream-string


return hexStr;
}

URI 规范

你不能确定你使用的是什么服务器端框架(如果有的话) ,但是你的服务器端框架可能会假设查询字符串总是在名称-值对中,并且它可能会被不是那种格式的查询字符串卡住(例如 ?bar)。如果解析查询字符串的是您自己的自定义代码,那么您只需确保处理该查询字符串格式。如果它是一个框架,那么您需要查阅您的文档或者简单地测试它,看看它是如何处理的。

URI 规范中唯一相关的部分是知道第一个 ?和第一个 #之间的 一切是否符合规范中查询的定义。它可以包含任何字符,如 [:/.?]。这意味着诸如 ?bar?ten+green+apples之类的查询字符串是有效的。

Erl 的 URI 提供了解析这类结构的方法
$uri->query_keywords
$uri->query_keywords( $keywords, ... )
$uri->query_keywords( \@keywords )
Sets and returns query components that use the keywords separated by "+" format.

Js url(没有特殊支持)

作为另一个更为常见的例子,node.js采用正常的路由并简化解析

    找到 我是 RFC 3986

    HTML 规格

  • 一根绳子
  • isindex不是有意义的 HTML5。

  • 或者,键和值的对象(使用 parseQueryString)

大多数其他 URI 解析 API 都遵循类似的内容。

    它提供了 不赞成,仅用作表单中的第一个元素,并且提交时不使用名称。

  • 类似的实现,但只返回查询的字符串
[3] 翻译成 CppTest的语言是这样的:

TEST_ASSERT(int_to_hex(char(0x12)) == "12");
TEST_ASSERT(int_to_hex(short(0x1234)) == "1234");
TEST_ASSERT(int_to_hex(long(0x12345678)) == "12345678");
TEST_ASSERT(int_to_hex((long long)(0x123456789abcdef0)) == "123456789abcdef0");
TEST_ASSERT(int_to_hex(0x123, 1) == "123");
TEST_ASSERT(int_to_hex(0x123, 8) == "00000123");
// width deduction test as suggested by Lightness Races in Orbit:
TEST_ASSERT(int_to_hex(short(0x12)) == "0012");

在 MySQL 中使用浮点数和十进制数据类型有什么区别。

我编辑这段代码是为了添加对 std: : to _ string 的调用,因为传递给 std::stringstream的8位整数类型(例如 std::uint8_t值)被视为 char,这不会给出您想要的结果。将这些整数传递给 std::to_string可以正确地处理它们,并且在使用其他较大的整数类型时不会造成损害。当然,在这些情况下,您可能会受到轻微的性能影响,因为 std: : to _ string 调用是不必要的。

我什么时候该用哪个?

注意: 我本来可以在原始答案的评论中添加这个,但是我没有代表来评论。

#include <boost/format.hpp>
...
cout << (boost::format("%x") % 1234).str();  // output is: 4d2

我的解决方案。只有整数类型是允许的。

您可以在 https://replit.com/@JomaCorpFX/ToHex上测试/运行

可以在第二个参数中设置可选的前缀0x。

定义 h

#include  <iomanip>
#include <sstream>


template <class T, class T2 = typename std::enable_if<std::is_integral<T>::value>::type>
static std::string ToHex(const T & data, bool addPrefix = true);






template<class T, class>
inline std::string ToHex(const T & data, bool addPrefix)
{
std::stringstream sstream;
sstream << std::hex;
std::string ret;
if (typeid(T) == typeid(char) || typeid(T) == typeid(unsigned char) || sizeof(T)==1)
{
sstream << static_cast<int>(data);
ret = sstream.str();
if (ret.length() > 2)
{
ret = ret.substr(ret.length() - 2, 2);
}
}
else
{
sstream << data;
ret = sstream.str();
}
return (addPrefix ? u8"0x" : u8"") + ret;
}

Main.cpp

#include <iostream>
#include "definition.h"


int main()
{
std::cout << ToHex<unsigned char>(254) << std::endl;
std::cout << ToHex<char>(-2) << std::endl;
std::cout << ToHex<int>(-2) << std::endl;
std::cout << ToHex<long long>(-2) << std::endl;
    

std::cout<< std::endl;
std::cout << ToHex<unsigned char>(254, false) << std::endl;
std::cout << ToHex<char>(-2, false) << std::endl;
std::cout << ToHex<int>(-2, false) << std::endl;
std::cout << ToHex<long long>(-2, false) << std::endl;
return 0;
}

结果:

0xfe
0xfe
0xfffffffe
0xfffffffffffffffe


fe
fe
fffffffe
fffffffffffffffe

output

我想添加一个答案来欣赏 C + + 语言的美。对高低层次工作的适应性。编程愉快。

public:template <class T,class U> U* Int2Hex(T lnumber, U* buffer)
{
const char* ref = "0123456789ABCDEF";
T hNibbles = (lnumber >> 4);


unsigned char* b_lNibbles = (unsigned char*)&lnumber;
unsigned char* b_hNibbles = (unsigned char*)&hNibbles;


U* pointer = buffer + (sizeof(lnumber) << 1);


*pointer = 0;
do {
*--pointer = ref[(*b_lNibbles++) & 0xF];
*--pointer = ref[(*b_hNibbles++) & 0xF];
} while (pointer > buffer);


return buffer;
}

例子:

char buffer[100] = { 0 };
Int2Hex(305419896ULL, buffer);//returns "0000000012345678"
Int2Hex(305419896UL, buffer);//returns "12345678"
Int2Hex((short)65533, buffer);//returns "FFFD"
Int2Hex((char)18, buffer);//returns "12"


wchar_t buffer[100] = { 0 };
Int2Hex(305419896ULL, buffer);//returns L"0000000012345678"
Int2Hex(305419896UL, buffer);//returns L"12345678"
Int2Hex((short)65533, buffer);//returns L"FFFD"
Int2Hex((char)18, buffer);//returns L"12"
#include <iostream>
#include <sstream>


int main()
{
unsigned int i = 4967295; // random number
std::string str1, str2;
unsigned int u1, u2;


std::stringstream ss;

使用 void 指针:

// INT to HEX
ss << (void*)i;       // <- FULL hex address using void pointer
ss >> str1;          //     giving address value of one given in decimals.
ss.clear();         // <- Clear bits
// HEX to INT
ss << std::hex << str1;   // <- Capitals doesn't matter so no need to do extra here
ss >> u1;
ss.clear();

添加0x:

// INT to HEX with 0x
ss << "0x" << (void*)i;   // <- Same as above but adding 0x to beginning
ss >> str2;
ss.clear();
// HEX to INT with 0x
ss << std::hex << str2;   // <- 0x is also understood so need to do extra here
ss >> u2;
ss.clear();

产出:

std::cout << str1 << std::endl; // 004BCB7F
std::cout << u1 << std::endl;   // 4967295
std::cout << std::endl;
std::cout << str2 << std::endl; // 0x004BCB7F
std::cout << u2 << std::endl;   // 4967295




return 0;
}

对于固定数目的数字,例如2:

    static const char* digits = "0123456789ABCDEF";//dec 2 hex digits positional map
char value_hex[3];//2 digits + terminator
value_hex[0] = digits[(int_value >> 4) & 0x0F]; //move of 4 bit, that is an HEX digit, and take 4 lower. for higher digits use multiple of 4
value_hex[1] = digits[int_value & 0x0F]; //no need to move the lower digit
value_hex[2] = '\0'; //terminator

您还可以编写一个 for 循环变量来处理可变数字金额

效益:

  • 速度: 这是一个最小的位操作,没有外部函数调用
  • 内存: 它使用本地字符串,无需分配出函数栈帧,无需空闲内存。无论如何,如果需要,您可以使用字段或全局值使 value _ ex 保持在堆栈框架之外

(咒语)

char buf[_MAX_U64TOSTR_BASE2_COUNT];
_itoa_s(10, buf, _countof(buf), 16);
printf("%s\n", buf);    // a

Swprintf _ s

uint8_t x = 10;
wchar_t buf[_MAX_ITOSTR_BASE16_COUNT];
swprintf_s(buf, L"%02X", x);

Char _ to _ hex 返回两个字符的字符串

const char HEX_MAP[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};


char replace(unsigned char c)
{
return HEX_MAP[c & 0x0f];
}


std::string char_to_hex(unsigned char c)
{
std::string hex;


// First four bytes
char left = (c >> 4);
// Second four bytes
char right = (c & 0x0f);


hex += replace(left);
hex += replace(right);


return hex;
}

由于使用了 C + + 20和 std::format,您可能会这样做:

std::format("{:#x}", your_int);    // 0x2a
std::format("{:#010x}", your_int); // 0x0000002a

演示

你可以用 C + + 20 std::format:

std::string s = std::format("{:x}", 42); // s == 2a

std::format被广泛使用之前,你可以使用 { fmt }库std::format是基于(Godbolt) :

std::string s = fmt::format("{:x}", 42); // s == 2a

免责声明 : 我是{ fmt }和 C + + 20 std::format的作者。

您可以将 宏观定义为如下所示的一行程序。

#include <sstream>
#define to_hex_str(hex_val) (static_cast<std::stringstream const&>(std::stringstream() << "0x" << std::hex << hex_val)).str()

这个问题很老了,但是给出的答案依我的看法并不是最好的。 如果您使用 C + + 20,那么您可以选择使用 std::format,这是一个非常好的解决方案。但是,如果您使用的是 C + + 11/14/17或以下版本,则不会有此选项。

大多数其他答案要么使用 std::stringstream,要么自己实现转换,直接修改底层字符串缓冲区。 第一个选项相当沉重,第二个选项本身就不安全,而且容易出错。

因为我最近不得不实现一个整数十六进制字符串,所以我选择使用函数重载和模板部分专门化来实现一个真正的 C + + 安全实现,让编译器处理类型检查。代码使用 sprintf(std::to_string的标准库通常使用它的一种风格)。它依靠模板部分专门化来正确选择正确的 sprintf格式和前导0加法。它分别正确地处理不同的操作系统和体系结构的不同指针大小和 unsigned long大小。(4/4/4,4/4/8,4/8/8)

这个答案的目标是 C + + 11

H 档案:

#ifndef STRINGUTILS_H_
#define STRINGUTILS_H_


#include <string>


namespace string_utils
{
/* ... Other string utils ... */
    

std::string hex_string(unsigned char v);
std::string hex_string(unsigned short v);
std::string hex_string(unsigned int v);
std::string hex_string(unsigned long v);
std::string hex_string(unsigned long long v);
std::string hex_string(std::ptrdiff_t v);


} // namespace string_utils


#endif

CPP 文件

#include "stringutils.h"


#include <cstdio>


namespace
{
template <typename T, int Width> struct LModifier;


template <> struct LModifier<unsigned char, sizeof(unsigned char)>
{
static constexpr char fmt[] = "%02hhX";
};
template <> struct LModifier<unsigned short, sizeof(unsigned short)>
{
static constexpr char fmt[] = "%04hX";
};
template <> struct LModifier<unsigned int, sizeof(unsigned int)>
{
static constexpr char fmt[] = "%08X";
};
template <> struct LModifier<unsigned long, 4>
{
static constexpr char fmt[] = "%08lX";
};
template <> struct LModifier<unsigned long, 8>
{
static constexpr char fmt[] = "%016lX";
};
template <> struct LModifier<unsigned long long, sizeof(unsigned long long)>
{
static constexpr char fmt[] = "%016llX";
};
template <> struct LModifier<std::ptrdiff_t, 4>
{
static constexpr char fmt[] = "%08tX";
};
template <> struct LModifier<std::ptrdiff_t, 8>
{
static constexpr char fmt[] = "%016tX";
};


constexpr char LModifier<unsigned char, sizeof(unsigned char)>::fmt[];
constexpr char LModifier<unsigned short, sizeof(unsigned short)>::fmt[];
constexpr char LModifier<unsigned int, sizeof(unsigned int)>::fmt[];
constexpr char LModifier<unsigned long, sizeof(unsigned long)>::fmt[];
constexpr char LModifier<unsigned long long, sizeof(unsigned long long)>::fmt[];
constexpr char LModifier<std::ptrdiff_t, sizeof(std::ptrdiff_t)>::fmt[];


template <typename T, std::size_t BUF_SIZE = sizeof(T) * 2U> std::string hex_string_(T v)
{
std::string ret(BUF_SIZE + 1, 0);
std::sprintf((char *)ret.data(), LModifier<T, sizeof(T)>::fmt, v);
return ret;
}
} // anonymous namespace


std::string string_utils::hex_string(unsigned char v)
{
return hex_string_(v);
}
std::string string_utils::hex_string(unsigned short v)
{
return hex_string_(v);
}
std::string string_utils::hex_string(unsigned int v)
{
return hex_string_(v);
}
std::string string_utils::hex_string(unsigned long v)
{
return hex_string_(v);
}
std::string string_utils::hex_string(unsigned long long v)
{
return hex_string_(v);
}
std::string string_utils::hex_string(std::ptrdiff_t v)
{
return hex_string_(v);
}


我可以看到其他人用来作为答案的所有复杂的代码样本,但是在 C + + 应用程序中简单地使用这些代码并没有什么错:

    printf ("%04x", num);

For num = 128:

    007f

Https://en.wikipedia.org/wiki/printf_format_string

C + + 实际上是已经扩展的原始 C 语言,所以 C 中的任何东西都是完全有效的 C + + 。

一种新的 C + + 17方式: 来自 <charconv>(https://en.cppreference.com/w/cpp/utility/to_chars)的 std::to_chars:

char addressStr[20] = { 0 };
std::to_chars(std::begin(addressStr), std::end(addressStr), address, 16);
return std::string{addressStr};

这有点冗长,因为 std::to_chars使用一个预分配的缓冲区来避免动态分配,但是这也允许您优化代码,因为如果这是在热点中,分配会变得非常昂贵。

对于额外的优化,您可以省略预初始化缓冲区并检查 to_chars的返回值以检查错误并获得所写数据的长度。注意: to_chars不写空终止符!

另一个简单的方法

#include<iostream>
#include<iomanip> // for setbase(), works for base 8,10 and 16 only
using namespace std;




int main(){
int x = (16*16+16+1)*15;
string ans;




stringstream ss;
ss << setbase(16) << x << endl;
ans = ss.str();




cout << ans << endl;//prints fff

使用变量:

char selA[12];

然后:

snprintf(selA, 12, "SELA;0x%X;", 85);

将导致包含字符串 SELA;0x55;selA

请注意,围绕 55的内容只是与我的应用程序中使用的串行协议有关的细节。