2012-06-28 29 views
6

Tôi muốn chuyển đổi một vector<char> thành std::string và thực hiện chuyển đổi theo cách.Chuyển đổi một vector <char> thành chuỗi có chuyển đổi

Tôi sắp sửa ở đó, nhưng kết quả của mã bên dưới là vector<string>, trong khi tôi muốn có một chuỗi (một phần của tất cả các phần chuỗi trong vectơ).

Xem ví dụ về mã của tôi để biết chi tiết.

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

Kết quả tôi cần là một chuỗi chứa "1C09". Làm thế nào để đạt được điều đó với std::transform?

Trả lời

4

Bạn đã gần như ở đó; công trình này:

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

Nhưng không may này instantiates khá nhiều suối chuỗi, đó là không hiệu quả. Lý tưởng nhất, chức năng ConvertHexToAscii (tên không đúng, bằng cách này! C++ không biết về mã hóa) sẽ trực tiếp sử dụng luồng cơ bản.

+0

Tôi thích điều này - đơn giản hơn nhiều so với xung đột với các trình lặp đầu ra chức năng. – Flexo

1

tạo back_insert_iterator riêng của bạn (nhìn vào mã trong lib STL của bạn, nó khá đơn giản) với nhiều loại chuỗi trong đó operator = được định nghĩa là

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

Bạn có thể làm điều này với một iterator đầu ra chức năng:

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

tôi đã sử dụng một lambda để gọi append() chức năng trên chuỗi kết quả, nhưng nếu bạn không có sẵn mà nó khá dễ dàng để sử dụng boost::bind hoặc chỉ viết một functor lỗi thời cũ để làm điều đó cho bạn.

Với boost::bind chức năng đầu ra iterator được tạo ra như:

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

để thay thế. Hơi lộn xộn vì bạn cần chọn đúng tình trạng quá tải cho 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 Đây là một giải pháp tốt đẹp _very_! Tôi sẽ không bao giờ nghĩ đến việc sử dụng 'std :: accumulate' ở đây. Trong khi điều này không chính xác trả lời câu hỏi của tôi, nó giải quyết vấn đề của tôi một cách rất gọn gàng. – nabulke

0

Trong khi ý tưởng perreal của của việc sử dụng một sự tích lũy không phải là xấu, nó có thể là performant hơn để hoạt động trên dòng trực tiếp thay vì tạo rất nhiều chuỗi tạm thời (mặc dù ngữ nghĩa di chuyển có thể giúp với điều đó):

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: Nhưng Ok, đó là có thể là một chút oversophistication đây, một foreach đơn giản đã có thể làm, quá (thậm chí nếu không muốn nói là ngữ nghĩa trong sạch như một sự tích lũy):

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

Nhưng bất cứ điều gì có thể tốt hơn là tạo ra toàn bộ chuỗi các chuỗi tạm thời.

Các vấn đề liên quan