簡體   English   中英

如何轉換向量<wstring>到 wchar_t**?

[英]How to convert a vector<wstring> to a wchar_t**?

我需要創建一個與 C 兼容的(友好的)返回類型,以便我的 C++ 函數可以用於基於 C 的函數。

如何將wstring向量轉換為wchar_t**數組?

您可以遍歷 wstring 向量並將每個wstring::c_str()wchart_t**數組。

如果可能的話,最好完全避免這樣做。

如果你真的別無選擇,你基本上會做一些事情,比如分配一個指針數組,然后為每個字符串分配空間,並將輸入中的每個單獨的字符串復制到你分配的緩沖區中。

wchar_t *dupe_string(std::wstring const &input) { 
    wchar_t *ret = new wchar_t[input.size()+1];
    wcscpy(ret, input.c_str());
    return ret;
}

wchar_t **ruin(std::vector<std::wstring> const &input) {
    wchar_t **trash = new wchar_t*[input.size()];
    for (int i=0; i<input.size(); i++)
       trash[i] = dupe_string(input[i]);
    return trash;
}

然而,根據評論,我對這適用於當前情況有一些疑慮——這假設輸入是寬字符串,這通常意味着 UTF-16 或 UTF-32/UCS-4。 如果輸入真的是 UTF-8 的形式,那么你處理的存儲元素真的是char ,而不是wchar_t ,所以你的輸入應該是窄字符串( std::string )和匹配的輸出char **而不是wchar_t **

wstring 是 basic_string 的模板化實例,因此其 c_str() 函數返回 wchar_t*。

所以,你可以做類似的事情

std::vector<const wchar_t*> pointers;
pointers.reserve(wstrVec.size());
for (auto it = wstrVec.begin(); it != wstrVec.end(); ++it) {
    pointers.push_back(it->c_str());
}

const whcar_t** cptr = pointers.data();

沒有更多的上下文,很難建議處理范圍/生命周期問題的最佳方法。 您是在編寫庫(這表明您無法控制范圍)還是為您正在監督的 C 代碼的回調提供 API?

一種常見的方法是提供一個 sizing api,以便調用者可以提供適當大小的目標緩沖區:

size_t howManyWstrings()
{
    return wstrVec.size();
}

bool getWstrings(const wchar_t** into, size_t intoSize /*in pointers*/)
{
    const size_t vecSize = wstrVec.size();
    if (intoSize < vecSize || into == nullptr)
        return false;
    for (size_t i = 0; i < vecSize; ++i) {
        into[i] = wstrVec[i].c_str();
    }
    return true;
}

聽起來你的 C 函數需要一個指向wchar_t緩沖區的指針,並且能夠移動這個指針。

嗯,這很容易,盡管您必須管理指針的生命周期。 為此,我建議不要將此作為返回類型(從而讓 C 破壞您的 API,更不用說您的代碼的健全性),而是在 C 函數的調用站點執行此邏輯:

/** A function that produces your vector */
std::vector<wchar_t> foo();

/** The C function in question */
void theCFunction(wchar_t**);

int main()
{
   std::vector<wchar_t> v = foo();
   wchar_t* ptr = &v[0];
   theCFunction(&ptr);
}

順便說一句,從問題和一些評論來看,您似乎誤解了charwchar_t什么——它們位於編碼層下方,如果您有 UTF-8,那么您應該將 UTF-8 字符串的每個字節存儲為單字節。 這意味着使用char s,就像在std::string 當然,該字符串中的每個字節不一定代表單個邏輯 unicode 字符,但這不是重點。

這是將std::wstring向量轉換為基於wchar_t**的字符串的函數。 由於使用了 DisposeBuffer(),它也不會泄漏任何內存; 呼叫不同於其他答案。

wchar_t ** xGramManipulator::GetCConvertedString(vector< wstring> const &input)
{
    DisposeBuffer();  //This is to avoid memory leak for calling this function multiple times
    cStringArraybuffer = new wchar_t*[input.size()]; //cStringArraybuffer is a member variable of type wchar_t**
    for (int i = 0; i < input.size(); i++)
    {
        cStringArraybuffer[i] = new wchar_t[input[i].size()+1];
        wcscpy_s(cStringArraybuffer[i], input[i].size() + 1, input[i].c_str());
        cStringArraySize++;
    }
    return cStringArraybuffer;
}

這是避免內存泄漏的 DisposeBuffer Helper 函數:

void xGramManipulator::DisposeBuffer(void)
{
    for (size_t i = 0; i < cStringArraySize; i++)
    {
        delete [] cStringArraybuffer[i];
    }
    delete [] cStringArraybuffer;
    cStringArraybuffer = nullptr;
    cStringArraySize = 0;
}

在這些之前,在你的構造函數中分配一個虛擬空間:

xGramManipulator::xGramManipulator()
{
    //allocating dummy array so that when we try to de-allocate it in GetCConvertedString(), dont encounter any undefined behavior

    cStringArraybuffer = new wchar_t*[1];
    cStringArraySize = 0;
    for (int i = 0; i < 1; i++)
    {
        cStringArraybuffer[i] = new wchar_t[1 + 1];
        cStringArraySize++;
    }
}

而這一切都完成了。

暫無
暫無

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

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