Embarcadero C++ Builder中string类型的默认值是AnsiString吗?

4
我继承了一个旧的Borland C ++ Builder应用程序,现在我必须将其迁移到新的开发工具。建议使用Embarcadero C ++ Builder进行迁移,从我的初步测试来看,这似乎是一个相当平稳的过渡。
然而,我有一个问题,希望有一个简单的解决方案:
该应用程序解析大量文本文件。这些文件都是基于ANSI的,永远不会改变,因此输入和输出都是ANSI。我的主要问题是,在Embarcadero C ++中,类型string现在是UnicodeString,而不是Borland C ++ Builder中的AnsiString。
在这个应用程序中使用Unicode不是一个选项 - 它处理的文件都是ANSI格式的。修改代码以使用AnsiString(和类似的内容)是可行的,但我宁愿不这样做,因为它使用了大量的TStringList(和类似的内容)构造。
因此,我的问题是:是否有一个设置或编译器选项或其他东西,可以告诉Embarcadero使用System.AnsiString作为string的定义,而不是System.UnicodeString?
这可能是一个长期的解决方案,但RAD Studio XE(这是我借来做一些测试的较旧版本)文档说:“默认情况下,类型string现在是Unicode字符串”,这意味着这可以改变。然而,在当前版本(XE8)的文档中,这被重新表述了...

在这种情况下使用UnicodeString没有任何问题。UnicodeStringAnsiString都是模板类AnsiStringT的特化版本,其中模板参数是代码页。 - M.M
3个回答

6
我继承了一个旧的Borland C++ Builder应用程序,现在必须将其迁移到新的开发工具。建议使用Embarcadero C++ Builder。是的,它们实际上是同一产品。Borland创建了一个名为CodeGear的子公司来管理其开发人员工具(Delphi、C++Builder等),然后Embarcadero后来购买了CodeGear。 我的主要问题是,在Embarcadero C++中,类型string现在是UnicodeString而不是AnsiString(如在Borland C++ Builder中)。 小写字母s的string指的是STL的std :: string类,仍然基于char。您正在考虑C ++ Builder的System :: String别名,该别名现在映射到System :: UnicodeString而不是System :: AnsiString(该更改是在引入UnicodeString时在C ++ Builder 2009中进行的)。但是,AnsiString仍然存在,并且可以直接使用。 在此应用程序中使用Unicode不是选项-它所使用的文件是ANSI格式。那么就不要使用UnicodeString来处理它们。继续使用AnsiString即可。 修改代码以使用AnsiString(以及类似的内容)是可行的,但我宁愿不这样做,因为它使用了许多TStringList(和类似的)构造。那将是一个问题。大多数RTL现在只支持UnicodeString。因此,使用TStringList的代码必须重新编写,例如使用TList或std :: vector(除非代码正在利用TStringList ::(Comma | Delimited)Text属性,在这种情况下,您需要进行更大的重写)。但是,对于AnsiString解析代码,许多旧的基于AnsiString的RTL函数被移动到单独的System.AnsiStrings单元中,因此您可以将#include 添加到您的代码中以到达它们。 那么我的问题是:是否有设置、编译器选项或其他东西,我可以使用它来告诉Embarcadero使用System.AnsiString作为字符串的定义,而不是System.UnicodeString?

不可以。如果你考虑一下,实现这个功能对他们来说是一个重大的任务。需要为每个支持的操作系统平台准备RTL/VCL/FMX框架的多个副本,每个平台需要2个副本。很多内部代码都必须使用IFDEF处理Ansi/Unicode处理逻辑之间的差异。因此,这对他们来说不太可行或划算(特别是考虑到在移动操作系统平台上不支持AnsiString - 虽然有第三方补丁可用于重新启用它)。

这可能是一个不太可能的事情,但RAD Studio XE(我借来做一些测试的旧版本)文档中说“默认情况下,类型string现在是Unicode字符串”,这意味着可以更改它。

不行,无法更改。RTL/VCL/FMX框架现在是Unicode的。但这并不要求你的代码必须也是Unicode的。只有在需要直接与RTL/VCL/FMX交互的地方才需要使用Unicode。其余的代码可以继续使用AnsiString(甚至std::string)。


虽然不是我所期望的快速解决方案,但我知道这是一个很难实现的目标。尽管如此,你给出了一个非常好而且详细的答案!我现在更好地理解了问题,并且有足够的线索相信我可以轻松完成这个任务。所以谢谢你,Remy! - Boise

1

Delphi字符串是从1开始索引的(除了移动平台,它们默认为0索引,但有一个Delphi编译器指令可以更改)。RTL/VCL/FMX框架是用Delphi编写的,而不是C++。C++的System::AnsiString和System::UnicodeString类只是Delphi本地字符串类型的兼容包装器,因此它们必须使用相同的索引。 - Remy Lebeau

0

AnsiString可以轻松转换为UnicodeString。这是我处理转换的方法。旧的C++Builder 2007代码:

void __fastcall TFormVidya::lbEntData(TWinControl *Control, int Index, AnsiString &Data)
{
    if(FEntNameSto) {
        char *pc;
        int len=FEntNameSto->PeekValue(Index,&pc);
        Data.printf("DB %.*s",len,pc);
    } else Data.sprintf("MOCK %d!",Index);
}

转换为C++Builder XE2:

void __fastcall TFormVidya::lbEntData(TWinControl *Control, int Index, UnicodeString &Data)
{
    if(FEntNameSto) {
        char *pc;
        int len=FEntNameSto->PeekValue(Index,&pc);
        AnsiString astr;
        astr.printf("DB %.*s",len,pc);
        Data=astr;
    } else Data.sprintf(L"MOCK %d!",Index);
}

本质是将AnsiString分配给UnicodeStringData = astr;

此外,帮助页面ms-help://embarcadero.rs_xe2/libraries/System.UnicodeString.html(其中说“默认情况下,声明为字符串类型的变量是UnicodeString。”)也说:“尽管其名称是UnicodeString,但它可以表示ANSI字符集字符串和Unicode字符串。”,但我无法使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接