2012-06-28 2 views
6

Ich möchte eine vector<char> in eine std::string konvertieren und eine Umwandlung eine Art und Weise tun.Konvertieren Sie einen Vektor <char> in eine Zeichenfolge mit einer Konvertierung

Ich bin fast da, aber das Ergebnis des folgenden Codes ist ein vector<string>, während ich gerne eine Zeichenfolge (eine Verkettung aller Zeichenfolge Teile im Vektor) haben würde.

Siehe mein Codebeispiel für 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"; 

Das Ergebnis ich brauche, ist eine Zeichenfolge, die "1C09". Wie erreiche ich das mit std::transform?

Antwort

4

Sie waren fast dort; das funktioniert:

Aber leider instanziiert dies eine ganze Reihe von String-Streams, was ineffizient ist. Idealerweise würde die Funktion ConvertHexToAscii (die übrigens auch C++ nicht über Encodings kennt) direkt den zugrunde liegenden Stream verwenden.

+0

Ich mag das - viel einfacher als mit Funktionsausgabe Iteratoren herumzualbern. – Flexo

1

Ihre eigenen back_insert_iterator erstellen (siehe den Code in Ihrer stl lib, es ist ziemlich einfach) für String-Typen, von denen Operator = ist definiert als

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; 
    } 
}; 
1

Sie diese mit einem Funktion Output-Iterator tun können:

#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; 
} 

benutzen ich eine Lambda die append() Funktion auf dem Ergebnis-String zu nennen, aber wenn Sie es nicht, dass die zur Verfügung haben ziemlich einfach boost::bind verwenden oder einfach nur einen altmodischen Funktors schreiben, dass für Sie zu tun.

Mit boost::bind die Funktion Output-Iterator wird wie geschaffen:

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

statt. Es ist leicht klobig, weil Sie die richtige Überladung für std::string::append auswählen müssen.

2
#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; 
} 
+0

+1 Dies ist eine sehr nette Lösung! Ich hätte nie gedacht, hier 'std :: accumum' zu verwenden. Obwohl dies meine Frage nicht genau beantwortet, löst es mein Problem auf sehr nette Weise. – nabulke

0

Während Perreal Idee eine Anhäufung der Verwendung nicht so schlecht ist, kann es mehr performant sein auf dem Strom zu betreiben, sondern direkt so viele temporäre Strings schaffen (obwohl bewegen Semantik dabei helfen kann):

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: Aber Ok, das ist vielleicht ein bisschen oversophistication hier eine einfache foreach auch getan hätte (wenn auch nicht als semantisch sauber als eine Ansammlung):

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(); 

Aber alles könnte besser sein, als eine ganze Reihe temporärer Strings zu erzeugen.

Verwandte Themen