如何将tr1/array转换为std::string?

4

我想知道如何将std::tr1::array<unsigned char, 16>转换为std::string

编译器总是报错,我已经尝试过以下方法:

std::tr1::array<unsigned char, 16> sss;
string(sss);
string asd(sss);

无论哪种方式,都可以使它正常工作...

2个回答

5

unsigned char使得这个问题变得棘手。如果你知道你的系统使用2s补码1字节8位unsigned charchar,并且从unsigned charchar的隐式转换符合你的要求(这些并不总是正确的!),并且你的数组缓冲区以null结尾(即第一个0之后的字符应该被丢弃),那么这个函数就可以工作:

template<std::size_t N>
std::string to_string( std::array<unsigned char, N> const& arr ) {
  std::string retval;
  for( auto c : arr ) {
    if (!c)
      return retval;
    retval.push_back(c);
  }
  return retval;
}

我在这里加入了一些关于数组可能会“满”并且缺少空终止符的偏执症。

如果您实际上想要所有16个unsigned char,即使其中一些是null,您需要使用以下代码:

std::string str( arr.begin(), arr.end() );

应该使用从 unsigned charchar 的隐式转换。

如果隐式转换不能达到您想要的效果,并且您知道 array 的存储器实际上是一个 char 数组,即使它的类型是 unsigned char,您需要进行一些重新解释转换。

对于以空值结尾的情况:

template<std::size_t N>
std::string to_string_helper( const char* buf ) {
  std::string retval; 
  if (!buf)
    return retval;
  for ( const char* it = buf; it < (buf+N); ++it ) {
    if (!*it)
      return retval;
    retval.push_back(*it);
  }
  return retval;
}
template<std::size_t N>
std::string to_string_2( std::array<unsigned char, N> const& arr ) {
  return to_string_helper<N>( arr.data() );
}

并且对于“整个缓冲区”的情况:
template<std::size_t N>
std::string to_string_2( std::array<unsigned char, N> const& arr ) {
  const char* str = reinterpret_cast<const char*>(arr.data());
  return std::string( str, str+N );
}

第二个选项比较好,但如果“sss”是一个“unsigned char”数组,则第一个选项无法编译。 - Andy Prowl
@AndyProwl 没有注意到 unsigned。已经澄清了。我认为我理解了未定义行为的部分,但不确定。 - Yakk - Adam Nevraumont
@PeteBecker:没错,你指出了一个好的观点。我明确提到了“unsigned char”,因为那是OP所使用的。 - Andy Prowl
@weeo 关于内存使用的顾虑与charunsigned char有什么关系? - Yakk - Adam Nevraumont
@Yakk 我需要尽可能地使用有限的内存来存储这种类型的数组。所以,如果我从 char 改为 unsigned char,它应该可以将内存减少一半吗? - weeo
显示剩余4条评论

2

只是为了明确,你知道这个转换是一种复制转换,对吧?

// if you want the whole fixed-size string including any nul characters
template <std::size_t N>
std::string fixed_array_to_string(std::tr1::array<unsigned char, N> const &array)
{
    return std::string(reinterpret_cast<const char *>(&*array.begin()), N);
}

// if your array is nul-terminated
template <std::size_t N>
std::string nul_array_to_string(std::tr1::array<unsigned char, N> const &array)
{
    return std::string(reinterpret_cast<const char *>(&*array.begin()));
}

&* 这个东西很丑,可以用 &array.front() 代替。

如果你确定将其解释为 char 是有意义的,那么你可以将其推广到任何类型的数组:

// if you want the whole fixed-size string including any nul characters
template <typename T, std::size_t N>
std::string fixed_array_to_string(std::tr1::array<T, N> const &array)
{
    return std::string(reinterpret_cast<const char *>(&*array.begin()),
                       N * sizeof(T));
}

解除引用“end”迭代器是否合法?我认为std :: string的(begin,end)ctor会复制空字节? - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接