0

i want to get value from two file .txt, one file contain different dimension matrix with other

i have try this code:

  procedure TfrmJST.ParseDelimited(const S1: TStrings; const Value: String; const Delimiter: String);
    var
      dx,cx: integer;
      ns,ms: String;
      txt: string;
      delta,teta: integer;

   procedure TfrmJST.ParseDelimited(const S1: TStrings; const Value: String; const Delimiter: String);
var
  dx,cx: integer;
  ns,ms: String;
  txt: string;
  delta,teta: integer;

    begin
     Col := 1;
     Delta := Length(Delimiter);
     Txt := Value+Delimiter;;
     begin
      while Length(Txt) > 1 do
      begin
        Dx := Pos(Delimiter, Txt);
        Ns := Trim(Copy(Txt, 1, Dx-1));
    //    S1.Add('#'+Ns+'*');             //only needed for testing
        if Ns <> '' then
        begin
          Matrix[Row,Col] := StrToFloat(Ns);    //for first matrix
          Inc(Col);
        end;
        Txt := Copy(Txt, Dx+Delta, MaxInt);
      end;
     end;



     Col := 1;
     teta := Length(delimiter);
     txt := value+delimiter;
     begin
      while Length(txt) > 1 do
      begin
        cx := Pos(delimiter, txt);
        ms := Copy(txt, 1, cx-1);
        if ms <> '' then
          begin
          ref[Row,Col] := StrToFloat(ms);    ///for 2nd matrix

          Inc(Col);
          end;
          txt := Copy(txt, cx+teta, MaxInt);
      end;
     end;
    end;

and this is initialize of matrix:

private
    { Private declarations }
    Row, Col: integer;
    Matrix: array[1..140,1..141] of double;
     Ref: array[1..2,1..140] of double ;

this is the implementation:

begin
  Temp := TStringList.Create;
  MemoSL:= TStringList.Create ;
  Temp.LoadFromFile('trainer.txt');
  Row := 1;
  for I := 0 to Temp.Count-1 do
  begin
    ParseDelimited(MemoSL, Trim(Temp.Strings[I]), ' ');
    Inc(Row); //stackoverflow error in this line
  end;
  Temp.Free;

 //parsing second matrix
  TempList := TStringList.Create;
  Templist.LoadFromFile('refbaru.txt');
  row := 1;
  for J := 0 to Templist.Count-1 do
  begin
 T := Templist[J];
 ParseDelimited(Memo1.Lines, T, ' ');
  Inc(row);
  end;
  Templist.Free;

i tried that code but give me error, the error was stackoverflow error in line 'inc(row)' that process first matrix. and while i gave comment out at the second function that process 2nd matrix, Temp[i] only returns 2 rows of matrix[140x141]. does it mean the code can't process two different file? and why it only return two rows of the matrix? anyone can help me?

sephtian
  • 445
  • 2
  • 11
  • 23
  • Ok, parseDelimited is back. what is the error? And it looks like unfinished code. – Hendra Aug 09 '12 at 07:02
  • i have edited the code. the error was in line inc(row) in code that proccess first matrix. do you know why? – sephtian Aug 09 '12 at 07:08
  • 2
    Do we have to guess what the error was? Any reason why you won't tell us? Do you think it's more fun for us if we have limited information? The fact that these details don't matter to you is the main problem you have. I suspect that you don't even read the error message yourself. Read them and learn how to interpret them. – David Heffernan Aug 09 '12 at 07:11
  • the error was stackoverflow error in line 'inc(row)' that process first matrix – sephtian Aug 09 '12 at 07:14
  • That seems pretty unlikely, but please edit the question to contain that information. Don't make everyone ferret through comments to find useful info. – David Heffernan Aug 09 '12 at 07:18
  • I don't see how Inc(Row) could result in stack overflow. – David Heffernan Aug 09 '12 at 07:55

2 Answers2

1
while Length(Txt) > 1 do
begin
  Dx := Pos(Delimiter, Txt);
  Ns := Trim(Copy(Txt, 1, Dx-1));
  //    S1.Add('#'+Ns+'*');             //only needed for testing
  if Ns <> '' then
  begin
    Matrix[Row,Col] := StrToFloat(Ns);    //for first matrix
    Inc(Col);
  end;
  Txt := Copy(Txt, Dx+Delta, MaxInt);
end;

Looking at this piece of code I see the posibility of an endless loop: what happens if there is no Delimiter found? It will keep running and forever increase your 'col' value. Make sure to have a condition to stop your while loop if no delimeter is found.

Pieter B
  • 1,874
  • 10
  • 22
  • Calling a function/procedure does using memory from the stack, and having infinite loop is a way to chew up all available memory allocated for stack. – Hendra Aug 09 '12 at 07:54
  • @sephian step away from it a bit. Take a piece of paper and write out (without using code) what your program is supposed to do. Get back to the logic and go step by step through what you are doing and what the result should be. Make a diagram. – Pieter B Aug 09 '12 at 07:59
  • i want to process two diferent matrix in two file txt. trainer.txt contain of 140x141 dimension matrix. refbaru.txt contain of 2x140 dimension matrix. the matrix was splited with space between each record. i just want to move trainer.txt to matrix[i,j], and refbaru.txt to ref[i,j] – sephtian Aug 09 '12 at 08:11
  • I'd say, make a little testcase with your own matrix: a 3x3 matrix. This way you can easily make your testdata and check to see if it works on a small scale, once you get that then start with the 140x141 one. – Pieter B Aug 09 '12 at 08:15
  • i have tried it. i'd using 10x10 and 2x10 matrix and it can ran successfully. – sephtian Aug 09 '12 at 08:18
  • i think its because i using one procedure i two process. do you have any idea how to solve this? – sephtian Aug 09 '12 at 08:35
  • @Hendra No that's incorrect. Calling a procedure creates a new stack frame for that procedure, but when that procedure returns, the stack frame is destroyed. So an infinite loop will not lead to stack overflow. Unterminated recursion leads to stack overflows, but not a non-terminating while loop. – David Heffernan Aug 09 '12 at 08:41
  • Anyway, if there was an endless loop here then there would be an access violation. So whilst this answer may have identified a bug, it doesn't seem to address the main thrust of the question. – David Heffernan Aug 09 '12 at 09:00
