1

みんなおはよう。

私は現在、十分に単純であると確信している何かを理解しようとしていますが、実際にうまくいくには半分の作業であることが証明されています.

さまざまなファイルを別の場所に移動することで、ドライブの使用を最小限に抑えるように設計されたプロジェクトに取り組んでいます。int64移動する可能性のあるファイルのファイル サイズを含む値の配列 (0..12) を取得しました。配列は、予測される最大のファイル サイズから予測される最小のファイル サイズまでの順序で並べられます。また、これらのファイルの名前を別の配列 ( としてWoWDataも知られる 、[0..12]) に保存しました。次に、「インストール サイズ」と「目的のサイズ」を取得しました。

私の仕事は、ファイルサイズの配列を調べて、<=希望のサイズ。

これは、私が使用しようとしてきたサンプル コード (Delphi/Firemonkey) です。このような作業を行う方法を理解しようとすると混乱するので、多くの問題が発生することは間違いありません。

Global Vars;
    _WoWDataFileSize : Array [0..12] of Int64;
    // "TBWoWDir" is a TTrackBar (Firemonkey)

var
  TotalSize, ReqSize, DiffSize, CurDiff : Int64;
  i : Integer;
begin
  // Set up initial values to work with
  ReqSize := Round(TBWoWDir.Value); // Requested Size
  TotalSize := Round(TBWoWDir.Max); // Actual installation size
  CurDiff := 0; // Assume as "Current Difference in size"

  // Calculate difference between install and requested size
  DiffSize := TotalSize - ReqSize; // This calculates correctly

// The below is what i'm struggling with
  repeat
    for i := Low(_WoWDataFileSize) to High(_WoWDataFileSize) do
      begin
        CurDiff := ReqSize - _WoWDataFileSize[i];
      end;
  until CurDiff <= ReqSize;
end;

repeat .. untilループなしでループだけを使用してみましたforが、もう一度、それを理解しようとしているときに混乱しすぎています。


例を挙げましょう。_WoWDataFileSize[0]それが 200 で、_WoWDataFileSize[1]~まで_WoWDataFileSize[12]が配列インデックスと同じ値であると仮定しましょう(例: _WoWDataFileSize[6]= 6、_WoWDataFileSize[8]= 8 など)。

150 の値 (200 - 12 - 11 - 10 - 9 - 8またはArray[0] - Array[12] - Array[11] - Array[10] - Array[9] - Array[8]配列による) を計算し、この要件を満たすために移動する必要があるファイルのリストを配列から取得しWoWDataたい場合、どのようにルーチンを記述しますか?

で指定された動的なユーザー要求サイズに向けて作業しているため、150 は任意の数値に置き換えることができますTBWoWDir.Value

Whileループを実行してセットアップを使用する必要があるかもしれないと考えていi := i+1ます。現実的には、一度に配列内の値を 1 つ取り出して、その都度、必要な値以下かどうかを確認するようにハードコーディングすることができます。項目ごとに 2 ~ 3 行になります (したがって、合計 24 ~ 36 行) ですが、これは維持するのが面倒であり、最適ではありません。ループでそれがどのように行われるかを見ることに興味があります。通常、ループに問題はありませんが、これは私にとって標準的なものではありません。

4

3 に答える 3

1
curdiff:= 0;
i:= Low(_WoWDataFileSize) - 1;
while (curdiff <= reqsize) and (i < High(_WoWDataFileSize)) do
 begin
  inc (i);
  curdiff:= curdiff + _WoWDataFileSize[i];
 end;

ループの最後で、必要なサイズの縮小を達成したか、配列全体を反復処理しました。

于 2012-10-17T06:08:16.490 に答える
1

それはあなたのコードに2行だけ欠けている私見です:o)

CurDiff := ReqSize;
// repeat
  for i := Low(_WoWDataFileSize) to High(_WoWDataFileSize) do
    begin
      CurDiff := CurrDiff - _WoWDataFileSize[i];
      if CurDiff <= ReqSize then break; // breaks the for..to loop
    end;
