将 hexdump 值作为字符串传递
Passing hexdump values as string
我有一个接受 hexdump 值列表的函数,它们作为初始化列表参数传递给函数并复制到缓冲区:
void func(void * buff, std::initializer_list<unsigned char> s) {
memcpy(buff, s.begin(), s.size());
}
我想要做的是将这些值也作为字符串传递,如“0x04 0x02 0x01”。两者都可以作为字符串或 initializer_list 传递给上面函数的参数。我知道我必须创建模板来实现这一点。到目前为止,这就是我所尝试过的。我无法实现为模板
void func(void * buff, std::string s) {
unsigned char arr[s.length() + 1];
strcpy(arr, s.c_str());
std::initializer_list<unsigned char> hex_values(arr);
memcpy(d, hex_values.begin(), hex_values.size());
}
您可以将字符串放入 std::istringstream
并从中进行格式化输入:
#include <algorithm>
#include <iterator>
void func(void* buff, const std::string& s) {
std::istringstream is(s);
is.setf(is.hex, is.basefield); // set the istream in hex mode
// copy hex values from the istream and store in buff
std::copy(std::istream_iterator<unsigned>(is),
std::istream_iterator<unsigned>{},
static_cast<unsigned char*>(buff)
);
}
完整示例:
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <sstream>
void func(void* buff, std::initializer_list<unsigned char> s) {
std::memcpy(buff, s.begin(), s.size());
}
void func(void* buff, const std::string& s) {
std::istringstream is(s);
is.setf(is.hex, is.basefield); // set the istream in hex mode
// copy hex values from the istream and store in buff
std::copy(std::istream_iterator<unsigned>(is),
std::istream_iterator<unsigned>{},
static_cast<unsigned char*>(buff)
);
}
template <size_t N>
void show(unsigned char(&b)[N]) {
for(unsigned ch : b) {
std::cout << std::setw(2) << ch << ' ';
}
std::cout << '\n';
}
int main() {
unsigned char buff[4];
std::cout << std::hex;
func(buff, "0x01 0xFF 0x7F 0x80");
show(buff);
func(buff, {0x12, 0xF4, 0x1A, 0x17});
show(buff);
}
输出
1 ff 7f 80
12 f4 1a 17
您还可以添加一个更通用的版本,将迭代器作为输入:
template<typename It>
void func(void* buff, It begin, It end) {
std::copy(begin, end, static_cast<unsigned char*>(buff));
}
使用 SFINAE 检查迭代器迭代的内容是否可转换为 unsigned char
,它可能看起来像这样:
#include <type_traits>
template<typename It,
std::enable_if_t<
std::is_convertible_v<typename std::iterator_traits<It>::value_type,
unsigned char>>* = nullptr>
void func(void* buff, It begin, It end) {
std::copy(begin, end, static_cast<unsigned char*>(buff));
}
我有一个接受 hexdump 值列表的函数,它们作为初始化列表参数传递给函数并复制到缓冲区:
void func(void * buff, std::initializer_list<unsigned char> s) {
memcpy(buff, s.begin(), s.size());
}
我想要做的是将这些值也作为字符串传递,如“0x04 0x02 0x01”。两者都可以作为字符串或 initializer_list 传递给上面函数的参数。我知道我必须创建模板来实现这一点。到目前为止,这就是我所尝试过的。我无法实现为模板
void func(void * buff, std::string s) {
unsigned char arr[s.length() + 1];
strcpy(arr, s.c_str());
std::initializer_list<unsigned char> hex_values(arr);
memcpy(d, hex_values.begin(), hex_values.size());
}
您可以将字符串放入 std::istringstream
并从中进行格式化输入:
#include <algorithm>
#include <iterator>
void func(void* buff, const std::string& s) {
std::istringstream is(s);
is.setf(is.hex, is.basefield); // set the istream in hex mode
// copy hex values from the istream and store in buff
std::copy(std::istream_iterator<unsigned>(is),
std::istream_iterator<unsigned>{},
static_cast<unsigned char*>(buff)
);
}
完整示例:
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <sstream>
void func(void* buff, std::initializer_list<unsigned char> s) {
std::memcpy(buff, s.begin(), s.size());
}
void func(void* buff, const std::string& s) {
std::istringstream is(s);
is.setf(is.hex, is.basefield); // set the istream in hex mode
// copy hex values from the istream and store in buff
std::copy(std::istream_iterator<unsigned>(is),
std::istream_iterator<unsigned>{},
static_cast<unsigned char*>(buff)
);
}
template <size_t N>
void show(unsigned char(&b)[N]) {
for(unsigned ch : b) {
std::cout << std::setw(2) << ch << ' ';
}
std::cout << '\n';
}
int main() {
unsigned char buff[4];
std::cout << std::hex;
func(buff, "0x01 0xFF 0x7F 0x80");
show(buff);
func(buff, {0x12, 0xF4, 0x1A, 0x17});
show(buff);
}
输出
1 ff 7f 80
12 f4 1a 17
您还可以添加一个更通用的版本,将迭代器作为输入:
template<typename It>
void func(void* buff, It begin, It end) {
std::copy(begin, end, static_cast<unsigned char*>(buff));
}
使用 SFINAE 检查迭代器迭代的内容是否可转换为 unsigned char
,它可能看起来像这样:
#include <type_traits>
template<typename It,
std::enable_if_t<
std::is_convertible_v<typename std::iterator_traits<It>::value_type,
unsigned char>>* = nullptr>
void func(void* buff, It begin, It end) {
std::copy(begin, end, static_cast<unsigned char*>(buff));
}