如何在源文件中嵌入unicode字符串常量?

时间:2009-01-14 12:13:55

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

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

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

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

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

这根本不起作用。以前我使用宏调用一个例程将一个窄字符串转换为一个宽字符串(我们在应用程序中使用towstring所以它是现有代码)

#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。谁能告诉我他们是否有更好的解决方案来解决这个问题?

3 个答案:

答案 0 :(得分:18)

繁琐但可移植的方法是使用数字转义码来构建字符串。例如:

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

变为:

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

您必须将所有Unicode字符转换为数字转义符。这样,您的源代码就变得与编码无关。

您可以使用在线工具进行转换,例如this one。它输出JavaScript转义格式\uXXXX,所以只需搜索&amp;将\u替换为\x以获取C格式。

答案 1 :(得分:11)

您必须告诉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位)不得超过gcc使用的wchar_t大小。

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

gcc联机帮助页man gcc中详细介绍了这些选项。

答案 2 :(得分:0)

#define UNICODE_CONSTANT( CONSTANT ) towstring( CONSTANT )

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

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