// until CurDiff <= ReqSize;

編集繰り返しの必要はありません...ループまで

しかし、私見では、どのファイルが一致するかを保存せずにサイズを数えるだけではあまり役に立ちません。したがって、CustomObject と Lists (ジェネリックに感謝) を使用すると、非常に簡単になります。

type
  TFileObject = class
  private
    FName : string;
    FSize : Int64;
  public
    constructor Create( AName : string; ASize : Int64 );
  published
    property Name : string read FName;
    property Size : Int64 read FSize;
  end;

procedure MoveFileObject(AMaxSize : Int64; ASrcList, ATarList : TList<TFileObject> );
var
  LItem : TFileObject;
  LSize : Int64;
begin
  LSize := 0;
  for LItem in ASrcList do
  begin
    if LSize + LItem.Size <= AMaxSize then
      begin
        LSize := LSize + LItem.Size;
        ATarList.Add( LItem );
      end;
  end;
end;
于 2012-10-17T06:37:21.010 に答える
0

回答してくれた皆さんのおかげで、どこが間違っていたのかがわかりました。最初の質問で計算していたとき、値の除算を説明するのを忘れていました( にライブバインドされているため、バイトでTBWoWDir.Valueはなく MB を表示するためですTLabel.textが、実際のサイズは割り当て前に分割されていましたTBWoWDir.Max)。

No'am Newman による回答からのいくつかの微調整のおかげで、私は自分でこれを理解することができました。これが、私が求めていた(またはそれにはるかに近い)結果を得た方法です。

Global Vars;
    _WoWDataFileSize : Array [0..12] of Int64;
Global Const;
    _WoWData : Array [0..12] of String;
    // "TBWoWDir" is a TTrackBar (Firemonkey)

[...]
var
  ReqSize : int64;
  DiffSize, CurDiff : Int64;
  i, ii : Integer;
  FilesTot : Integer;
  FILESMSG : String;
begin
  // Set up initial values to work with
  ReqSize := Round(TBWoWDir.Value) * 1024 * 1024; // Requested Size - Multiplied from formatting
  TotalSize := Round(TBWoWDir.Max) * 1024 * 1024; // Actual installation size - Multiplied from formatting

  DiffSize := TotalSize - ReqSize; // Calculate Difference
  CurDiff := 0; // Reset Current Difference
  i := -1; // Reset i
  repeat
    inc (i); // Increment i
    CurDiff := CurDiff + _WoWDataFileSize[i]; // Add current array item file size to CurDiff
  until (CurDiff >= (DiffSize)) or (i >= 12); // Repeat until we reach ideal size or the end of the array

  // Calculate which array item we stopped at
  for ii := 0 to i do // use i from previous loop as the max
  begin
    FILESMSG := FILESMSG + 'File: ' + WoWData[ii] +
                           ' | Size: ' + IntToStr(_WoWDataFileSize[ii])+' '#13#10;
    FilesTot := FilesTot + _WoWDataFileSize[ii];
  end;

  // Show Message providing details
  ShowMessage('CurDiff:' + IntToStr(CurDiff div 1024 div 1024) +
              ' | DiffSize: ' + IntToStr(DiffSize div 1024 div 1024) +
              ' | Array i: ' +
              IntToStr(i) +#13#10+
              'Difference between CurDiff and DiffSize: '+ IntToStr(((DiffSize div 1024 div 1024) - (CurDiff div 1024 div 1024)))+#13#10#13#10+
              'File Details' +#13#10#13#10+
              FilesMsg +#13#10#13#10+
              'Total Size: ' + IntToStr(FilesTot));
end;

ShowMessageコードは、どのファイルをコピーする必要があるかを教えてくれます (そのため、ファイルをコピーするためにコードを変更することはそれほど難しくありません) ShowMessage。値は正しく返されています。他の多くの人もそうしていると確信しています)。

于 2012-10-17T17:31:17.593 に答える