1

問題があるので、指を置くことができないようです。関数呼び出しから文字列(文字と数字を含むランダムコード)を収集し、TStringList変数に配置しようとしています。関連するコードは以下のとおりです。

テストを実行すると、文字列が一定時間繰り返され、新しい文字列が生成されます。コードが生成されるたびにsleep(xx)またはshowmessageコマンドを導入すると(以下の「編集」を参照)、メモにコピー/戻り、すべてが正常に見えます。'delay'を削除すると、関数から繰り返しが返されます。

TStringListに追加する関数の部分:

..

 AddToMemo:=TStringList.Create;
 AddToMemo.Clear;
 AddToMemo.Sorted:=False;
 for loop := 1 to totalamount do
  begin
   sResult:=MakeCode(charspercode, cbUpperLowerCase, cbAvoidChars, customchars);

   Sleep(50);
   // (or):
   //ShowMessage(sResult);

   // ^ If I leave a Sleep or ShowMessage in, I can see sResult just fine and
   //   program works fine - results in memo are correct as well. If I remove
   //   it, I get repeated entries.

   AddToMemo.add(sResult+IntToStr(loop));

 // If I remove "sResult+" from AddToMemo.add the ".add"
 // works - shows loop numbers in my updated memo
 // If left in, I see one code (1st one produced) and no
 // appended number at all in Memo produced.

  end;
Result:=AddToMemo; 
end;

編集:以下で説明するように、ShowMessageまたはSleep(xx)呼び出しを残して、.addの間に一時停止すると、正常に機能します。それを削除すると、最終的なtmemoに多数の重複エントリが表示されます。 編集: MakeCodeは、chars + numbers(A..Z a..z 0..9)の単一のランダムな文字列を返す関数です。それ自体で正常に動作します。

(回答2のために編集)

例外は現れませんでした。

したがって、sleep()を含めないと、500個の文字列が生成される可能性がありますが、それらはすべて繰り返しです。一定の時間が経過すると、変化します。スリープコマンドを増やすと、関数呼び出しからの繰り返しの量が減少します。スリープ前後(40); 関数から正しく表示されます。しかしもちろん、これには時間がかかり、受け入れられません。

MakeCode()の「根性」

function MakeCode(CharsPerCode: Integer; bULCase, bAvoidChars: Boolean; sCChars: String): String;


var
  i: integer;
  s: string;


begin
//(misc stuff here)

  begin
    randomize;
    s[0]:=chr(CharsPerCode);
    for i:=1 to CharsPerCode do
    repeat
      s[i]:=chr(random(128));
    until
    (s[i] in ['A'..'Z','a'..'z','0'..'9'])
  end;

Result:=s;
end;
4

3 に答える 3

4

これはの動作ですRandomize。乱数ジェネレータは、システムクロックの計算によって初期化されます。クイックループの各反復で呼び出すと、同じシードで初期化されます。そのため、aSleep(50)は結果を変えています。たとえば、文字列リストの作成を開始する前に、randomizeを1回呼び出します。

...
AddToMemo.Clear;
AddToMemo.Sorted:=False;
Randomize;            // <-- possibly here
for loop := 1 to totalamount do

...

function MakeCode(CharsPerCode: Integer; bULCase, bAvoidChars: Boolean; sCChars: String): 

...
  begin
//    randomize;      // <-- not here!
    s[0]:=chr(CharsPerCode);


以下の引用はDelphiのドキュメントからのものです:

ループ内のRandomizeの呼び出しとRandom関数の呼び出しを組み合わせないでください。通常、Randomizeは、Randomを呼び出す前に、一度だけ呼び出されます。

于 2011-07-17T19:56:25.187 に答える
0

もう少しコード、evtlを表示する必要があります。MakeCode。MakeCodeなしでsResultの定数文字列を使用して同じことを試みますが、同じようになりますか?次のようなものを試してください:

for loop := 1 to totalamount do
begin
  try
    sResult:=MakeCode(charspercode, cbUpperLowerCase, cbAvoidChars, customchars);
    AddToMemo.add(sResult+IntToStr(loop)); 
  except on e: exception do
    showmessage(e.message);
  end;
end;

例外はありますか?

于 2011-07-15T06:20:47.000 に答える
0

MakeCode()が実際に何を返しているかを確認しないと、メモやRTLでさえサブシーケンス文字をスキップする原因となる印刷不可能な制御文字(特にヌル文字)が含まれsResultていると思います。sResult

于 2011-07-14T21:47:02.677 に答える