开发者

Converting a sequence of bytes to ASCII representation and vice-versa

Suppose we have a vector of uint8_t: { 0x12 0x34 0xab 0xcd }. I've found that I can use ostringstream in order to convert it to a string "1234abcd" (no spaces, no 0x prefixes). But I couldn't simply convert it back with istringstream, apparently since it has no spaces. hex + setw(2) manipulators didn'开发者_如何学运维t help. Are there any easy ways to convert such strings to corresponding byte sequences (other than writing my own parser, at least)? Introducing spaces and other delimiters in the ASCII string is not possible.


You can create a proxy object that reads precisely two characters from your istringstream

struct U8 {
  unsigned int datum;
  friend std::istream& operator>>(std::istream&is, U8& u) {
    char s[3] = "xx";
    if(!((is>>s[0]) && (is>>s[1]) && (std::istringstream(s) >> std::hex >> u.datum)))
      is.setstate(std::ios::badbit);
    return is;
  }
  operator unsigned int() const { return datum; }
};

You would use it thus:

U8 nextByte;
iss >> nextByte;
std::cout << nextByte;
uint8_t ch = nextByte;

A complete program follows:

#include <sstream>
#include <iomanip>
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cassert>

typedef std::vector<unsigned char> V;

std::string Stringify(const V& v) {

  std::ostringstream oss;

  oss << std::hex;
  for(V::const_iterator it = v.begin(); it != v.end(); ++it) {
    oss << std::hex << (unsigned int)*it;
  }
  return oss.str();
}


struct U8 {
  unsigned int datum;
  friend std::istream& operator>>(std::istream&is, U8& u) {
    char s[3] = "xx";
    if(!((is>>s[0]) && (is>>s[1]) && (std::istringstream(s) >> std::hex >> u.datum)))
      is.setstate(std::ios::badbit);
    return is;
  }
  operator unsigned int() const { return datum; }
};

const V UnStringify(const std::string& str) {
  V v;
  std::istringstream iss(str);

  std::copy(std::istream_iterator<U8>(iss),
            std::istream_iterator<U8>(),
            std::back_inserter(v));

  return v;
}


int main() {
  V v;
  v.push_back(0x12);
  v.push_back(0x34);
  v.push_back(0xab);
  v.push_back(0xcd);

  std::cout << Stringify(v) << "\n";
  assert(v == UnStringify("1234abcd"));
}


you can feed your istringstream by pair of characters in a cycle. i am sure ) use .str()


Not the best way, I believe, but still:

void BytesToString(unsigned char* bt, char* str)
{
 int len = sizeof(bt);

 for (int i = 0; i < len; i++)
 {
  sprintf(str + i*2, "%2.2x", bt[i]);
 }
}

void StringToBytes(char* str, unsigned char* bt)
{
 unsigned int sz = strlen(str);
 if ((sz % 2) == 1)
 {
  //was too lazy to prepend 0 to the string or write a separate case for that one, whatever

  puts("Bad input #1");
 }

 memset(bt, 0, sz/2);

 unsigned char temp = 0;
 for (unsigned int step = 0; step < sz; step++)
 {
  if (str[step] >= 0x30 && str[step] <= 0x39) {temp = (unsigned char)str[step] - 0x30;}
  else
   if (str[step] >= 0x61 && str[step] <= 0x7A) {temp = (unsigned char)str[step] - 0x57;}
        else {/* Is not an ASCII HEX string (illegal character) */   puts("Bad input #2");}

  bt[(step - step % 2) / 2] += temp*(0x01 + 0x0F*(!(step % 2)));
 }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