0

我想从两个文件 .txt 中获取值,一个文件包含与其他文件不同的维度矩阵

我试过这个代码:

  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;

这是矩阵的初始化:

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

这是实现:

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;

我尝试了该代码但给了我错误,错误是处理第一个矩阵的“inc(row)”行中的stackoverflow错误。虽然我在处理第二个矩阵的第二个函数中给出了注释,但 Temp[i] 只返回 2 行矩阵 [140x141]。这是否意味着代码无法处理两个不同的文件?为什么它只返回两行矩阵?任何人都可以帮助我吗?

4

2 回答 2

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

于 2012-08-09T16:46:36.503 回答
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;

看着这段代码,我看到了无限循环的可能性:如果没有找到 Delimiter 会发生什么?它将继续运行并永远增加您的“col”值。如果没有找到分隔符,请确保有条件停止您的 while 循环。

于 2012-08-09T07:27:53.190 回答