AnsiString 作为 Embarcadero C++ Builder 中类型字符串的默认值?

AnsiString as default for type string in Embarcadero C++ Builder?

我继承了一个旧的 Borland C++ Builder 应用程序,现在我必须将其迁移到新的开发工具。建议的方法是使用 Embarcadero C++ Builder,从我最初的测试来看,它似乎是一个相当平稳的过渡。

但是我确实有一个问题,我希望有一个简单的解决方案:

应用程序解析大量文本文件。这些文件都是基于 ANSI 的,并且永远不会改变,所以它是 ANSI 输入和 ANSI 输出。我遇到的主要问题是,对于 Embarcadero C++,类型 string 现在是 UnicodeString 而不是 AnsiString(就像在 Borland C++ Builder 中一样)。

不能在此应用程序中使用 Unicode - 它使用的文件是 ANSI 格式的。修改代码以使用 AnsiString(和类似)是可行的,但我宁愿不这样做,因为它使用了很多 TStringList(和类似)构造。

所以我的问题是:是否有设置或编译器选项或我可以用来告诉 Embarcadero 使用 System.AnsiString 作为 string 的定义而不是 System.UnicodeString 的东西?

这可能是一个远景,但 RAD Studio XE(这是我借来进行一些测试的旧版本)文档说“默认string 类型现在是一个 Unicode 字符串”,这意味着可以更改它。但是,当前版本 (XE8) 的文档中对此进行了改写,因此...

可能我有坏消息。他们总是谈论迁移,而不是快速修复。

http://docwiki.embarcadero.com/RADStudio/XE3/en/Enabling_Applications_for_Unicode http://docwiki.embarcadero.com/RADStudio/XE3/en/Enabling_C%2B%2B_Applications_for_Unicode

嗯...我讨厌 Borland 中的 Strings。到底是谁想出从 1 而不是 0 给它们编号的?!

I have inherited an old Borland C++ Builder application which I now must migrate to a new development tool. The suggested way to go is with Embarcadero C++ Builder

是的。它们实际上是同一种产品。 Borland 创建了一家名为 CodeGear 的子公司来管理其开发工具(Delphi、C++Builder 等),然后 Embarcadero 后来收购了 CodeGear。

The main problem I have is that with Embarcadero C++, the type string is now a UnicodeString instead of an AnsiString (as it was in Borland C++ Builder).

string(小写s)指的是STL的std::stringclass,仍然是基于char的。您正在考虑 C++Builder 的 System::String 别名,它现在映射到 System::UnicodeString 而不是 System::AnsiString(该更改是在 C++Builder 2009 中进行的,当时 UnicodeString被介绍)。不过AnsiString还是存在的,可以直接使用

Using Unicode in this application is not an option - the files it work with are ANSI formatted.

那就不要用UnicodeString来处理它们。继续使用 AnsiString

Modifying the code to use AnsiString (and similar) is doable, but i'd rather not since it uses a lot of TStringList (and similar) constructs.

另一方面,这会是个问题,是的。大多数 RTL 现在只支持 UnicodeString。所以使用 TStringList 的代码将不得不重写,例如使用 TList<AnsiString>std::vector<AnsiString> 代替(除非代码使用 TStringList::(Comma|Delimited)Text 属性,在这种情况下你有一个更大的重写)。但是,对于 AnsiString 解析代码,许多基于 AnsiString 的旧 RTL 函数已移至单独的 System.AnsiStrings 单元,因此您可以将 #include <System.AnsiStrings.hpp> 添加到代码中以达到他们。

So my question is: Is there a setting or compiler option or something that I can use to tell Embarcadero to use System.AnsiString as definition for string instead of System.UnicodeString?

没有。如果您考虑一下,这将是他们实施的一项重大任务。 RTL/VCL/FMX 框架的多个副本,每个受支持的 OS 平台 2 个。很多内部代码必须进行 IFDEF 处理 Ansi/Unicode 处理逻辑之间的差异。因此,他们这样做并不可行或不划算(而且在这一点上为时已晚,特别是考虑到 AnsiString 在移动 OS 平台上不受支持——尽管有第 3 方补丁可用于重新启用它)。

This is probably a long-shot, but the RAD Studio XE (which is the older version that I have borrowed to make a few tests) documentation says "by default, the type string is now a Unicode string", which implies that this can be changed.

不,不能更改。 RTL/VCL/FMX 框架现在是 Unicode。但这并不要求您的代码也必须是 Unicode。仅在您需要直接与 RTL/VCL/FMX 互动的地方。您的其余代码可以根据需要继续使用 AnsiString(甚至 std::string)。

AnsiString-s可以很容易地转换成UnicodeString-s。这就是我处理转换的方式。旧 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到一个UnicodeString的赋值:Data=astr;.

此外,帮助页面 ms-help://embarcadero.rs_xe2/libraries/System.UnicodeString.html(上面写着 "By default, variables declared as type String are UnicodeString." 的那个) ,还说“尽管它的名字,UnicodeString 可以表示 ANSI 字符集字符串和 Unicode 字符串。”,但我无法使用它。