如何从std :: string获取可写C缓冲区?

c00*_*0fd 5 c++ windows mfc stdstring

我正在尝试将我的代码从使用MFC移植CStringstd::stringMicrosoft Windows平台.而且我对某些事感到好奇.在以下示例中说:

CString MakeLowerString(LPCTSTR pStr)
{
    CString strLower = pStr ? pStr : L"";
    CharLower(strLower.GetBuffer());        //Use WinAPI
    strLower.ReleaseBuffer();

    return strLower;
}
Run Code Online (Sandbox Code Playgroud)

我用strLower.GetBuffer()获取要传递给CharLower API 的可写缓冲区.但我没有看到类似的方法std::string.

我错过了什么吗?如果是这样,您将如何覆盖上述方法std::string

小智 5

在我的新工作中,我们不使用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:\TESTING\toBeCutOff)?") );
::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 \0 character
path.shrink_to_fit();                  // optional to adjust the string's
                                       // capacity - useful if you
                                       // do not plan to modify the string again
Run Code Online (Sandbox Code Playgroud)

Unicode版本:

std::wstring path( LR("?(C:\TESTING\toBeCutOff)?") );
::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 \0 character
path.shrink_to_fit();                  // optional to adjust the string's
                                       // capacity - useful if you
                                       // do not plan to modify the string again
Run Code Online (Sandbox Code Playgroud)

使用Win32-API函数扩展内部字符串缓冲区

假设您有一个字符串,该字符串将由Win32-API函数扩展或填充(例如::GetModuleFileName(NULL, path, cPath),检索可执行文件的路径),则可以采用以下方法:

std::wstring path( LR("?(C:\TESTING\toBeCutOff)?") );
::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 \0 character
path.shrink_to_fit();                  // optional to adjust the string's
                                       // capacity - useful if you
                                       // do not plan to modify the string again
Run Code Online (Sandbox Code Playgroud)

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 \0 character
path.shrink_to_fit();                  // optional to adjust the string's
                                       // capacity - useful if you
                                       // do not plan to modify the string again
Run Code Online (Sandbox Code Playgroud)

当最终收缩以适合字符串时,与MFC替代方案相比,在扩展字符串的内部缓冲区时只需要多一行代码,而在收缩字符串时,开销几乎相同。

与该std::string方法相比,该CString方法的优势在于您不必声明其他C-String指针变量,而只需使用官方std::string方法和一个strlen/ wcslen函数即可。当显示的Win32-API缓冲区为空终止时,上面显示的我的方法仅适用于收缩变体,但是对于Win32-API返回未终止的字符串的非常特殊的情况,则-与CString::ReleaseBuffer方法类似-您必须明确知道并指定新的字符串/缓冲区长度path.resize( newLength )-就像path.ReleaseBuffer( newLength )CString替代。


Spe*_*uce -1

要小写std::string 仅包含 ASCII 字符的a ,您可以使用以下代码:

#include <algorithm>
#include <string> 

std::string data = "Abc"; 
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
Run Code Online (Sandbox Code Playgroud)

你确实无法绕过遍历每个角色。最初的 Windows API 调用将在内部执行相同的字符迭代。

如果您需要获取toLower()多字节编码(例如UTF-8)或标准“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));
Run Code Online (Sandbox Code Playgroud)

要直接回答您的问题并去掉任何上下文,您可以调用从 astr.c_str()获取const char *(LPCSTR) std::string。不能直接将 a 转换std::string为 a char *(LPTSTR);这是设计使然,会破坏某些使用 的动机std::string

  • 请不要让它偏离轨道。我不是在问转换为小写。这只是我快速整理的一个例子。我问的是如何从 std::string 获取可写缓冲区。 (2认同)