2010-10-08 84 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