我有一个程序,它接受std::vector<uint8_t>
并返回格式为十六进制字符的std::string
,后跟ASCII文本,如下所示:
03 00 00 54 00 00 00 08 00 00 00 00 00 00 00 00 ASCII ... T ............
74 21 B8 30 00 2C 2E 31 62 30 74 21 A8 30 00 2C ASCII t!.0。,。1b0t!.0。,
这是代码的主要部分:
std::vector<uint8_t> value;
std::stringstream printed_line;
std::stringstream tempHexLine;
std::stringstream tempAsciiLine;
for (size_t printed_bytes = 0; printed_bytes < value.size(); printed_bytes += bytes_line) {
for (int i = 0; i < bytes_line; ++i) {
tempHexLine << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << static_cast<uint16_t>(value[printed_bytes + i]) << " ";
}
for (int i = 0; i < bytes_line; ++i) {
if(isprint(value[printed_bytes + i])) {
if (value[printed_bytes + i] == 60) {
tempAsciiLine << "<";
} else if(value[printed_bytes + i] == 62) {
tempAsciiLine << ">";
} else {
tempAsciiLine << static_cast<char>(value[printed_bytes + i]);
}
} else {
tempAsciiLine << ".";
}
}
}
printed_line << tempHexLine.str() << " " << tempAsciiLine .str();
我试图解决的问题是,当矢量大小很大(> 1000个元素)时,这需要很长时间 - 大约70%的样本使用Very Sleepy {{1}功能。
将这样的格式应用于向量中的值的最快方法是什么?有很好的定义数据需要将向量分解,所以看起来一次输出一个字节是一种低效的方式。
答案 0 :(得分:4)
有效写作应该是微不足道的。试试这个:
#include <algorithm>
#include <cstdint>
#include <iterator>
#include <string>
#include <vector>
std::string to_hex(std::vector<uint8_t> const & v)
{
std::string result;
result.reserve(4 * v.size() + 6);
for (uint8_t c : v)
{
static constexpr char alphabet[] = "0123456789ABCDEF";
result.push_back(alphabet[c / 16]);
result.push_back(alphabet[c % 16]);
result.push_back(' ');
}
result.append("ASCII ", 6);
std::copy(v.begin(), v.end(), std::back_inserter(result));
return result;
}
答案 1 :(得分:1)
您可以为单个字符使用一些转换表:
#include <cctype>
#include <cstring>
#include <iostream>
#include <vector>
class HexadecimalTable
{
public:
static const unsigned ElementSize = 4;
HexadecimalTable();
const char* operator [] (std::uint8_t value) const {
return m_table[value];
}
private:
typedef char hex_type[ElementSize];
hex_type m_table[256];
};
HexadecimalTable::HexadecimalTable() {
static const char hex[] = "0123456789ABCDEF";
for(int i = 0; i < 256; ++i) {
m_table[i][0] = hex[i / 16];
m_table[i][1] = hex[i % 16];
m_table[i][2] = 0;
}
}
class EntityTable
{
public:
static const unsigned ElementSize = 8;
EntityTable();
const char* operator [] (std::uint8_t value) const {
return m_table[value];
}
private:
typedef char entity_type[ElementSize];
entity_type m_table[256];
};
EntityTable::EntityTable() {
// Printable and non printable characters
for(int i = 0; i < 256; ++i) {
if(std::isprint(i)) m_table[i][0] = char(i);
else m_table[i][0] = '.';
m_table[i][1] = 0;
}
// Special characters
std::strcpy(m_table['<'], "<");
std::strcpy(m_table['>'], ">");
// ...
}
std::string hex_display(std::vector<uint8_t> const & v) {
HexadecimalTable hexadecimal;
EntityTable entities;
std::string result;
result.reserve((HexadecimalTable::ElementSize + EntityTable::ElementSize) * v.size());
for (uint8_t c : v) {
result.append(hexadecimal[c]);
result.push_back(' ');
}
for (uint8_t c : v)
result.append(entities[c]);
return result;
}
int main()
{
std::vector<std::uint8_t> v = {
0x74, 0x21, 0xB8, 0x30,
0x00, 0x2C, 0x2E, 0x31,
0x62, 0x30, 0x74, 0x21,
0xA8, 0x30, 60, 62
};
std::cout << hex_display(v) << std::endl;
return 0;
}