只是为了演示另一种可能更快的方法来完成操作,请考虑将所有内容读入到一个数组中,并使用自定义迭代器进行转换。
class ToHexIterator : public std::iterator<std::input_iterator_tag, int>{
char* it_;
char* end_;
int current_;
bool isHex(const char c){
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
char toUpperCase(const char c){
if (c >= 'a' && c <= 'f'){
return (c - 'a') + 'A';
}
return c;
}
int toNibble(const char c){
auto x = toUpperCase(c);
if (x >= '0' && x <= '9'){
return x - '0';
}
else {
return (x - 'A') + 10;
}
}
public:
ToHexIterator() :it_{ nullptr }, end_{ nullptr }, current_{}{}
ToHexIterator(char* begin, char* end) :it_{ begin }, end_{ end }, current_{}{
while (!isHex(*it_) && it_ != end_){ ++it_; };
++(*this);
}
bool operator==(const ToHexIterator &other){
return it_ == nullptr && end_ == nullptr && other.it_ == nullptr && other.end_ == nullptr;
}
bool operator!=(const ToHexIterator &other){
return !(*this == other);
}
int operator*(){
return current_;
}
ToHexIterator & operator++(){
current_ = 0;
if (it_ != end_) {
while (isHex(*it_) && it_ != end_){
current_ <<= 4;
current_ += toNibble(*it_);
++it_;
};
while (!isHex(*it_) && it_ != end_){ ++it_; };
}
else {
it_ = nullptr;
end_ = nullptr;
}
return *this;
}
ToHexIterator operator++(int){
ToHexIterator temp(*this);
++(*this);
return temp;
}
};
基本使用情况如下:
char in[] = "1,3,8,b,e,ff,10,--";
std::vector<int> v;
std::copy(ToHexIterator{ std::begin(in), std::end(in) }, ToHexIterator{}, std::back_inserter(v));
请注意,使用查找表进行ASCII到十六进制半字节转换可能会更快。
速度可能非常依赖于编译器优化和平台,但是由于一些istringstream函数是作为虚拟函数或函数指针实现的(取决于标准库的实现),因此优化器难以处理它们。在我的代码中,没有虚拟函数或函数指针,唯一的循环是在std::copy实现内部,优化器已经习惯了处理它。通常循环直到两个地址相等比循环直到某个变化指针指向的东西等于某个东西要快得多。归根结底,这都是猜测和巫术,但在我的机器上的MSVC13上,我的速度大约快10倍。这里有一个实时示例
http://ideone.com/nuwu15在GCC上,速度介于10倍和3倍之间,具体取决于运行和哪个测试先运行(可能是因为某些缓存效应)。
总的来说,在这个抽象层面上,无疑还有更多的优化空间等等。任何声称“我的速度总是更快”的人都是在卖蛇油。
更新:使用编译时生成的查找表可以进一步提高速度:
http://ideone.com/ady8GY(请注意,我增加了输入字符串的大小以减少噪音,因此这与上面的示例不是直接可比的)。
std::istringstream
和std::hex
I/O操作符一起使用。跳过,
字符可以按此示例所示完成。 - πάντα ῥεῖwhile
循环之前,你需要调用iss >> std::hex;
。或者你可以写成while(iss >> std::hex >> num || !iss.eof())
。此外,请注意BYTE
只是unsigned char
的一个别名,你应该首先将其输入到unsigned int
中。 - πάντα ῥεῖ