【问题标题】:How can I embed unicode string constants in a source file?如何在源文件中嵌入 unicode 字符串常量?
【发布时间】:2010-10-01 08:39:16
【问题描述】:

我正在编写一些单元测试,以验证我们对使用除普通拉丁字母之外的其他字符集的各种资源的处理:西里尔语、希伯来语等。

我遇到的问题是我找不到将期望嵌入到测试源文件中的方法:这是我正在尝试做的一个示例...

///
/// Protected: TestGetHebrewConfigString
///  
void CPrIniFileReaderTest::TestGetHebrewConfigString()
{
    prwstring strHebrewTestFilePath = GetTestFilePath( strHebrewTestFileName );
    CPrIniFileReader prIniListReader( strHebrewTestFilePath.c_str() );
    prIniListReader.SetCurrentSection( strHebrewSubSection );   

    CPPUNIT_ASSERT( prIniListReader.GetConfigString( L"דונדארןמע" ) == L"דונהשךוק") );
}

这根本行不通。以前我使用一个宏来解决这个问题,该宏调用一个将窄字符串转换为宽字符串的例程(我们在应用程序中到处都使用拖字符串,所以它是现有代码)

#define UNICODE_CONSTANT( CONSTANT ) towstring( CONSTANT )

wstring towstring( LPCSTR lpszValue )
{
    wostringstream os;
    os << lpszValue;
    return os.str();
}

上面测试中的断言就变成了:

CPPUNIT_ASSERT( prIniListReader.GetConfigString( UNICODE_CONSTANT( "דונדארןמע" ) ) == UNICODE_CONSTANT( "דונהשךוק" ) );

这在 OS X 上运行良好,但现在我正在移植到 linux 并且我发现测试都失败了:这一切都让人感觉很hackish。谁能告诉我他们是否有更好的解决方案来解决这个问题?

【问题讨论】:

    标签: c++ unit-testing string unicode constants


    【解决方案1】:

    一种乏味但可移植的方法是使用数字转义码构建字符串。例如:

    wchar_t *string = L"דונדארןמע";
    

    变成:

    wchar_t *string = "\x05d3\x05d5\x05e0\x05d3\x05d0\x05e8\x05df\x05de\x05e2";
    

    您必须将所有 Unicode 字符转换为数字转义符。这样你的源代码就变得独立于编码了。

    您可以使用在线工具进行转换,例如this one。它输出 JavaScript 转义格式 \uXXXX,因此只需搜索并替换 \u\x 即可获得 C 格式。

    【讨论】:

    • 在 windows 中 wchar_t 是 16 位,其他都是 32 位。这会影响需要列出哪些十六进制文字吗?或者\x05d3 是否同样适用于 16 位和 32 位?
    • \x 之后的十六进制数字的数量没有限制,所以无论 sizeof(wchar_t) 都应该是一样的。有关更多信息,请参阅此主题:stackoverflow.com/questions/2735101/unicode-escaping-in-c-c
    【解决方案2】:

    您必须告诉 GCC 您的文件使用哪种编码将这些字符编码到文件中。

    使用选项-finput-charset=charset,例如-finput-charset=UTF-8。然后你需要告诉它在运行时用于这些字符串文字的编码。这将确定字符串中 wchar_t 项的值。您使用-fwide-exec-charset=charset 设置该编码,例如-fwide-exec-charset=UTF-32。注意编码的大小(utf-32 需要 32 位,utf-16 需要 16 位)不能超过wchar_t gcc 使用的大小。

    你可以调整它。该选项主要用于为wine 编译程序,旨在与 Windows 兼容。该选项称为-fshort-wchar,很可能是 16 位而不是 32 位,这是 linux 上 gcc 的常用宽度。

    这些选项在 gcc 手册页 man gcc 中有更详细的描述。

    【讨论】:

      【解决方案3】:
      #define UNICODE_CONSTANT( CONSTANT ) towstring( CONSTANT )
      
      wstring towstring( LPCSTR lpszValue ) {
          wostringstream os;
          os << lpszValue;
          return os.str(); 
      }
      

      这实际上根本不会在 Unicode 编码之间进行转换,这需要一个专门的例程。您需要保持源代码和数据编码统一——大多数人使用 UTF-8——然后在必要时将其转换为特定于操作系统的编码(例如 Winders 上的 UTF-16)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-04
        • 2016-11-09
        • 1970-01-01
        • 2011-05-17
        • 2011-07-25
        • 2020-04-02
        • 2011-02-03
        相关资源
        最近更新 更多