如何从std::string中获取可写的C缓冲区
How to get a writable C buffer from std::string?
我正在尝试将我的代码从使用MFC的CString
移植到适用于Microsoft Windows平台的std::string
。我对一些事情很好奇。例如:
CString MakeLowerString(LPCTSTR pStr)
{
CString strLower = pStr ? pStr : L"";
CharLower(strLower.GetBuffer()); //Use WinAPI
strLower.ReleaseBuffer();
return strLower;
}
我使用strLower.GetBuffer()来获得一个可写缓冲区,以便传递给CharLower API。但我在std::string
中没有看到类似的方法。
我是不是错过了什么?如果是,您将如何使用std::string
覆盖上面的方法?
在我的新工作中,我们不使用MFC,但幸运的是std-lib和C++11,所以我遇到了与c00000fd相同的问题。多亏了BitTickler的回答,我想出了通过&s[0]
resp为Win32 API使用字符串的内部缓冲区的想法。&s.front()
捕获。
使用收缩内部字符串缓冲区的Win32-API函数
假设您有一个字符串,该字符串将被Win32-API函数(例如::PathRemoveFileSpec(path)
)缩短,您可以遵循以下方法:
std::string path( R("?(C:TESTINGtoBeCutOff)?") );
::PathRemoveFileSpec( &path.front() ); // Using the Win32-API
// and the the string's internal buffer
path.resize( strlen( path.data() ) ); // adjust the string's length
// to the first character
path.shrink_to_fit(); // optional to adjust the string's
// capacity - useful if you
// do not plan to modify the string again
Unicode版本:
std::wstring path( LR("?(C:TESTINGtoBeCutOff)?") );
::PathRemoveFileSpec( &path.front() ); // Using the Win32-API
// and the the string's internal buffer
path.resize( wcslen( path.data() ) ); // adjust the string's length
// to the first character
path.shrink_to_fit(); // optional to adjust the string's
// capacity - useful if you
// do not plan to modify the string again
使用扩展内部字符串缓冲区的Win32-API函数
假设你有一个字符串,它将被Win32-API函数扩展或填充,例如::GetModuleFileName(NULL, path, cPath)
来检索你的可执行文件的路径,你可以遵循这种方法:
std::string path;
path.resize(MAX_PATH); // adjust the internal buffer's size
// to the expected (max) size of the
// output-buffer of the Win32-API function
::GetModuleFileName( NULL, &path.front(), static_cast<DWORD>( path.size() ) );
// Using the Win32-API
// and the the string's internal buffer
path.resize( strlen( path.data() ) ); // adjust the string's length
// to the first character
path.shrink_to_fit(); // optional to adjust the string's
// capacity - useful if you
// do not plan to modify the string again
Unicode版本:
std::wstring path;
path.resize(MAX_PATH); // adjust the internal buffer's size
// to the expected (max) size of the
// output-buffer of the Win32-API function
::GetModuleFileName( NULL, &path.front(), static_cast<DWORD>( path.size() ) );
// Using the Win32-API
// and the the string's internal buffer
path.resize( wcslen( path.data() ) ); // adjust the string's length
// to the first character
path.shrink_to_fit(); // optional to adjust the string's
// capacity - useful if you
// do not plan to modify the string again
当你最终收缩以适应字符串时,与MFC替代方案相比,在扩展字符串的内部缓冲区时,你只需要多一行代码,而在收缩字符串时,它的开销几乎相同。
与CString
方法相比,std::string
方法的优势在于,您不必声明额外的C字符串指针变量,只需使用官方的std::string
方法和一个strlen
/wcslen
函数即可。上面所示的方法仅适用于Win32-API缓冲区为null终止时的收缩变体,但对于Win32-API返回未终止字符串的特殊情况,则-类似于CString::ReleaseBuffer
方法-您必须通过path.resize( newLength )
显式知道并指定新的字符串/缓冲区长度-就像CString
备选方案的path.ReleaseBuffer( newLength )
一样。
void GetString(char * s, size_t capacity)
{
if (nullptr != s && capacity > 5)
{
strcpy_s(s,capacity, "Hello");
}
}
void FooBar()
{
std::string ss;
ss.resize(6);
GetString(&ss[0], ss.size());
std::cout << "The message is:" << ss.c_str() << std::endl;
}
正如您所看到的,您既可以使用"老派c-pointer"将字符串输入到遗留函数中,也可以将其用作OUT参数。当然,您需要确保字符串中有足够的容量使其工作等。
根据您的需求,您可以使用以下一个或多个:
-
CCD_ 18。此函数返回给定索引处的字符,不进行边界检查。
-
std::string::at()
。此函数通过边界检查返回给定索引处的字符。 -
CCD_ 20。此函数返回一个指向原始数据的
const
指针。 -
CCD_ 22。此函数返回与
std::string::data()
相同的值
要使仅包含ASCII字符的std::string
小写,可以使用以下代码:
#include <algorithm>
#include <string>
std::string data = "Abc";
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
你真的无法绕过每个角色的迭代。最初的Windows API调用将在内部执行相同的字符迭代。
如果您需要获得用于多字节编码(例如UTF-8)的toLower()
,或者除标准";C";区域设置,您可以使用:
std::string str = "Locale-specific string";
std::locale loc("en_US.UTF8"); // desired locale goes here
const ctype<char>& ct = use_facet<ctype<char> >(loc);
std::transform(str.begin(), str.end(), str.begin(), std::bind1st(std::mem_fun(&ctype<char>::tolower), &ct));
要直接回答您的问题并减去任何上下文,您可以调用str.c_str()
从std::string
中获取const char *
(LPCSTR)。不能直接将std::string
转换为char *
(LPTSTR);这是故意的,会破坏使用CCD_ 31的一些动机。
- 使用 strcat 获取缓冲区溢出错误
- 是否可以从 OpenGL 缓冲区获取原始大小的像素?
- 在 DirectX 11 中从 GPU 读回顶点缓冲区(并获取顶点)
- 让 iaxClient 将音频发送到缓冲区而不是音频设备/从缓冲区获取音频
- CSV文件未从缓冲区获取数据
- 从 CImage AtlImage 获取缓冲区数组
- 如何在运行时从平面缓冲区获取数据值和数据类型
- 无法获取索引缓冲区以在 OpenGL 中绘制正方形
- 从交换链获取多个屏幕缓冲区
- 从索引缓冲区中获取索引
- 如何使用 std::istringstream 获取正确的缓冲区大小以进行数据解析
- 获取 vscode c++ 插件以查找协议缓冲区标头
- GlReadPixel始终从深度缓冲区0中获取
- 获取当前目录,我可以在不知道最大缓冲区大小的情况下进行
- 套接字:在没有memcpy的情况下,使用recvfrom将UDP数据获取到字对齐的缓冲区
- 如何从窗口中获取像素数据像素缓冲区并提取RGB
- OpenGL:只获取模具缓冲区而不获取深度缓冲区
- 获取字符串流中的最后一个字符,而不复制其整个缓冲区
- 获取字符串流的适当大小,以便将其放入缓冲区
- 协议缓冲区获取EnumDescriptor *