簡體   English   中英

轉換向量<string>進入 char** C++

[英]convert vector<string> into char** C++

我有一個vector<std::string>變量。 我需要將它傳遞給一個接受char**作為輸入參數的方法。

這該怎么做 ? 如果可能,我需要通過一個可寫的。

更新 1:在用於創建服務方法的工具中,我將參數指定為 std::vector,但它自動將限定符設置為 &,這意味着該工具生成的我的方法定義將如下所示:

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

}

使用傳遞的參數表中的值自動調用此方法。 現在,從這個方法內部,我將在 lib 文件夾中的 dll 中調用一個方法,如下所示:

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

對於 par1 --> 我正在傳遞 (char*)par1.c_str()

我需要知道如何為 par2 和 par3 以及 pRetValue 傳遞變量。 par2 和 par3 的值在向量中可用,但最后一個參數 pRetValue 是一個輸出參數,我需要將它作為 std::string 返回。

對不起,如果我很困惑或問非常基本的問題。

只要函數不修改傳入的char** ,就可以在不復制所有std::strings情況下解決問題。 否則我別無選擇,只能將所有內容復制到新的 char**` 結構中(參見第二個示例)

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

示例 2:如果函數必須修改傳入的數據:

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

int main()
{
    {
        // pre C++11
        std::vector<std::string> strings {"one", "two", "three"};

        // guarantee contiguous, null terminated strings
        std::vector<std::vector<char>> vstrings;

        // pointers to rhose strings
        std::vector<char*> cstrings;

        vstrings.reserve(strings.size());
        cstrings.reserve(strings.size());

        for(size_t i = 0; i < strings.size(); ++i)
        {
            vstrings.emplace_back(strings[i].begin(), strings[i].end());
            vstrings.back().push_back('\0');
            cstrings.push_back(vstrings.back().data());
        }

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

    {
        // post C++11
        std::vector<std::string> strings {"one", "two", "three"};

        std::vector<char*> cstrings;   
        cstrings.reserve(strings.size());

        for(auto& s: strings)
            cstrings.push_back(&s[0]);

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

注意:已修改以提供更好的代碼。

Galik 的回答有許多安全問題。 這是我在現代 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;
    }
}

沒有凌亂的內存管理或討厭的const_cast s。

住在 Coliru。

輸出:

modifiable version
one
two
three


non-modifiable version
four
five
six

此問題評分最高的答案希望您傳入帶有 char** 參數的大小。 但是在 method_to_be_called() 中,無法傳遞 par2 和 par3 的大小,因此這些 c 樣式字符串列表可能期望以 null 結尾。 換句話說,字符串列表 (char **) 中的最后一個字符串 (char*) 需要是空指針。 這是許多 c 庫中的常見范例。

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

解決此問題的最方便的方法可能是采用更 c 風格的答案。

//directly create char** par2
std::vector<std::string> par2Vect{"one", "two", "three"};
char ** par2 = (char**) malloc( sizeof(char*)*(par2Vect.size() + 1) );
for(size_t i = 0; i < par2Vect.size(); ++i)
{
    par2[i] = strdup(par2Vect[i].c_str());
}
// set the last entry to null to signify the end of the list
par2[par2Vect.size()] = nullptr;

// call your library
method_to_be_called(..., par2,...);

// delete par2
for(size_t i = 0; i < par2Vect.size(); ++i)
{
    // free memory for each c-style string
    free(par2[i]);
}
// free memory for outer char* array 
free(par2);

我相信這相當容易,並且可以在沒有太多復雜性的情況下完成。

std::vector<std::string> vector = {"a", "std::vector", "of", "std::string"};
// Result char**.
char** result = new char*[vector.size()];
for (int index = 0; index < vector.size(); index++) {
    result[index] = const_cast<char*>(vector[index].c_str());
}
// Use the result.
delete[] result;
// Deallocate the memory from heap after usage.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM