我正在从文件中读取一个字符串,所以它是char
数组的形式。我需要对字符串进行标记,并将每个char
数组标记保存为数组中的uint8_t
十六进制值。
char* starting = "001122AABBCC";
// ...
uint8_t[] ending = {0x00,0x11,0x22,0xAA,0xBB,0xCC}
如何从starting
转换为ending
?感谢。
答案 0 :(得分:2)
这是一个完整的工作计划。它基于Rob I的解决方案,但修复了几个已经过测试的问题。
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
const char* starting = "001122AABBCC";
int main()
{
std::string starting_str = starting;
std::vector<unsigned char> ending;
ending.reserve( starting_str.size());
for (int i = 0 ; i < starting_str.length() ; i+=2) {
std::string pair = starting_str.substr( i, 2 );
ending.push_back(::strtol( pair.c_str(), 0, 16 ));
}
for(int i=0; i<ending.size(); ++i) {
printf("0x%X\n", ending[i]);
}
}
答案 1 :(得分:1)
strtoul会将您选择的任何基础中的文本转换为字节。你必须做一些工作来将输入字符串分成单个数字,或者你可以一次转换32或64位。
ps uint8_t[] ending = {0x00,0x11,0x22,0xAA,0xBB,0xCC}
没有任何意义,你没有将数据存储在uint8中作为'hex',你存储的是字节,它取决于你(或你的调试器)如何解释二进制数据
答案 2 :(得分:1)
使用C ++ 11,您可以使用std::stoi
:
std::vector<uint8_t> convert(const std::string& s)
{
if (s.size() % 2 != 0) {
throw std::runtime_error("Bad size argument");
}
std::vector<uint8_t> res;
res.reserve(s.size() / 2);
for (std::size_t i = 0, size = s.size(); i != size; i += 2) {
std::size_t pos = 0;
res.push_back(std::stoi(s.substr(i, 2), &pos, 16));
if (pos != 2) {
throw std::runtime_error("bad character in argument");
}
}
return res;
}
答案 3 :(得分:1)
我认为任何规范的答案(例如,赏金笔记)都会涉及解决方案中的一些不同阶段:
鉴于此类转换的有用性,解决方案应该包括一些灵活性w.r.t.正在使用的类型和所需的语言环境。
从一开始,给出了更多规范答案的请求日期&#34; (大约在2014年8月)将适用C ++ 11的自由使用。
代码的带注释版本,其类型对应于OP:
std::vector<std::uint8_t> convert(std::string const& src)
{
// error check on the length
if ((src.length() % 2) != 0) {
throw std::invalid_argument("conversion error: input is not even length");
}
auto ishex = [] (decltype(*src.begin()) c) {
return std::isxdigit(c, std::locale()); };
// error check on the data contents
if (!std::all_of(std::begin(src), std::end(src), ishex)) {
throw std::invalid_argument("conversion error: input values are not not all xdigits");
}
// allocate the result, initialised to 0 and size it to the correct length
std::vector<std::uint8_t> result(src.length() / 2, 0);
// run the actual conversion
auto str = src.begin(); // track the location in the string
std::for_each(result.begin(), result.end(), [&str](decltype(*result.begin())& element) {
element = static_cast<std::uint8_t>(std::stoul(std::string(str, str + 2), nullptr, 16));
std::advance(str, 2); // next two elements
});
return result;
}
代码的模板版本增加了灵活性;
template <typename Int /*= std::uint8_t*/,
typename Char = char,
typename Traits = std::char_traits<Char>,
typename Allocate = std::allocator<Char>,
typename Locale = std::locale>
std::vector<Int> basic_convert(std::basic_string<Char, Traits, Allocate> const& src, Locale locale = Locale())
{
using string_type = std::basic_string<Char, Traits, Allocate>;
auto ishex = [&locale] (decltype(*src.begin()) c) {
return std::isxdigit(c, locale); };
if ((src.length() % 2) != 0) {
throw std::invalid_argument("conversion error: input is not even length");
}
if (!std::all_of(std::begin(src), std::end(src), ishex)) {
throw std::invalid_argument("conversion error: input values are not not all xdigits");
}
std::vector<Int> result(src.length() / 2, 0);
auto str = std::begin(src);
std::for_each(std::begin(result), std::end(result), [&str](decltype(*std::begin(result))& element) {
element = static_cast<Int>(std::stoul(string_type(str, str + 2), nullptr, 16));
std::advance(str, 2);
});
return result;
}
convert()
函数可以基于basic_convert()
,如下所示:
std::vector<std::uint8_t> convert(std::string const& src)
{
return basic_convert<std::uint8_t>(src, std::locale());
}
答案 4 :(得分:0)
uint8_t通常只不过是unsigned char的typedef。如果您正在从文件中读取字符,您应该能够像签名的char数组一样将它们读入unsigned char数组,并且unsigned char数组 是一个uint8_t数组。
答案 5 :(得分:0)
我会尝试这样的事情:
std::string starting_str = starting;
uint8_t[] ending = new uint8_t[starting_str.length()/2];
for (int i = 0 ; i < starting_str.length() ; i+=2) {
std::string pair = starting_str.substr( i, i+2 );
ending[i/2] = ::strtol( pair.c_str(), 0, 16 );
}
没有测试它,但它对我来说很好......
答案 6 :(得分:0)
您可以将自己的转换从 char {'0','1',...'E','F'}添加到 uint8_t :
uint8_t ctoa(char c)
{
if( c >= '0' && c <= '9' ) return c - '0';
else if( c >= 'a' && c <= 'f' ) return 0xA + c - 'a';
else if( c >= 'A' && c <= 'F' ) return 0xA + c - 'A';
else return 0;
}
然后将字符串转换为数组很容易:
uint32_t endingSize = strlen(starting)/2;
uint8_t* ending = new uint8_t[endingSize];
for( uint32_t i=0; i<endingSize; i++ )
{
ending[i] = ( ctoa( starting[i*2] ) << 4 ) + ctoa( starting[i*2+1] );
}
答案 7 :(得分:0)
这个简单的解决方案应该适用于您的问题
char* starting = "001122AABBCC";
uint8_t ending[12];
// This algo will work for any size of starting
// However, you have to make sure that the ending have enough space.
int i=0;
while (i<strlen(starting))
{
// convert the character to string
char str[2] = "\0";
str[0] = starting[i];
// convert string to int base 16
ending[i]= (uint8_t)atoi(str,16);
i++;
}
答案 8 :(得分:-1)
uint8_t* ending = static_cast<uint8_t*>(starting);