将二进制字符的字符串表示转换为字符串的最佳方法

时间:2016-05-10 10:07:35

标签: c++ locale

我创建了一个自定义的numpunct类,它允许我创建一个带有用户定义值的自定义numpunct(在我的例子中,千位分隔符,小数分隔符和分组将从xml文档中读取)。 这是我的班级:

class custom_numpunct : public std::numpunct<char>
{
public:
  custom_numpunct(const char decimal_point, const char thousands_sep, const std::string grouping)
    : cDecimalPoint(decimal_point), cThousandsSep(thousands_sep), sGroup(grouping) {}
protected:
  virtual char do_decimal_point() const { return cDecimalPoint; }
  virtual char do_thousands_sep() const { return cThousandsSep; }
  virtual std::string do_grouping() const { return sGroup; }
  const char cDecimalPoint;
  const char cThousandsSep;
  const std::string sGroup;
};

主要问题是分组接受二进制字符进行分组。 因此,如果我直接使用代码中的值,如

std::string grouping = "\1\2\3";

它起作用,因为它们是二进制值。问题是从用户输入读取我将

std::string grouping = "\\1\\2\\3";

(用户插入\ 1 \ 2 \ 3) 所以我需要一些东西来将字符串二进制代表转换为实际字符。 我创建了这个函数

std::string convertToBinary(std::string input)
{
  std::stringstream out;
  std::stringstream ss(input);
  std::string tok;
  int value;

  while (std::getline(ss, tok, '\\')) 
  {
    if (!tok.empty())
    {
      try 
      {
        value = std::stoi(tok);
      }
      catch (const std::invalid_argument& ia) 
      {
        std::cerr << "Invalid argument: " << ia.what() << std::endl;
        continue;
      }
      out << (char)(value & 0xff);
    }
  }
  return out.str();
}

它将字符串拆分为\并尝试使用字符串将单个整数转换为字符,但它可能不可靠(1也是有效的二进制输入)。 有更好的方法可以进行此转换吗?

1 个答案:

答案 0 :(得分:0)

我这样做:

string convertToBinary(const string& in)
{
    string out;
    out.reserve(in.size() / 2);

    for (const char *cur = in.c_str(), *end = cur + in.size(); cur != end; ++cur) {
        if (*cur == '\\') {
            ++cur; // skip first backslash                                                                              
            if (cur == end) {
                break;
            }

            if (isdigit(*cur)) { // found escape sequence                                                               
                char* end;
                unsigned long num = strtol(cur, &end, 10);
                cur = end - 1;
                out.push_back(num);
                continue;
            }
        }

        out.push_back(*cur);
    }

    return out;
}

如果我调用convertToBinary("\\1\\233"),我会得到一个包含两个字节的字符串,即1和233十进制。不会删除任何后跟数字的反斜杠,例如"\\n"变为"n"

可以根据您的典型输入数据调整顶部的reserve()调用。如果您的输入始终充满转义序列,例如"\\1\\10\\100"您可能希望除以3,但如果您的输入可能没有多次转义,则可能只想使用完整的in.size()