2011-09-05 76 views
2

基本上我有一個功能,大致看起來像這樣,我需要退出。從函數返回動態C風格的字符串?

const char* UTF16ToUTF8(const wchar_t *in) { 
    int tmp = wcslen(in); 
    int size_needed = WideCharToMultiByte(CP_UTF8, 0, &in[0], (size_t)tmp, NULL, 0, NULL, NULL); 
    std::vector<char> out; 
    out.resize(size_needed); 
    WideCharToMultiByte(CP_UTF8, 0, &in[0], (size_t)tmp, &out[0], size_needed, NULL, NULL); 

    return &out[0]; 
} 

顯然在返回時得到解除引用。我有什麼選擇?我需要能夠像這樣調用這個函數。我絕對會喜歡留在棧上。

utf8outputfile << UTF16ToUTF8(wchar_tString) << endl; 
fprintf(utf8outputfile, "%s", UTF16ToUTF8(L"Mmm Mmm Unicode String κόσμε")); 
return UTF16ToUTF8(wchar_tString); 
+0

我不知道你可以用'std :: vecor'來做到這一點。是否將'&out [0]'傳遞給'WideCharToMultiByte'以多字節安全?好形式? – Sodved

+0

@Sodved no - 它會爆炸,因爲當函數返回時矢量將被破壞(並且釋放後備分配)。因此,這個函數的結果永遠不會指向有效的分配。如果向量要超過函數,那麼你當然可以使用char向量來表示一個字符串(儘管在大多數情況下std :: string更合適)。 – justin

+1

@Sodved然而,矢量確保連續分配。把'&vec [0]'當作一個c數組是很好的。 – justin

回答

6

不與任何這樣的擔心給自己煩惱,並返回一個std::string

std::string UTF16ToUTF8(const wchar_t *in) { 
    std::vector<char> out; 
    //... 
    return std::string(out.begin(), out.end()); // or std::string(out.data()) 
} 

然後,在你的C接口,使用:

printf("%s", UTF16ToUTF8(ws).c_str()); 

我甚至會使其論點的功能std::wstring,並僅在調用API函數時才提取C字符串。

begin/end版本包括全部個字符,.data()版本將緩衝區視爲以空字符結尾的字符串。選擇最合適的一個。

2

返回std :: string將是我的第一選擇。

但是,如果你絕對肯定需要一個char *,你有幾個選項。

你可以在堆上分配一個新的char *和返回,是真的,真的仔細以確保來電總是將釋放內存。我相信有一個提升auto_ptr相當於陣列友好的,可以明確所有權轉移。

另一個選項是調用者傳入char *(和最大大小)以及將數據放入其中的函數。因此,調用者總是擁有內存。

另一個選項是調用者傳入char **(或char * &),並且函數將內存分配給調用者的指針。這使得所有權轉移顯式化。 (如果調用者可能需要的話,你也可以有一個size(size_t &)參數來保存這個大小)。

+0

我可能會去用std :: string。 儘管char *&thing很有趣。它可以在堆棧上分配嗎?如果我可以通過一次調用函數在堆棧上完成所有操作,我不會介意必須丟棄返回值。 – Riley