2010-10-08 87 views
2

如何在保留'\ 0'字符的同時將std :: string轉換爲LPCSTR?將std :: string轉換爲帶有尾部或前導' 0'的LPCSTR

我想使用OPENFILENAME.lpstrFilter上的結果,它要求過濾器包含'\ 0'作爲分隔符。

的std :: string.c_str()似乎會,並提前修剪 '\ 0'

謝謝!

==========================

(如何正確添加到像在回覆帖子的回覆評論?論壇)

閱讀您的意見後,我又仔細檢查這個片段:

std::string filter = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
const char* f1 = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
const char* f2 = filter.c_str(); 
for(int i = 0; i < 50; i++) 
{ 
char c1 = *(f1 + i); // works 
char c2 = *(f2 + i); // doesn't work. beyond the first \0, it's garbage. 
} 

是我錯了就c_str()或LPCSTR是如何工作的?

+0

見http://msdn.microsoft.com/en-us/library/ ms646839%28VS.85%29.aspx:'lpstrFilter:緩衝區中的最後一個字符串必須以兩個空字符結尾。您需要**兩個** NULL字符才能正確使用該參數。 'c_str()'按設計只有一個。 – AshleysBrain 2010-10-08 14:08:26

+0

是的,我知道這個事實。 – Jake 2010-10-08 14:39:42

回答

6

C_STR不會去掉NUL字符。這個錯誤很可能與你構造STD :: string的方式有關。

+0

c_str不刪除空值,但要謹慎,它會返回一個仍然由字符串類所擁有的指針,所以您必須確保複製內容 – 2010-10-08 14:03:40

+0

請使用代碼段查看已編輯的問題。它在相同的範圍內,不是嗎? – Jake 2010-10-08 14:40:50

+1

無論如何,亞歷山大的觀點是,在你的代碼片段中,過濾器std :: string並沒有被你的全部輸入初始化,因爲構造函數會在第一個nul停止讀取。根據Steve的回答,你需要使用'std :: string filter(「Terrain Configuration(* .tcfg)\ 0 * .tcfg \ 0 \ 0」,40);'我想。 – Rup 2010-10-08 14:45:55

1

它取決於std :: string的進一步生命週期。

例如,可以手動附加終端零:

std::string test("init"); 
test += '\0'; 

這導致長度被增加一。或者只是創建另一個std :: string實例,並附加了零:

2

您的stringlength()是您需要用來確保包含所有字符的前提條件,只要它在第一個位置正確構建以包含嵌入的\0字符。

對於LPCSTR有效而cString的範圍是:

#include <boost/scoped_array.hpp> 
#include <string> 
#include <algorithm> 

string source("mystring"); 
boost::scoped_array<char> cString(new char[source.length() + 1]); 

std::copy(source.begin(), source.end(), cString.get()); 
cString[source.length()] = 0; 

LPCSTR rawStr = cString.get(); 

沒有scoped_array:

#include <string> 
#include <algorithm> 

string source("mystring"); 
LPSTR rawStr = new char[source.length() + 1]; 

std::copy(source.begin(), source.end(), rawStr); 
rawStr[source.length()] = 0; 

// do the work here 

delete[] rawStr; 

編輯: 在你filter初始化的string構造僅包括數據上升到第\0 char。這是有道理的 - 當它手頭有數據時,如何不停止拷貝數據是const char *?試試這個:

const char f3[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(f3, sizeof(f3)); 
+0

嗯......我可以一次複製一個字符,但只希望有一個更快的方法。 – Jake 2010-10-08 14:41:54

+0

@Jake - 'std :: copy'不需要逐字節的複製循環。如果你刪除上面的'scoped_array',它可能會更清晰,直接在'rawStr'中直接新增。請參閱編輯。 – 2010-10-08 14:46:21

5

一般來說,std :: string會正確處理嵌入的'\ 0'字符。

但是,當與const char *接口時,必須非常小心。

在這種情況下,問題已經出現在構建的字符串:

std::string filter = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; // wrong 

在這裏,你從一個const char構造的std :: string *。由於構造函數不知道構建std :: string需要使用多少個字符,因此會停在第一個'\ 0'處。

人們可以通過一個自己一個複製的人物,但有一個更好的辦法:使用需要兩個迭代器的字符數組,一個有開始和一個與末端的構造器:

const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(filter_, filter_ + sizeof(filter_)); 

它看起來很可怕,但希望你不會在你的代碼中經常這樣做。

更新:或))開始的appropiate定義(和結束(模板(根據詹姆斯·甘孜的評論):

const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(begin(filter_), end(filter_)); 
+0

這是sizeof(filter_) - 1如果字符串常量已經有 – 2010-10-08 15:09:07

+1

對不起,不習慣這個接口: 這就是sizeof(filter_) - 1如果字符串常量已經是 包含雙精度\ 0。初始化一個字符串爲 的數組會自動附加'\ 0'。 當然,當字符爲 變爲wchar_t時,sizeof的使用將會中斷。函數begin(filter_),end(filter_),例如: \t std :: string(begin(filter_),end(filter_));更好的辦法是使用通用模板 。 – 2010-10-08 15:12:16

+0

@詹姆斯Kanze:感謝指出begin()和end()模板,我還不知道他們。 – Sjoerd 2010-10-08 16:09:06