简体   繁体   English

转换矢量 <char> 到具有转换的字符串

[英]Convert a vector<char> to a string with a conversion

I'd like to convert a vector<char> to a std::string and do a conversion one the way. 我想将vector<char>转换为std::string并进行转换。

I'm almost there, but the result of the code below is a vector<string> , while I'd like to have one string (a concatenation of all the string parts in the vector). 我差不多了,但是下面代码的结果是vector<string> ,而我想要一个字符串(矢量中所有字符串部分的串联)。

See my code example for details. 有关详情,请参阅我的代码示例

string ConvertHexToAscii(const char input)
{
    std::ostringstream oss;
    oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
    return oss.str();
}

vector<char> readBuffer; // this is my input

readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);

vector<string> resultVec;

std::transform(readBuffer.begin(), readBuffer.end()
    , back_inserter(resultVec)
    , ConvertHexToAscii);

// resultVec[0] = "1C";
// resultVec[1] = "09";

The result I need is a string containing "1C09". 我需要的结果是一个包含“1C09”的字符串。 How to achieve that with std::transform ? 如何用std::transform实现呢?

You were almost there; 你快到 ; this works: 这工作:

std::stringstream sstr;
std::transform(
    input.begin(), input.end(),
    std::ostream_iterator<std::string>(sstr, ""),
    ConvertHexToAscii);

But unfortunately this instantiates quite a lot of string streams, which is inefficient. 但不幸的是,这会实例化很多字符串流,效率很低。 Ideally, the ConvertHexToAscii (misnamed, by the way! C++ doesn't know about encodings) function would directly use the underlying stream. 理想情况下, ConvertHexToAscii (错误命名,顺便说一下!C ++不知道编码)函数会直接使用底层流。

#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <numeric>

std::string ConvertHexToAscii(std::string acc, char input)
{
  std::ostringstream oss;
  oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
  return acc + oss.str();
}


int main() {
  std::vector<char> readBuffer; // this is my input
  readBuffer.push_back(0x1c);
  readBuffer.push_back(0x09);

  std::cout << std::accumulate(readBuffer.begin(), readBuffer.end()
          , std::string(), ConvertHexToAscii) << std::endl;

  return 0;
}

create your own back_insert_iterator (look at the code in your stl lib, it's fairly simple) for string types of which operator = is defined as 创建自己的back_insert_iterator(查看stl lib中的代码,这很简单)对于字符串类型,其中operator =定义为

template< class string_type, class value_type >
class back_insert_iterator
{
public:
  back_insert_iterator< _string_type >& operator = ( const value_type& val )
  {
    container->append( val )
    return *this;
  }
};

You can do this with a function output iterator: 您可以使用函数输出迭代器执行此操作:

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <boost/function_output_iterator.hpp>

std::string ConvertHexToAscii(const char input)
{
    std::ostringstream oss;
    oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
    return oss.str();
}

int main() {
    std::vector<char> readBuffer; // this is my input

    readBuffer.push_back(0x1c);
    readBuffer.push_back(0x09);

    std::string temp;

    std::transform(readBuffer.begin(), readBuffer.end()
    , boost::make_function_output_iterator([&temp](const std::string& r) {temp.append(r);})
    , ConvertHexToAscii);


    std::cout << temp << std::endl;
}

I used a lambda to call the append() function on the result string, but if you don't have that available it's fairly easy to use boost::bind or just write an old fashioned functor to do that for you. 我使用lambda来调用结果字符串上的append()函数,但是如果你没有那个可用,那么使用boost::bind或者只是编写一个老式的仿函数来为你做这件事就相当容易了。

With boost::bind the function output iterator gets created as: 使用boost::bind ,函数输出迭代器被创建为:

boost::make_function_output_iterator(boost::bind(static_cast<std::string& (std::string::*)(const std::string&)>(&std::string::append), &temp, _1))

instead. 代替。 It's slightly clunky because you need to pick the right overload for std::string::append . 它有点笨重,因为你需要为std::string::append选择正确的重载。

Whereas perreal's idea of using an accumulation isn't that bad, it may be more performant to operate on the stream directly instead of creating so many temporary strings (though move semantics may help with that): 虽然Perreal使用累积的想法并不是那么糟糕,但直接在流上操作而不是创建如此多的临时字符串可能更有效(尽管移动语义可能对此有所帮助):

std::ostringstream os;
std::string temp = std::accumulate(
                       readBuffer.begin(), readBuffer.end(), std::ref(os), 
                       [](std::ostream &os, const char input) 
                       -> std::reference_wrapper<std::ostream> {
                           return os << std::hex << std::setw(2) 
                                     << std::setfill('0') 
                                     << static_cast<int>(input);
                       }).str();

EDIT: But Ok, that's maybe a bit oversophistication here, a simple foreach would have done, too (even if not as semantically clean as an accumulation): 编辑:但是好吧,这可能有点过于复杂,一个简单的foreach也会做(即使不像积累那样语义清晰):

std::ostringstream os;
std::for_each(readBuffer.begin(), readBuffer.end(), 
              [&os](const char input) mutable {
                  os << std::hex << std::setw(2) << std::setfill('0') 
                     << static_cast<int>(input);
              });
std::string temp = os.str();

But anything might be better than creating a whole bunch of temporary strings. 但是任何事情都可能比创建一大堆临时字符串更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM