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

时间:2015-06-21 04:20:45

标签: c++ windows mfc stdstring

我正在尝试将我的代码移植到使用MFC的CStringstd::string的Microsoft Windows平台。我对某些事感到好奇。在下面的例子中说:

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覆盖上述方法?

4 个答案:

答案 0 :(得分: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

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

使用扩展内部字符串缓冲区

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

当你最终收缩以适应字符串时,在扩展字符串的内部缓冲区时,与MFC替代方法相比,你只需要一行代码,当缩小字符串时,它几乎具有相同的开销。

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

答案 1 :(得分:2)

小写std::string的可接受方式是:

#include <algorithm>
#include <string> 

std::string data = "Abc"; 
std::transform(data.begin(), data.end(), data.begin(), ::tolower);

你真的无法绕过每个角色。原始的Windows API调用将在内部进行相同的字符迭代。

如果你需要获得toLower()以外的语言环境而不是标准&#34; C&#34;语言环境,您可以改为使用:

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()const char *获取std::string(LPCSTR)。您无法直接将std::string转换为char *(LPTSTR);这是设计上的,会破坏使用std::string的一些动机。

答案 2 :(得分:2)

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指针”将字符串输入遗留函数,并将其用作OUT参数。当然,您需要确保字符串中有足够的容量才能使其工作等。

答案 3 :(得分:1)

根据您的要求,您可以使用以下一项或多项:

  1. std::string::operator[]()。此函数返回给定索引处的字符,而不进行边界检查。

  2. std::string::at()。此函数返回给定索引处的字符,并带有边界检查。

  3. std::string::data()。此函数返回指向原始数据的const指针。

  4. std::string::c_str()。此函数返回与std::string::data()

  5. 相同的值