Hi everyone. I have an app that converts values in a text file (cnc gcode) displayed in a Richedit. The program works ok except that every time the program is run there is a noticeable drop in speed. Also the larger the file the worse the problem. i.e. 61000 lines take 6mins 30s and 87000 take 13mins 10s.
I suspect a memory leak somewhere, however I don't really understand what they are, which part of the code is responsible and what to do about it.
The 'guts' of the program are shown below with the two main functions. (thanks to whosrdaddy)
If someone could point me in the right direction I would appreciate it.
Thanks
Beginner (as if you hadn't guessed!) using the free Turbo Delphi.
I suspect a memory leak somewhere, however I don't really understand what they are, which part of the code is responsible and what to do about it.
The 'guts' of the program are shown below with the two main functions. (thanks to whosrdaddy)
If someone could point me in the right direction I would appreciate it.
Thanks
Beginner (as if you hadn't guessed!) using the free Turbo Delphi.
Code:
procedure TForm1.btnRunClick(Sender: TObject);
var
I, LineCount: Integer;
OldValue, Line : String;
Radius, Diameter : Extended;
begin
If HasRun = 1 Then
begin
Beep;
Showmessage('Code is already converted. You must reopen file to convert with another setting.');
exit;
end
else
Radius := StrToFloat(EditRadius.Text); // Get the Stock radius from user.
Diameter := StrToFloat(EditRadius.Text) * 2; // Convert to Diameter
Linecount := Richedit1.Lines.count; // save the amount of lines to variable 'Linecount'
btnRun.Caption := 'Calculating'; // Change caption of Run button.
for i := 0 to Richedit1.Lines.Count-1 do //from line 0 to total number of lines less 1 do the following.
begin
Line := Richedit1.Lines[i]; // load current line which is a string to variable 'Line'
//X to B conversion type
if radioButton1.Checked = true then
if ansicontainsstr (Line,'X') then
if HasUnwanted(['Y','Z','F','H','D','S','M'],Line) then
begin
OldValue := GetXMove(Line);
NewValue := 'B' + Convert(OldValue,Radius);
end
else
begin
OldValue := AnsiMidstr(Line,(ansipos('X',Line)),maxint);
NewValue := 'B' + Convert(OldValue,Radius);
end;
//Y to A conversion type
if radioButton2.Checked = true then
if ansicontainsstr (Line,'Y') then
if HasUnwanted(['Z','F','H','D','S','M'],Line) then
begin
OldValue := GetYMove(Line);
NewValue := 'A' + Convert(OldValue,Radius);
end
else
begin
OldValue := AnsiMidstr(Line,(ansipos('Y',Line)),maxint);
NewValue := 'A' + Convert(OldValue,Radius);
end;
//X to A conversion type
if radioButton3.Checked = true then
if ansicontainsstr (Line,'X') then
if HasUnwanted(['Y','Z','F','H','D','S','M'],Line) then
begin
OldValue := GetXMove(Line);
NewValue := 'A' + Convert(OldValue,Radius);
end
else
begin
OldValue := AnsiMidstr(Line,(ansipos('X',Line)),maxint);
NewValue := 'A' + Convert(OldValue,Radius);
end;
//Y to B conversion type
if radioButton4.Checked = true then
if ansicontainsstr (Line,'Y') then
if HasUnwanted(['Z','F','H','D','S','M'],Line) then
begin
OldValue := GetYMove(Line);
NewValue := 'B' + Convert(OldValue,Radius);
end
else
begin
OldValue := AnsiMidstr(Line,(ansipos('Y',Line)),maxint);
NewValue := 'B' + Convert(OldValue,Radius);
end;
NewValue := AnsiReplaceStr(Line,(OldValue), (NewValue)); //Swap the old X or Y value with the new A or B value.
Richedit1.Lines[i] := NewValue; // write converted line back into memo
Progressbar1.Position := Trunc(i/Linecount*105);
end;
//Apply comments to the start of the converted program.
richedit1.selstart := 0;
richedit1.seltext := '(PROGRAM CONVERTED WITH WRAPPER)'+#13#10;
richedit1.seltext := '('+ DateTimeToStr(Now) + ')'+#13#10;
if radioButton1.Checked = true then
begin
richedit1.seltext := '(X AXIS MOVES CONVERTED TO ROTATIONAL B AXIS)'+#13#10;
end;
if radioButton2.Checked = true then
begin
richedit1.seltext := '(Y AXIS MOVES CONVERTED TO ROTATIONAL A AXIS)'+#13#10;
end;
if radioButton3.Checked = true then
begin
richedit1.seltext := '(X AXIS MOVES CONVERTED TO ROTATIONAL A AXIS)'+#13#10;
end;
if radioButton4.Checked = true then
begin
richedit1.seltext := '(Y AXIS MOVES CONVERTED TO ROTATIONAL B AXIS)'+#13#10;
end;
if i = Linecount then
begin
if radioButton1.Checked = true then
showmessage(' X to B axis'+#13#10 +'conversion complete.');
if radioButton2.Checked = true then
showmessage(' Y to A axis'+#13#10 +'conversion complete.');
if radioButton3.Checked = true then
showmessage(' X to A axis'+#13#10 +'conversion complete.');
if radioButton4.Checked = true then
showmessage(' Y to B axis'+#13#10 +'conversion complete.');
end;
btnRun.Caption := 'Conversion Complete';
HasRun := 1; //Setting HasRun variable to 1 prevents converting the code twice.
EditRadius.Enabled := False; // Code is already converted so can't be run again.
end;
function GetXMove(Str : string) : String;
var
Index : Integer;
Ch : Char;
StrLen, XPos : Integer;
NumStr : string;
begin
Result := ''; // Make sure result is empty first.
StrLen := Length(Str); // Get the length of the string passed to the function.
if StrLen = 0 then Exit; // Sanity Check
Index := 0;
NumStr := '';
XPos := ansipos('X',Str)-1; // get position of X in the string
Index := XPos; // Give X position to Index.
repeat
Inc(Index); // Increment Index. Move along the string 1 position every repeat
Ch := Str[Index]; // At every position get that character and pass it to variable ch
case Ch of // valid char. Ch is checked against wanted chars.
'X','-','0'..'9','.' : NumStr := NumStr + Ch; //every wanted char is added to string held in variable 'NumStr'
else
begin
Result := NumStr;
Index := MaxInt;
end;
end;
until
Index >= StrLen;
end;
Function Convert (Value:string; var radius : extended) :string;
var
Numbers, angle: Extended;
formated: String;
begin
result := '';
numbers := strtofloat (ansimidstr (value, 2, maxint));
Angle := (numbers)*180/Pi/(Radius);
Formated := Format('%.3f', [Angle]); //Format angle to 3 decimal places.
Result := Formated;
end;