1

It is pointless to look for a specific stack overflow error when many ordinary errors already exist.

If your code is clean programmed and it is still stack overflow, then of course, is time to look deeper into the code.
But first ! As long as you can see obvious errors, you should remove them.

  • 1.) "Row" used in the same procedure on a 140 dimension array and on a only 2 dimension array. How can that work ?

Matrix: array[1..140,1..141] of double;
Ref: array[1..2,1..140] of double ;
File 'trainer.txt' 140 Lines
File 'refbaru.txt' 2 Lines.

for I := 0 to Temp.Count-1 do // 140 lines
// ParseDelimited() will only run properly if Row < 3 
// remember -> Ref: array[1..2,1..140])
// if Row > 2 , with Ref[Row,Col] := , 137 times data is overwritten.

   procedure ParseDelimited(MemoSL, Trim(Temp.Strings[I]), ' ');
      ....
      Matrix[Row,Col] := StrToFloat(Ns);
      ....
      Ref[Row,Col] := StrToFloat(ms); 
      ....
   end;
Inc(Row);
end;
  • 2.) If you run the second loop with refbaru.txt and the two arrays are present together in the procedure ParseDelimited(), then you overwrite 2 values of array Matrix

recommendation

  • make sure: Loop through trainer.txt, writes values only to the Matrix array.
  • make sure: Loop through refbaru.txt, writes values only to the Ref array.

Your code could look something like:

[...]
filetoload: String;
[...]
procedure TfrmJST.ParseDelimited(S1: TStrings; Value: String; const Delimiter: String);
var
 f:double;
[...]
     Col := 1;
     txt := Value+Delimiter;
[...]
if filetoload='trainer.txt' then begin
     Delta := Length(Delimiter);
      while Length(txt) > 1 do
      begin
        Dx := Pos(Delimiter, txt);
        Ns := Trim(Copy(txt, 1, Dx-1));
        if Ns <> '' then
        begin
          if TryStrToFloat(Ns,f) then Matrix[Row,Col]:=f;
          Inc(Col);
          if Col > MatrixColMax then break;
          txt := Copy(txt, Dx+Delta, MaxInt);        
        end else txt:='';
      end;
end;

if filetoload='refbaru.txt' then begin
     teta := Length(delimiter);
      while Length(txt) > 1 do
      begin
        cx := Pos(delimiter, txt);
        ms := Copy(txt, 1, cx-1);
        if ms <> '' then
          begin
          if TryStrToFloat(ms,f) then Ref[Row,Col]:=f;
          Inc(Col);
          if Col > RefColMax then break;
          txt := Copy(txt, cx+teta, MaxInt);
          end else txt:='';
      end;
end;

begin
[...]

filetoload:='trainer.txt';
Temp := TStringList.Create;
Temp.LoadFromFile(filetoload);
if Temp.Count > MatrixRowMax then LinesToLoad:=MatrixRowMax-1 else
                                  LinesToLoad:=Temp.Count-1;
for I := 0 to LinesToLoad do
   [...]
   ParseDelimited(MemoSL, Trim(Temp.Strings[I]), ' ');
   [...]
end;

filetoload:='refbaru.txt';
TempList := TStringList.Create;
TempList.LoadFromFile(filetoload);
if TempList.Count > RefRowMax then LinesToLoad:=RefRowMax-1 else 
                                   LinesToLoad:=TempList.Count-1;
for J := 0 to LinesToLoad do
   [...]
   ParseDelimited(Memo1.Lines, T, ' ');
   [...]
end;
end;

You should also compare the linesize of the file with the size of the arrays

RefRowMax: integer;
RefColMax: integer;
MatrixRowMax: integer;
MatrixColMax: integer;
LinesToLoad: integer;

....

RefRowMax:=2;
RefColMax:=140;
MatrixRowMax:=140;
MatrixColMax:=141;
....

procedure ParseDelimited()

if filetoload='trainer.txt' then begin
 [...]
 Inc(Col)
 if Col > MatrixColMax then break;

end;

if filetoload='refbaru.txt' then begin
 [...]
 Inc(Col)
 if Col > RefColMax then break;

end;

You should also look for a valid value of Ns , StrToFloat(Ns) before you write to the arrays in ParseDelimited()

  • function TryStrToFloat(const S: string; out Value: Double): Boolean;
    or
  • Val();

  var
  f:double;
  ....
  begin
  ....
  if TryStrToFloat(Ns,f) then Matrix[Row,Col]:=f;
  ....

The OP overwritting many of used data.
And when he has enough data overwritten, he gets a stack overflow error.

enter image description here

enter image description here

enter image description here

moskito-x
  • 11,832
  • 5
  • 47
  • 60