比较std :: wstring和std :: string

ali*_*ian 3 c++

我如何可以比较wstring,比如L"Hello",一个string?如果我需要相同的类型,我怎样才能将它们转换为相同的类型?

Ker*_* SB 6

既然你问,这是我的标准转换函数,从字符串到宽字符串,使用C++ std::stringstd::wstring类实现.

首先,确保启动您的程序set_locale:

#include <clocale>

int main()
{
  std::setlocale(LC_CTYPE, "");  // before any string operations
}
Run Code Online (Sandbox Code Playgroud)

现在为功能.首先,从一个窄字符串中获取一个宽字符串:

#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cwchar>
#include <cerrno>

// Dummy overload
std::wstring get_wstring(const std::wstring & s)
{
  return s;
}

// Real worker
std::wstring get_wstring(const std::string & s)
{
  const char * cs = s.c_str();
  const size_t wn = std::mbsrtowcs(NULL, &cs, 0, NULL);

  if (wn == size_t(-1))
  {
    std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
    return L"";
  }

  std::vector<wchar_t> buf(wn + 1);
  const size_t wn_again = std::mbsrtowcs(buf.data(), &cs, wn + 1, NULL);

  if (wn_again == size_t(-1))
  {
    std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
    return L"";
  }

  assert(cs == NULL); // successful conversion

  return std::wstring(buf.data(), wn);
}
Run Code Online (Sandbox Code Playgroud)

然后回去,用宽弦做一个窄弦.我将窄字符串称为"locale string",因为它依赖于平台相关的编码,具体取决于当前的语言环境:

// Dummy
std::string get_locale_string(const std::string & s)
{
  return s;
}

// Real worker
std::string get_locale_string(const std::wstring & s)
{
  const wchar_t * cs = s.c_str();
  const size_t wn = std::wcsrtombs(NULL, &cs, 0, NULL);

  if (wn == size_t(-1))
  {
    std::cout << "Error in wcsrtombs(): " << errno << std::endl;
    return "";
  }

  std::vector<char> buf(wn + 1);
  const size_t wn_again = std::wcsrtombs(buf.data(), &cs, wn + 1, NULL);

  if (wn_again == size_t(-1))
  {
    std::cout << "Error in wcsrtombs(): " << errno << std::endl;
    return "";
  }

  assert(cs == NULL); // successful conversion

  return std::string(buf.data(), wn);
}
Run Code Online (Sandbox Code Playgroud)

一些说明:

  • 如果你没有std::vector::data(),你可以说&buf[0].
  • 我发现,在r风格转换功能mbsrtowcs,并wcsrtombs不能在Windows正常工作.在那里,你可以用mbstowcswcstombs来代替:mbstowcs(buf.data(), cs, wn + 1);,wcstombs(buf.data(), cs, wn + 1);


在回答您的问题时,如果您想比较两个字符串,可以将它们转换为宽字符串然后进行比较.如果从磁盘读取具有已知编码iconv()的文件,则应使用将文件从已知编码转换为WCHAR,然后与宽字符串进行比较.

但要注意,复杂的Unicode文本可能有多种不同的表示形式,您可能需要考虑相同的代码点序列.如果可能,您需要使用更高级别的Unicode处理库(例如ICU)并将字符串规范化为一些常见的可比较形式.