2012-06-28 20 views
6

vector<char> bir std::string dönüştürmek ve bir dönüşüm bir şekilde yapmak istiyorum.Bir dönüşüme <char> dönüştürmek

Neredeyse oradayım, ancak aşağıdaki kodun sonucu bir vector<string> iken, bir dizgiye sahip olmak istiyorum (vektördeki tüm dizge parçalarının birleşimiyle).

Ayrıntılar için kod örneğime bakın.

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

ihtiyacım sonuç "1C09" içeren bir dizedir. Bunu std::transform ile nasıl başarabilirim?

cevap

4

neredeyse vardı;

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

Ama ne yazık ki bu verimsizdir dize akışların, oldukça fazla başlatır: Bu çalışır. İdeal olarak, ConvertHexToAscii (yanlış adlandırarak, bu arada! C++ kodlamalar hakkında bilinmez) işlevi doğrudan temel akışı kullanır.

+0

Bunu beğendim - işlev çıkışı yineleyicileriyle uğraşmaktan çok daha basit. – Flexo

1

Kendi back_insert_iterator oluşturmak dize türleri için (sizin stl lib koduna bakmak, oldukça basit) hangi operatör ait = Bir fonksiyon çıkış Yineleyici ile yapabilirsiniz

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

olarak tanımlanır:

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

sonucun dizesi append() işlevi çağırmak için bir lambda kullanılan, ama o mevcut yoksa o boost::bind kullanabilir veya sadece sizin için bunu bir eski moda functor yazmak için oldukça kolaydır. yerine

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

:

boost::bind ile fonksiyon çıkış yineleyici olarak oluşturulan. Biraz tıkalı çünkü std::string::append için doğru aşırı yükü seçmeniz gerekiyor. Bir birikimini kullanarak Perreal fikri kötü değil Oysa

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 Bu bir _very_ güzel çözüm! Asla 'std :: accumulate' kullanmayı düşünmemiştim. Bu tam olarak soruma cevap vermezken, sorunumu çok düzgün bir şekilde çözüyor. – nabulke

0

, (hareket semantik bu konuda yardımcı olabilir) bu kadar çok geçici dizeleri oluşturmak yerine doğrudan akışında çalışmasına daha fazla ölçülebilir olabilir:

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

DÜZENLEME: Ama Tamam, bu basit bir foreach (bir birikimi olarak bile sanki semantik temiz değil) da yapardı, burada belki biraz oversophistication var:

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

Ancak, her şey bir dizi geçici dizge oluşturmaktan daha iyi olabilir.

İlgili konular