在c++中将字节串拆分为字节向量
Splitting a string of bytes to vector of BYTES in C++
我有一个字节串,看起来像这样:
"1,3,8,b,e,ff,10"
如何将该字符串拆分为包含以下值的std:: BYTEs vector:
[0x01, 0x03, 0x08, 0x0b, 0x0e, 0xff, 0x10]
我试图使用','作为分隔符分割字符串,但我有一些麻烦让这个工作。谁能告诉我如何完成这件事?
所以我试过了:
std::istringstream iss("1 3 8 b e ff 10");
BYTE num = 0;
while(iss >> num || !iss.eof())
{
if(iss.fail())
{
iss.clear();
std::string dummy;
iss >> dummy;
continue;
}
dataValues.push_back(num);
}
但是这会将ascii字节值推入vector:
49 //1
51 //3
56 //8
98 //b
101 //e
102 //f
102 //f
49 //1
48 //0
我试着用
填充向量 0x01
0x03
0x08
0x0b
0x0e
0xff
0x10
你刚刚错过了一些小问题,出现在你的用例中,从我的评论链接的答案:
std::istringstream iss("1,3,8,b,e,ff,10");
std::vector<BYTE> dataValues;
unsigned int num = 0; // read an unsigned int in 1st place
// BYTE is just a typedef for unsigned char
while(iss >> std::hex >> num || !iss.eof()) {
if(iss.fail()) {
iss.clear();
char dummy;
iss >> dummy; // use char as dummy if no whitespaces
// may occur as delimiters
continue;
}
if(num <= 0xff) {
dataValues.push_back(static_cast<BYTE>(num));
}
else {
// Error single byte value expected
}
}
您可以在ideone上看到完整的工作示例
一个工作示例代码(在GCC 4.9.0和c++ 11中测试):
文件save.txt
包含:1,3,8,b,e,ff,10
作为第一行,也是唯一一行。
1
3
8
b
e
ff
10
思路是:
- 使用std::getline逐行读取
- 使用boost::split根据分隔符拆分行。
- 用户std::stringstream将十六进制字符串转换为无符号字符。
#include <fstream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/lexical_cast.hpp>
int main(int argc, char* argv[]) {
std::ifstream ifs("e:\save.txt");
std::string line;
std::vector<std::string> tokens;
std::getline(ifs, line);
boost::split(tokens, line, boost::is_any_of(","));
std::vector<unsigned char> values;
for (const auto& t : tokens) {
unsigned int x;
std::stringstream ss;
ss << std::hex << t;
ss >> x;
values.push_back(x);
}
for (auto v : values) {
std::cout << std::hex << (unsigned long)v << std::endl;
}
return 0;
}
只是为了演示另一种可能更快的方法,考虑将所有内容读入数组并使用自定义迭代器进行转换。
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_{}{} //default constructed means end iterator
ToHexIterator(char* begin, char* end) :it_{ begin }, end_{ end }, current_{}{
while (!isHex(*it_) && it_ != end_){ ++it_; }; //make sure we are pointing to valid stuff
++(*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倍。下面是一个在GCC上运行的实例http://ideone.com/nuwu15,根据运行和哪个测试先进行(可能是因为一些缓存效果),它的运行速度在10倍到3倍之间。
总而言之,毫无疑问还有更多的优化空间等,任何在这个抽象层次上说"我的总是更快"的人都是在骗人。
更新:使用编译时生成的查找表进一步提高速度:http://ideone.com/ady8GY(注意,我增加了输入字符串的大小以减少噪音,因此这不能直接与上面的示例相比较)
- 从不同线程使用int64的不同字节安全吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 在UNIX系统中使用DIR查找文件的字节大小
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- C++将向量的向量拆分为向量的N个子向量
- std::当在256字节边界上写入整数时,流的奇怪行为
- 当比特(而不是字节)的顺序至关重要时的持久性
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 如何拆分文件中.txt字母并使用c ++使用数组进行扑克?
- 字节到位运算符重载C++
- 如何将输入值拆分为4位矢量,就像将n位拆分为每部分矢量的半字节一样
- C++字符串数组在 20 字节后拆分
- 如何通过读取C++中的文件来拆分字节数组
- 如何从子进程以 4096 字节拆分管道
- 将单词拆分为两个字节的最快方法
- 在c++中将字节串拆分为字节向量
- 在nodejs中按字节拆分对象
- 快速拆分.或者如何使文件系统将字节数组识别为文件