2014-09-25 14 views
12

Tôi có biến số vector<std::string>. Tôi cần phải chuyển nó vào một phương thức chấp nhận char** làm tham số đầu vào.chuyển đổi vector <string> thành char ** C++

cách thực hiện việc này? Nếu có thể, tôi cần phải vượt qua bài có thể ghi được.

Cập nhật 1: Trong một công cụ để tạo ra một phương pháp dịch vụ, cung cấp cho tôi thông số như std :: vector, nhưng nó đặt tự động các vòng loại như &, có nghĩa là định nghĩa phương pháp của tôi được tạo ra bởi công cụ này sẽ trông như sau:

std::string SvcImpl::myMethodname (const std::string par1, const std::vector<  std::string >& par2, const std::vector<std::string>& par3) 
{ 

} 

Phương pháp này được gọi tự động với các giá trị trong thông số được thông qua. Bây giờ từ bên trong phương pháp này tôi sẽ gọi một phương thức trong một dll trong một thư mục lib đó trông giống như:

int method_to_be_called(char* par1, char ** par2, char ** par3, void* pRetValue); 

cho par1 -> Tôi đang đi qua (char *) par1.c_str()

Tôi cần biết cách chuyển các biến cho par2 và par3 và cho pRetValue. giá trị cho par2 và par3 có sẵn trong vectơ nhưng tham số pRetValue cuối cùng là tham số đầu ra mà tôi cần trả về nó dưới dạng std :: string.

xin lỗi nếu tôi rất bối rối hoặc đặt câu hỏi rất cơ bản.

+1

sau đó hoạt động của bạn nên được trên '* writable', giả ** ghi được chấp nhận char của bạn ** param. –

+1

Tôi nghĩ rằng bạn sẽ cần phải tạo ra một 'std :: vector ' để lưu trữ địa chỉ của tất cả dữ liệu chuỗi của bạn. – Galik

+0

Chính xác thì phương pháp này bạn đang truyền đạt để làm gì? – Wlerin

Trả lời

18

Có thể giải quyết sự cố mà không cần sao chép tất cả các std::strings miễn là chức năng không sửa đổi đã được chuyển vào char**. Nếu không, tôi có thể thấy không có cách nào khác ngoài việc sao chép mọi thứ vào một ký tự char mới ** ** (xem ví dụ thứ hai).

void old_func(char** carray, size_t size) 
{ 
    for(size_t i = 0; i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

int main() 
{ 
    std::vector<std::string> strings {"one", "two", "three"}; 
    std::vector<char*> cstrings; 
    cstrings.reserve(strings.size()); 

    for(size_t i = 0; i < strings.size(); ++i) 
     cstrings.push_back(const_cast<char*>(strings[i].c_str())); 

    // Do not change any of the strings here as that will 
    // invalidate the new data structure that relies on 
    // the returned values from `c_str()` 
    // 
    // This is not an issue after C++11 as long as you don't 
    // increase the length of a string (as that may cause reallocation) 

    if(!cstrings.empty()) 
     old_func(&cstrings[0], cstrings.size()); 
} 

VÍ DỤ 2: Nếu chức năng phải thay đổi thông qua trong dữ liệu:

void old_func(char** carray, size_t size) 
{ 
    for(size_t i = 0; i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

int main() 
{ 
    std::vector<std::string> strings { "one", "two", "three"}; 
    char** cstrings = new char*[strings.size()]; 

    for(size_t i = 0; i < strings.size(); ++i) 
    { 
     cstrings[i] = new char[strings[i].size() + 1]; 
     std::strcpy(cstrings[i], strings[i].c_str()); 
    } 

    // Now the function can do what it likes (within the bounds) 
    // with the passed in structure 

    old_func(cstrings, strings.size()); 

    // clean up memory 

    for(size_t i = 0; i < strings.size(); ++i) 
     delete[] cstrings[i]; 

    delete[] cstrings; 
} 

EDIT5: giải quyết trên một giải pháp đơn giản cho bài C++ 98 mã (thnx để BeyelerStudios) đã thêm một giải pháp cho phép chức năng sửa đổi dữ liệu được truyền.

+0

Tốt, mặc dù trong phiên bản thứ hai tôi sẽ sử dụng một vector hoặc ít nhất một unique_ptr để giữ mảng con trỏ, và một số loại scope_exit cơ sở để xóa các con trỏ bên trong. Nếu bất kỳ phân bổ chuỗi riêng lẻ nào không thành công, tất cả các phân bổ chuỗi trước đó cộng với mảng con trỏ sẽ bị rò rỉ. –

+0

trong nhận xét về mã của bạn, bạn đã viết rằng "đây không phải là vấn đề sau C++ 11". bạn có thể giải thích tại sao không? – bernie

+1

@lefenzy Tôi đã chỉnh sửa nhận xét vì nó không hoàn toàn chính xác. Nhưng trước khi 'C++ 11' không đảm bảo rằng con trỏ được trả về bởi' c_str() 'trỏ tới dữ liệu thực của chuỗi (nó có thể là một bộ đệm tạm thời). Sau khi 'C++ 11' nó được bảo đảm để trỏ đến chuỗi dữ liệu thực tế. Nó chỉ bị vô hiệu nếu bạn tăng * độ dài của chuỗi. – Galik

7

Câu trả lời của Galik có một số vấn đề về an toàn. Đây là cách tôi sẽ làm điều đó trong Modern C++:

#include <iostream> 
#include <string> 
#include <vector> 

void old_func(char** carray, std::size_t size) 
{ 
    for(std::size_t i(0); i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

void other_old_func(const char** carray, std::size_t size) 
{ 
    for(std::size_t i(0); i < size; ++i) 
     std::cout << carray[i] << '\n'; 
} 

int main() 
{ 
    { 
     std::cout << "modifiable version\n"; 
     std::vector<std::string> strings{"one", "two", "three"}; 
     std::vector<char*> cstrings{}; 

     for(auto& string : strings) 
      cstrings.push_back(&string.front()); 

     old_func(cstrings.data(), cstrings.size()); 

     std::cout << "\n\n"; 
    } 
    { 
     std::cout << "non-modifiable version\n"; 
     std::vector<std::string> strings{"four", "five", "six"}; 
     std::vector<const char*> cstrings{}; 

     for(const auto& string : strings) 
      cstrings.push_back(string.c_str()); 

     other_old_func(cstrings.data(), cstrings.size()); 
     std::cout << std::endl; 
    } 
} 

Không quản lý bộ nhớ lộn xộn hoặc khó chịu const_cast s.

Live on Coliru.

Đầu ra:

modifiable version 
one 
two 
three 


non-modifiable version 
four 
five 
six 
Các vấn đề liên quan