12

を使用writelnすると、数値をテキスト行にフォーマットできます。

var 
  file: text;
  mystring: string;

begin
  writeln(file,'Result is: ', var1:8:2,' | ', var2:8:2,' |');
end;

同様の結果を処理するDelphiでの同様の使いやすい手順はありますか

  _format_string(mystring, 'Result is: ', var1:8:2,' | ', var2:8:2,' |');

ありがとうございました。

4

4 に答える 4

17

Format次の関数を使用します。

mystring := Format('The image dimensions are %d × %d.', [640, 480]);
于 2013-08-01T12:31:37.077 に答える
12

技術的には、答えは「はい」です。しかし、それはお勧めできません。

System.TTextRec型に基づいて、独自のテキスト ファイル デバイス ドライバを作成できます。

過去に (特に Turbo Pascal の時代に) デバッグ目的でこれを行ったことがあります。これは大変な作業であり、特別な手順を作成する必要があり、必ずブロック内のを使用してファイルをMyAssign閉じる必要があります。面倒ですが、実行可能です。TextTTextRectry..finally

Andreas Rejbrand で説明されているように、より簡単な代替手段はFormat 関数を使用することです。

を使用することの優れた点は、フォーマット文字列Formatを使用して、やその内部などをパラメータ化するだけでなく、通常は値を提供するようなパラメータとしても使用できることです。widthprecisionFormat String

質問の例のように、 a widthof 8 と a of 2 の使用に非常に近づくことができます。precision

たとえば、ドキュメントを引用するには:

Format ('%*.*f', [8, 2, 123.456]);

次と同等です。

Format ('%8.2f', [123.456]);

Formatこれは、との見過ごされがちな機能ですFormat Strings

于 2013-08-01T15:29:34.663 に答える
6

Jeroen はそれを推奨していませんが、私は約 1 年前にこのようなことをしました - やり方を学ぶためだけに。これはコードです:

type
  TTextFile = class
  private type
    TTextRecHelper = record helper for TTextRec
    public
      function GetTextFile: TTextFile;
      procedure SetTextFile(const Value: TTextFile);
      property TextFile: TTextFile read GetTextFile write SetTextFile;
    end;
  private var
    FBuilder: TStringBuilder;
    class function TextClose(var F: TTextRec): Integer; static;
    class function TextIgnore(var F: TTextRec): Integer; static;
    class function TextInput(var F: TTextRec): Integer; static;
    class function TextOpen(var F: TTextRec): Integer; static;
    class function TextOutput(var F: TTextRec): Integer; static;
    procedure AppendString(const Value: string);
    procedure AssignFile(var F: Text);
  public
    var F: Text;
    constructor Create;
    destructor Destroy; override;
    function ToString: string; override;
  end;

constructor TTextFile.Create;
begin
  inherited Create;
  FBuilder := TStringBuilder.Create();
  AssignFile(F);
  Rewrite(F);
end;

destructor TTextFile.Destroy;
begin
  Close(F);
  FBuilder.Free;
  inherited Destroy;
end;

procedure TTextFile.AppendString(const Value: string);
begin
  FBuilder.Append(Value);
end;

procedure TTextFile.AssignFile(var F: Text);
begin
  FillChar(F, SizeOf(F), 0);
  with TTextRec(F)do
  begin
    Mode := fmClosed;
    BufSize := SizeOf(Buffer);
    BufPtr := @Buffer;
    OpenFunc := @TextOpen;
    TextFile := Self;
  end;
end;

class function TTextFile.TextClose(var F: TTextRec): Integer;
begin
  Result := 0;
end;

class function TTextFile.TextIgnore(var F: TTextRec): Integer;
begin
  Result := 0;
end;

class function TTextFile.TextInput(var F: TTextRec): Integer;
begin
  F.BufPos := 0;
  F.BufEnd := 0;
  Result := 0;
end;

class function TTextFile.TextOpen(var F: TTextRec): Integer;
begin
  if F.Mode = fmInput then
  begin
    F.InOutFunc := @TextInput;
    F.FlushFunc := @TextIgnore;
    F.CloseFunc := @TextIgnore;
  end else
  begin
    F.Mode := fmOutput;
    F.InOutFunc := @TextOutput;
    F.FlushFunc := @TextOutput;
    F.CloseFunc := @TextClose;
  end;
  Result := 0;
end;

class function TTextFile.TextOutput(var F: TTextRec): Integer;
var
  AStr: AnsiString;
begin
  SetLength(AStr, F.BufPos);
  Move(F.BufPtr^, AStr[1], F.BufPos);
  F.TextFile.AppendString(string(AStr));
  F.BufPos := 0;
  Result := 0;
end;

function TTextFile.ToString: string;
begin
  Close(F);
  result := FBuilder.ToString;
  Rewrite(F);
end;

function TTextFile.TTextRecHelper.GetTextFile: TTextFile;
begin
  Move(UserData[1], Result, Sizeof(Result));
end;

procedure TTextFile.TTextRecHelper.SetTextFile(const Value: TTextFile);
begin
  Move(Value, UserData[1], Sizeof(Value));
end;

あなたの質問に従ってそれを使用する方法の例:

  tf := TTextFile.Create;
  try
    Writeln(tf.F, 'Result is: ', var1:8:2,' | ', var2:8:2,' |');
    Caption := tf.ToString;
  finally
    tf.Free;
  end;
于 2013-08-01T17:12:43.593 に答える
2

書き込みに関する注意

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;
于 2013-08-01T21:20:25.513 に答える