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

发布于 2024-09-26 20:06:30 字数 637 浏览 2 评论 0原文

如何将 std::string 转换为 LPCSTR,同时保留 '\0' 字符?

我想在 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 的工作原理?

How can I convert std::string to LPCSTR while preserving '\0' characters?

I want to use the result on OPENFILENAME.lpstrFilter which requires the filter to contain '\0' as delimiters.

std::string.c_str() seems to strip and trim '\0'

Thanks in advance!

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

(How do I properly add a comment to the responses like a reply post in a forum?)

After reading your comments, I went on to double check this snippet:

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.
}

Am I mistaken on how c_str() or LPCSTR works?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

九公里浅绿 2024-10-03 20:06:30

C_STR 不会去除 NUL 字符。该错误可能是您构建 STD::string 的方式造成的。

C_STR doesn't strip the NUL characters. The error is likely in the way you are constructing the STD::string.

偏闹i 2024-10-03 20:06:30

一般来说,std::string 可以正确处理嵌入的 '\0' 字符。

然而,在与 const char* 交互时,必须格外小心。

在这种情况下,在构造字符串过程中已经出现了问题:

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

这里,您从 const char* 构造 std::string 。由于构造函数不知道要使用多少个字符来构造 std::string,因此它会在第一个 '\0' 处停止。

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

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

它看起来很糟糕,但希望你不会这样做这在你的代码中经常出现。

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

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

Generally speaking, std::string handles embedded '\0' characters correctly.

However, when interfacing with const char*, extreme care must be taken.

In this case, the problem already occurs during constructing the string with:

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

Here you construct a std::string from a const char*. As the constructor doesn't know how many characters to use for constructing the std::string, it stops at the first '\0'.

One could copy the characters one by one oneself, but there is a better way: use the contructor that requires two iterators to the char array, one with the begin and one with the end:

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

It looks horrible, but hopefully you won't do this that frequently in your code.

Update: Or with appropiate definitions of begin() and end() templates (as per James Kanze's comment):

const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(begin(filter_), end(filter_));
你没皮卡萌 2024-10-03 20:06:30

您需要使用 stringlength() 来确保包含所有字符,前提是它首先被正确构造以包含嵌入的 \0 个字符。

对于在 cString 处于范围内时有效的 LPCSTR

#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 init 中,string 的构造函数仅包含第一个 \0 字符之前的数据。这是有道理的 - 当手头只有 const char * 时,它怎么会不停止复制数据呢?尝试使用以下方法:

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

The length() of your string is what you need to use to ensure all characters are included, provided it was properly constructed in the first place to include the embedded \0 characters.

For an LPCSTR valid while cString is in scope:

#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();

Without 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;

EDIT:
In your filter init, the constructor of string only includes data up to the first \0 char. This makes sense - how else would it not to stop copying data when all it has in hand is const char *? Try this with:

const char f3[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0";
std::string filter(f3, sizeof(f3));
滥情空心 2024-10-03 20:06:30

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

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

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

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

It depends on further life-cycle of std::string.

For example you can append terminal zero manually:

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

This causes length to be increased by one. Or just create another instance of std::string with zero appended

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文