2012-06-28 5 views
6

Me gustaría convertir un vector<char> en un std::string y hacer una conversión en el camino.Convierta un vector <char> en una cadena con una conversión

Estoy casi allí, pero el resultado del código siguiente es vector<string>, mientras que me gustaría tener una cadena (una concatenación de todas las partes de la cadena en el vector).

Vea el ejemplo de mi código para más detalles.

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"; 

El resultado lo que necesito es una cadena que contiene "1C09". ¿Cómo lograr eso con std::transform?

Respuesta

4

Usted era casi allí; esto funciona:

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

Pero desafortunadamente esto crea un montón de secuencias de cadenas, lo que es ineficiente. Idealmente, la función ConvertHexToAscii (mal llamada, por cierto! C++ no sabe sobre codificaciones) usaría directamente la secuencia subyacente.

+0

Me gusta esto - mucho más simple que jugar con iteradores de salida de función. – Flexo

1

crear su propia back_insert_iterator (mira el código en su lib STL, es bastante simple) para este tipo de cuerda de los cuales el operador = se define como

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

Usted puede hacer esto con un iterador de salida de la función:

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

he usado un lambda para llamar a la función append() en la cadena de resultado, pero si usted no tiene la disponible es bastante fácil de usar boost::bind o simplemente escribir una antigua usanza funtor a hacer eso por usted.

Con boost::bind el iterador salida de la función se crea como:

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

lugar. Es un poco torpe porque necesita elegir la sobrecarga correcta para std::string::append.

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 ¡Esta es una solución muy buena! Nunca hubiera pensado usar 'std :: accumulate' aquí. Si bien esto no responde exactamente mi pregunta, resuelve mi problema de una manera muy clara. – nabulke

0

Mientras que la idea de Perreal de utilizar una acumulación no es tan malo, puede ser con más prestaciones para funcionar con la corriente directa en lugar de crear tantas cadenas temporales (aunque se mueven semántica puede ayudar con eso):

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: Pero Ok, eso es tal vez un poco aquí sofisticación excesiva, un foreach sencilla habría hecho, también (aunque no tan limpio como semánticamente una acumulación):

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

Pero cualquier cosa podría ser mejor que crear un conjunto completo de cadenas temporales.

Cuestiones relacionadas