C++ 将std::string转换为带尾随或前导的LPCSTR'\0';

C++ 将std::string转换为带尾随或前导的LPCSTR'\0';,c++,stdstring,lpcstr,C++,Stdstring,Lpcstr,如何在保留“\0”字符的同时将std::string转换为LPCSTR 我想使用OPENFILENAME.lpstrFilter上的结果,该结果要求筛选器包含“\0”作为分隔符 std::string.c_str()似乎在剥离和修剪“\0” 提前谢谢 ========================== (我如何正确地在回复中添加评论,如论坛中的回复帖子?) 在阅读了您的评论之后,我再次检查了这段代码: std::string filter = "Terrain Configuration (*

如何在保留“\0”字符的同时将std::string转换为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.
}
std::string filter=“地形配置(*.tcfg)\0*.tcfg\0\0”;
const char*f1=“地形配置(*.tcfg)\0*.tcfg\0\0”;
const char*f2=filter.c_str();
对于(int i=0;i<50;i++)
{
字符c1=*(f1+i);//有效
char c2=*(f2+i);//不起作用。超过第一个\0,它是垃圾。
}

我是否误解了c_str()或LPCSTR的工作原理?

这取决于std::string的进一步生命周期

例如,您可以手动附加端子零:

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

这将导致长度增加1。或者只创建另一个附加了零的std::string实例

C_STR不会去除NUL字符。该错误可能是在构造STD::string时发生的。

您的
字符串的
长度()
是确保包含所有字符所需的,前提是首先正确构造该字符串以包含嵌入的
\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();

一般来说,std::string正确处理嵌入的“\0”字符

但是,当与const char*接口时,必须格外小心

在这种情况下,在使用以下内容构造字符串时,问题已经出现:

std::string filter = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; // wrong
在这里,您可以从const char*构造一个std::字符串。由于构造函数不知道用于构造std::string的字符数,因此它会在第一个“\0”处停止

可以一个接一个地复制字符,但有一种更好的方法:使用构造函数,该构造函数需要两个迭代器来复制字符数组,一个带开始,一个带结束:

const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(filter_, filter_ + sizeof(filter_));
这看起来很可怕,但希望您在代码中不会经常这样做

更新:或使用begin()和end()模板的适当定义(根据James Kanze的评论):


c_str不会去掉null,但要小心,它返回的指针仍然属于string类,因此您必须确保复制内容请参见带代码段的已编辑问题。它在同一个范围内,不是吗?不管怎样,Alexander的观点是,在您的代码段中,筛选器std::string没有使用您的完整输入进行初始化,因为构造函数将在第一个nul时停止读取。根据下面Steve的回答,您需要使用
std::string过滤器(“地形配置(*.tcfg)\0*.tcfg\0\0”,40)我想。请参阅:
lpstrFilter:缓冲区中的最后一个字符串必须以两个空字符结尾。
。要使该参数正常工作,需要在末尾添加两个空字符<代码>c_str()
按设计只有一个。嗯。。。我可以一次复制一个字符,但只是希望有一种更快的方法。@Jake-
std::copy
消除了逐字节复制循环的需要。如果删除上面的
作用域_数组
,可能会更清晰,只需直接将其新建到
rawStr
。请参见编辑。如果字符串常量已包含sorry,则为sizeof(filter_u2;)-1,不用于此接口:如果字符串常量已包含double\0,则为sizeof(filter_2;)-1。使用字符串常量初始化数组会自动附加“\0”。当然,当char更改为wchar\u t时,sizeof的使用将中断。最好使用常用的模板函数begin(filter_)、end(filter_),例如:std::string(begin(filter_)、end(filter_))@James Kanze:谢谢你指出begin()和end()模板,我还不知道它们。@James Kanze:wrt the-1,我认为在末尾有三个'\0'是无害的,不想让答案太复杂。我的选择是省略字符串常量末尾的第二个“\0”,并添加一条注释,说明编译器将添加第二个“\0”。
std::string filter = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; // wrong
const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(filter_, filter_ + sizeof(filter_));
const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(begin(filter_), end(filter_));