开发者

TStringList .add produces duplicates from random function

开发者 https://www.devze.com 2023-03-20 21:45 出处:网络
Having a problem I can\'t seem to put my finger on. I am trying to gather strings (random code with letters and numbers) from a function call and place into my TStringList variable. Relevant code is b

Having a problem I can't seem to put my finger on. I am trying to gather strings (random code with letters and numbers) from a function call and place into my TStringList variable. Relevant code is below.

If I run a test, the strings repeat for a given amount of time then a new one is produced. If I introduce a sleep(xx) or showmessage command to happen after each time a code is produced (see 'edits' below) it copies/returns to memo fine and everything looks fine. If I remove the 'delay' I get repeats from function again.

The part of function to add to TStringList:

..

 AddToMemo:=TStringList.Create;
 AddToMemo.Clear;
 AddToMemo.Sorted:=False;
 for loop := 1 to totalamount do
  begin
   sResult:=MakeCode(charsp开发者_StackOverflow中文版ercode, 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;

Edit: As I mention below if I leave a ShowMessage or Sleep(xx) call in to pause between .add's, it works fine. If I remove it, I get a bunch of duplicate entries in final tmemo. Edit: MakeCode is a function to return a single random string of chars+numbers (A..Z a..z 0..9). It works fine on it's own.

(Edit for Answer 2)

No exceptions showed up.

So if I do not include sleep() it may generate 500 strings but they are all repeats; after a given amount of time it does change. The amount of repeats from the function call decreases as I increase sleep command. At around Sleep(40); it shows up correctly from function. But of course this is time consuming and unacceptable.

The 'guts' of 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;


This is a behavior of Randomize. The random number generator is initialized by a calculation on the system clock. If you call it in each iteration in a quick loop, it is initialized with the same seed. That's why a Sleep(50) is changing the outcome. Call randomize for once, for instance, before starting to populate the string list.

...
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);


The below quote is from the Delphi documentation:

Do not combine the call to Randomize in a loop with calls to the Random function. Typically, Randomize is called only once, before all calls to Random.


Without seeing what MakeCode() is actually returning in sResult, my guess would be that sResult contains non-printable control characters (null characters in particular) that cause the Memo or even the RTL to skip subsequence characters.


You need to show some more Code, evtl. MakeCode. I would try the same with a constant String in sResult without MakeCode, do you get the same? try something like:

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;

Do you get any exceptions?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号