Ash*_*ppa 13 c c++ string unicode
我看到Visual Studio 2008及更高版本现在开始使用字符集设置为Unicode的新解决方案.我的旧C++代码只处理英文ASCII文本,并且满是:
"Hello World"
char
类型char *
指向已分配的C字符串的指针STL string
类型转换STL string
为C字符串,反之亦然,使用STL string
构造函数(接受const char *
)和STL string.c_str()
我需要对迁移此代码进行哪些更改,以便它在Visual Studio Unicode和Unicode启用的库的生态系统中工作?(我不需要它同时使用ASCII和Unicode,它可以是纯Unicode.)
是否也可以以独立于平台的方式执行此操作?(即,不使用Microsoft类型.)
我看到很多广泛的字符和Unicode类型和转换散落在周围,因此我的困惑.(例如:wchar_t,TCHAR,_T,_TEXT,TEXT等)
Pav*_*sky 14
I recommend very much against L""
, _T()
, std::wstring
(the latter is not multiplatform) and Microsoft recommendations on how to do Unicode.
There's a lot of confusion on this subject. Some people still think Unicode == 2 byte characters == UTF-16. Neither equality is correct.
In fact, it's possible, and even better to stay with char*and the plain std::string
, plain literals and change very little (and still fully support Unicode!).
请参阅我的回答:https://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful/1855375#1855375,了解如何以最简单的方式(在我看来)这样做.
pae*_*bal 14
注意:哇...显然,有人决定几乎所有的答案都应该得到一个downmod,即使是正确的...我自己对它进行了修改以平衡downmod ...
让我们看看我是否有自己的downmod ......: - /
九个小时前,有人(可能是那个对Pavel Radzivilovsky的每个答案都赞不绝口的人)低估了这个答案.当然,没有任何评论指出我的答案有什么问题.
\ O /
我需要对迁移此代码进行哪些更改,以便它在Visual Studio Unicode和Unicode启用的库的生态系统中工作?(我不需要它同时使用ASCII和Unicode,它可以是纯Unicode.)
让我们想象你想逐渐做到这一点(因为你的应用程序不小).
我的团队遇到了同样的问题:我想生成Unicode准备好的代码,这些代码与非Unicode准备好的代码共存.
为此,您必须使用MS'标头tchar.h
,并使用其设施.使用您自己的示例:
"Hello World"
----> _T("Hello World")
char
类型----> TCHAR
类型char *
分配C字符串的TCHAR *
指针----> 指针std::string
类型--->这很棘手,因为你必须创建自己的 std::tstring
tstring.hpp
标题要使用我的编译器来处理STL(当时,我正在使用Visual C++ 2003,所以你的里程可能会有所不同),我必须提供一个tstring.hpp
标题,它既可以跨平台又可以让用户使用tstring,tiostream等..我不能把完整的资源放在这里,但是我会提供一个能让你自己制作的摘录:
namespace std
{
#ifdef _MSC_VER
#ifdef UNICODE
typedef wstring tstring ;
typedef wistream tistream ;
// etc.
#else // Not UNICODE
typedef string tstring ;
typedef istream tistream ;
// etc.
#endif
#endif
} // namespace std
Run Code Online (Sandbox Code Playgroud)
通常,它没有被授权污染std
命名空间,但我想这是好的(并且测试好了).
这样,您可以为大多数STL/C++ iostreams构造添加前缀,t
并准备好Unicode(在Windows上).
现在,您可以通过定义UNICODE
和_UNICODE
定义来从ANSI模式切换到UNICODE模式,通常在项目设置中(我记得在Visual C++ 2008上,第一个设置页面中的条目完全是为了这个).
我的建议是,因为您可能在Visual C++项目上有"调试"和"释放"模式,以创建从它们派生的"调试Unicode"和"释放Unicode"模式,其中定义了上述宏.
因此,您将能够生成ANSI和UNICODE二进制文件.
如果您希望自己的应用跨平台,请忽略此部分.
现在,要么您可以一步修改所有代码库,要么已经转换了所有代码库以使用上述tchar.h
功能,现在可以从代码中删除所有宏:
_T("Hello World")
----> L"Hello World"
TCHAR
类型----> wchar_t
类型TCHAR *
分配C字符串的wchar_t *
指针----> 指针std::tstring
类型---> std::wstring
类型等Windows上一个常见的误解是相信wchar_t字符是一个Unicode字形.这是错误的,因为一些Unicode字形由两个wchar_t表示.
因此,char
如果您使用的非Unicode字形不是来自BMP ,那么任何依赖于一个为一个字形的代码都可能会中断.
是否也可以以独立于平台的方式执行此操作?(即,不使用Microsoft类型.)
现在,这是棘手的部分.
Linux(我不知道其他操作系统,但它很容易从Linux或Windows解决方案推断)现在是Unicode就绪,该char
类型应该包含UTF-8值.
这意味着您的应用程序,例如,在我的Ubuntu 10.04上编译后,默认为Unicode.
当然,上面关于UTF-16和宽字符的建议在这里更为重要:
Unicode字形可以char
表示1到4个字符.因此,您使用的任何代码都依赖于每个char
都是一个独立的Unicode字符的假设会破坏.
tchar.h
Linux 上没有!我的解决方案:写下来.
您只需要定义't'前缀符号以映射到正常符号,如此提取中所示:
#ifdef __GNUC__
#ifdef __cplusplus
extern "C" {
#endif
#define _TEOF EOF
#define __T(x) x
// etc.
#define _tmain main
// etc.
#define _tprintf printf
#define _ftprintf fprintf
// etc.
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
#ifdef __cplusplus
}
#endif
#endif // __GNUC__
Run Code Online (Sandbox Code Playgroud)
...并将其包含在Linux上,而不是包含tchar.h
来自Windows的.
tstring
Linux 上没有!当然,上面为Windows完成的STL映射应该完成以处理Linux的情况:
namespace std
{
#ifdef _MSC_VER
#ifdef UNICODE
typedef wstring tstring ;
typedef wistream tistream ;
// etc.
#else // Not UNICODE
typedef string tstring ;
typedef istream tistream ;
// etc.
#endif
#elif defined(__GNUC__)
typedef string tstring ;
typedef istream tistream ;
// etc.
#endif
} // namespace std
Run Code Online (Sandbox Code Playgroud)
现在,您可以在Linux和Windows上使用_T("Hello World")
和std::tstring
.
而且有.
首先,存在std
使用您自己的t
前缀符号污染命名空间的问题,这应该被禁止.然后,不要忘记宏上的添加,这将污染您的代码.在目前的情况下,我猜这是好的.
二,我认为你在Windows上使用MSVC(因此是宏_MSC_VER
)和Linux上的GCC(因此是宏__GNUC__
).如果您的情况不同,请修改定义.
三,您的代码必须是Unicode中性的,也就是说,您必须不依赖于您的字符串为UTF-8或UTF-16.实际上,除了ASCII字符之外,你的源代码应该是空的,以保持跨平台兼容.
这意味着某些功能,例如搜索ONE Unicode Glyph的存在,必须通过单独的代码完成,这将具有#define
使其正确运行所需的所有功能.
例如,搜索字符é
(Unicode Glyph 233)需要您在Windows上使用UTF-16 wchar_t时搜索第一个字符233,并在UTF-8上使用第一个两个字符195和169的序列char
.这意味着您必须使用某些Unicode库来执行此操作,或者自己编写它.
但这更像是Unicode本身的问题,而不是Windows或Linux上的Unicode.
所以呢?
我看到的"规范"示例是EDIT Win32控件,它应该无法在Windows上正确退格非BMP UTF-16字符(不是我没有验证错误,我只是不在乎) .
这是Microsoft的问题.您在代码中决定的任何内容都不会改变Win32 API中存在或不存在此错误的事实.因此,在Windows上使用UTF-8字符不会纠正EDIT控件上的错误.您唯一可以做的就是创建自己的EDIT控件(将其子类化并正确处理BACKSPACE事件?)或您自己的转换函数.
不要混淆两个不同的问题,即:Windows API中的假定错误和您自己的代码.除非您不使用假设的错误Windows API,否则您自己的代码中的任何内容都不会避免Windows API中的错误.
是的,它可能会导致某些平台上的错误,如果你对字符的假设过多,那么其他平台上就不会发生错误.
我假设你的主要平台是Windows(或者你想为两者wchar_t
和char
用户提供一个库).
但如果不是这种情况,如果Windows不是你的主要平台,那么就有一个假设所有char和std :: string都包含UTF-8字符的解决方案,除非说明不同.然后,您需要包装API以确保您的char UTF-8字符串不会被误认为是Windows上的ANSI(或其他代码管理的)字符串.例如,假定stdio.h
和iostream
库的文件名称是代码分段的,以及Win32 API的ANSI版本(例如,CreateWindowA).
这是使用UTF-8字符的GTK +的方法,但令人惊讶的是,使用UTF-16的QT(构建Linux KDE).
资源:
不过,它不会保护你免受"嘿,但Win32编辑控件不能处理我的unicode字符!" 问题,所以你仍然必须将该控件子类化以获得所需的行为(如果bug仍然存在)......
请参阅我的回答 std :: wstring VS std :: string for std::string
和std::wstring
.之间的完全区别.
归档时间: |
|
查看次数: |
10385 次 |
最近记录: |