書き込みに関する注意
Writeln(file, 'Result is: ', var1:8:2,' | ', var2:8:2,' |');
出力:
Result is: 4.50 | 0.67 |
Delphi は、 DecimalSeparatorを尊重せずに古い Pascal フォーマットを行っているようです。Writeln
これが、出力が使用.
され、以下の他のアプローチが使用される理由です,
(私はスペイン語版の Windows を使用しています)。
TStringBuilder
最新の Delphi バージョンでは、TStringBuilderは流暢なインターフェースのサポートにより、文字列連結のための洗練された方法を提供します。フォーマット機能は限られていますが、Format
フレーバーが含まれています (通常のFormat
関数として非常に便利ですが、型チェックがありません)。
sb := TStringBuilder.Create;
try
sb.Append('Result is: ').Append(var1).Append(' | ').Append(var2).Append(' |');
Memo.Lines.Add(sb.ToString);
sb.Clear;
sb.AppendFormat('Result is: %8.2f | %8.2f |', [var1, var2]);
Memo.Lines.Add(sb.ToString);
finally
sb.Free;
end;
出力:
Result is: 4,5 | 0,666666666666667 |
Result is: 4,50 | 0,67 |
挿入演算子
演算子のオーバーロードやクロージャーなどのトリックを使用して、 C++ ostream 挿入演算子を模倣することができます。
Memo.Lines.Add(stringout < 'My ' < 5 < ' cents' < soEndl < '2/3: ' < soPrec(4) < 2/3);
出力:
My 5 cents
2/3: 0,6667
あなたの例:
Memo.Lines.Add(
stringout
< 'Result is: ' < soWidth(8) < soPrec(2) < var1 < ' | '
< soWidth(8) < soPrec(2) < var2 < ' |'
);
出力:
Result is: 4,50 | 0,67 |
Delphi がクラスでの演算子のオーバーロードをサポートすると、実装がより簡潔になります。一方、演算子のオーバーロードにレコードを使用し、自動メモリ管理にインターフェイスを使用すると、うまくいきます。
type
PStringOut = ^TStringOut;
TStringOutManipulatorRef = reference to procedure(pso: PStringOut);
PStringOutInternalStorage = ^TStringOutInternalStorage;
TStringOutInternalStorage = record
Data: TStringBuilder;
Width, Precision: integer;
procedure ClearFormat; inline;
function GetFormatString(formatType: char): string;
end;
IStringOutInternal = interface
function TheStorage: PStringOutInternalStorage;
end;
TStringOutInternal = class(TInterfacedObject, IStringOutInternal)
strict private
Storage: TStringOutInternalStorage;
private
constructor Create;
function TheStorage: PStringOutInternalStorage;
public
destructor Destroy; override;
end;
TStringOut = record
private
Buffer: IStringOutInternal;
public
// insertion operator
class operator LessThan(const this: TStringOut; add: string): TStringOut;
class operator LessThan(const this: TStringOut; add: char): TStringOut;
class operator LessThan(const this: TStringOut; add: integer): TStringOut;
class operator LessThan(const this: TStringOut; add: double): TStringOut;
class operator LessThan(const this: TStringOut; manipulator: TStringOutManipulatorRef): TStringOut; inline;
// implicit conversion to string ("extraction" operator)
class operator Implicit(const this: TStringOut): string; inline;
end;
{ TStringOutInternalStorage }
procedure TStringOutInternalStorage.ClearFormat;
begin
Width := 0;
Precision := 0;
end;
function TStringOutInternalStorage.GetFormatString(formatType: char): string;
begin
Result := '%';
if Width > 0 then
Result := Result + IntToStr(Width);
if Precision > 0 then
Result := Result + '.' + IntToStr(Precision);
Result := Result + formatType;
end;
{ TStringOutInternal }
constructor TStringOutInternal.Create;
begin
inherited;
Storage.Data := TStringBuilder.Create;
end;
destructor TStringOutInternal.Destroy;
begin
Storage.Data.Free;
inherited;
end;
function TStringOutInternal.TheStorage: PStringOutInternalStorage;
begin
Result := @Storage;
end;
{ TStringOut }
class operator TStringOut.Implicit(const this: TStringOut): string;
begin
Result := this.Buffer.TheStorage.Data.ToString;
end;
class operator TStringOut.LessThan(const this: TStringOut; add: string): TStringOut;
begin
this.Buffer.TheStorage.Data.AppendFormat(this.Buffer.TheStorage.GetFormatString('s'), [add]);
this.Buffer.TheStorage.ClearFormat;
Result.Buffer := this.Buffer;
end;
class operator TStringOut.LessThan(const this: TStringOut; add: char): TStringOut;
begin
this.Buffer.TheStorage.Data.Append(add);
this.Buffer.TheStorage.ClearFormat;
Result.Buffer := this.Buffer;
end;
class operator TStringOut.LessThan(const this: TStringOut; add: integer): TStringOut;
begin
this.Buffer.TheStorage.Data.AppendFormat(this.Buffer.TheStorage.GetFormatString('d'), [add]);
this.Buffer.TheStorage.ClearFormat;
Result.Buffer := this.Buffer;
end;
class operator TStringOut.LessThan(const this: TStringOut; add: double): TStringOut;
var
s: PStringOutInternalStorage;
begin
s := this.Buffer.TheStorage;
if s.Precision <> 0
then s.Data.AppendFormat(s.GetFormatString('f'), [add])
else s.Data.AppendFormat(s.GetFormatString('g'), [add]);
s.ClearFormat;
Result.Buffer := this.Buffer;
end;
class operator TStringOut.LessThan(const this: TStringOut; manipulator: TStringOutManipulatorRef): TStringOut;
begin
Result := this;
manipulator(@Result);
end;
{ Manipulators }
function soEndl: TStringOutManipulatorRef;
begin
Result :=
procedure(pso: PStringOut)
begin
pso.Buffer.TheStorage.Data.AppendLine;
pso.Buffer.TheStorage.ClearFormat;
end;
end;
function soWidth(value: integer): TStringOutManipulatorRef;
begin
Result :=
procedure(pso: PStringOut)
begin
pso.Buffer.TheStorage.Width := value;
end;
end;
function soPrec(value: integer): TStringOutManipulatorRef;
begin
Result :=
procedure(pso: PStringOut)
begin
pso.Buffer.TheStorage.Precision := value;
end;
end;
{ The stringout "constructor" }
function stringout: TStringOut; inline;
begin
Result.Buffer := TStringOutInternal.Create;
end;