2016-05-13 1 views
0

Ich habe einen C++ Builder XE5-Code, den ich in Delphi konvertiere. Obwohl ich in der Lage bin zu kompilieren, scheint der Wert von KeyNum in meinem Delphi-Code immer 0 zurückzugeben. Das Problem könnte im Parsen der Strings liegen.C++ - String-Parsing nach Delphi

Die Funktion nimmt eine Textdatei und überträgt die Informationen in eine C++ - Struktur. Ich habe das in Delphi in eine gepackte Platte konvertiert.

C++ Code

int __fastcall TFastSift::fastSift(UnicodeString fileName) 
{ 
// 
STARTUPINFO StartInfo;  // name structure 
PROCESS_INFORMATION ProcInfo; // name structure 
memset(&ProcInfo, 0, sizeof(ProcInfo)); // Set up memory block 
memset(&StartInfo, 0 , sizeof(StartInfo)); // Set up memory block 
StartInfo.cb = sizeof(StartInfo); // Set structure size 
//UnicodeString app = "C:\\windows\\system32\\cmd.exe"; 
// 
UnicodeString app = getenv("COMSPEC"); 
// 
UnicodeString args = "/C "+progPath+"siftfast.exe  <"+workPath+fileName+".pgm>"+workPath+fileName+".kds"; 
StartInfo.dwFlags = STARTF_USESHOWWINDOW; 
StartInfo.wShowWindow = SW_HIDE; 
int res = CreateProcessW(app.w_str(), args.w_str(), NULL, NULL, NULL, NULL, NULL, NULL, &StartInfo, &ProcInfo); // starts MyApp 
if (res) 
    { 
    WaitForSingleObject(ProcInfo.hThread, INFINITE); 
    } 
// 
//TODO: check if file kds existis 
// 
TStringList *list = new TStringList(this); 
list->LoadFromFile(workPath+fileName+".kds"); 
FormatSettings.DecimalSeparator = '.'; 
if (list->Count < 1) 
    { 
    // error 
    delete list; 
    return 0; 
    } 
TStringDynArray tokens; 
// key num, key length 
tokens = SplitString(list->Strings[0], " "); 
int line_pos, tok_pos; 
int keynum = tokens[0].ToInt(); 
kfDesc = new FeatureDescriptor[keynum]; 
UnicodeString line, tok_test; 
line_pos = 1; 
for (int i = 0; i < keynum; i++) // 
    { 
    line = list->Strings[line_pos++]; 
    tokens = SplitString(line, " "); 
    tok_pos = 0; 
    try { 
     kfDesc[i].x = tokens[tok_pos++].ToDouble();  // x 
     kfDesc[i].y = tokens[tok_pos++].ToDouble();  // y 
     kfDesc[i].scale = tokens[tok_pos++].ToDouble(); // scale 
     kfDesc[i].orientation = tokens[tok_pos++].ToDouble(); // orientation 
     // values 
     tok_pos = 0; 
     while (tok_pos < KLEN) 
      { 
      line = list->Strings[line_pos++]; 
      tokens = SplitString(line, " "); 
      int tok_len = tokens.get_length() - 1; // usually 16 
      for (int j = 0; j < tok_len; j++) 
        { 
        tok_test = tokens[j]; 
        kfDesc[i].value[tok_pos] = tokens[j].ToDouble(); 
        tok_pos++; 
        } 
      } 
     line_pos++; // skip separator line 
     } 
    catch (...) { 
     keynum = 0; 
     break; 
     } 
    } 
delete list; 
return keynum; 
} 

Delphi-Code (Korrigiert)

function TFastSift.FastSift(const FileName: string): Integer; 
var 
    StartInfo: TStartupInfo; 
    ProcInfo: TProcessInformation; 
    ApplicationName: string; 
    CommandLine: string; 
    Created: Boolean; 
    List: TStringList; 
    Tokens: TArray<string>; 
    LinePos: Integer; 
    TokenPos: Integer; 
    KfDesc: TArrOfTFeatureDescriptor; 
    Line: string; 
    TokenTest: string; 
    I: Integer; 
    TokenLen: Integer; 
    KeyNum: Integer; 
    J: Integer; 
begin 
    FillChar(ProcInfo, SizeOf(ProcInfo), 0);  // Set up memory block 
    FillChar(StartInfo, SizeOf(StartInfo), 0); // Set up memory block 
    StartInfo.cb := SizeOf(StartInfo);   // Set structure size 
    ApplicationName := GetEnvironmentVariable('COMSPEC'); 
    CommandLine := '/C ' + FProgPath + 'siftfast.exe <' + FWorkPath + FileName + '.pgm>' + FWorkPath + FileName + '.kds'; 
    StartInfo.dwFlags := STARTF_USESHOWWINDOW; 
    StartInfo.wShowWindow := SW_HIDE; 
    Created := CreateProcess(PChar(ApplicationName), PChar(CommandLine), nil, nil, False, 0, nil, nil, StartInfo, ProcInfo); // starts MyApp 
    if (Created) then 
    begin 
    try 
     WaitForSingleObject(ProcInfo.hProcess, INFINITE); 
    finally 
     CloseHandle(ProcInfo.hProcess); 
     CloseHandle(ProcInfo.hThread); 
    end; 
    end; 

    // 
    // TODO: check if file kds existis 
    // 
    List := TStringList.Create(); 
    try 
    List.LoadFromFile(TPath.Combine(FWorkPath, FileName + '.kds')); 
    FormatSettings.DecimalSeparator := '.'; 
    if (List.Count < 1) then 
    begin 
     // error 
     Exit(0); 
    end; 

    // key num, key length 
    Tokens := List.Strings[0].Split([' ']); 
    KeyNum := StrToInt(Tokens[0]); 

    SetLength(KfDesc, KeyNum); 
    LinePos := 1; 
    for I := 0 to KeyNum - 1 do 
    begin 
     Line := List.Strings[LinePos]; 
     Tokens := Line.Split([' ']); 
     TokenPos := 0; 
     try 
     KfDesc[I].X := StrToFloat(Tokens[TokenPos]); // x 
     inc(TokenPos); 
     KfDesc[I].Y := StrToFloat(Tokens[TokenPos]); // y 
     inc(TokenPos); 
     KfDesc[I].Scale := StrToFloat(Tokens[TokenPos]); // scale 
     inc(TokenPos); 
     KfDesc[I].Orientation := StrToFloat(Tokens[TokenPos]); // orientation 
     // values 
     TokenPos := 0; 
     inc(LinePos); 
     while (TokenPos < KLEN) do 
     begin 
      Line := List.Strings[LinePos]; 
      Tokens := Line.Split([' ']); 
      TokenLen := Length(Tokens); // usually 16 
      for J := 0 to TokenLen - 1 do 
      begin 
      TokenTest := Tokens[J]; 
      KfDesc[I].Value[TokenPos] := StrToFloat(Tokens[J]); 
      inc(TokenPos); 
      end; 
      inc(LinePos); // skip separator line 
     end; 
     inc(LinePos); // skip separator line 

     except 
     KeyNum := 0; 
     break; 
     end; 
    end; 
    finally 
    List.Free(); 
    end; 
    Result := KeyNum; 
end; 

Die Textdatei Daten sehen so etwas wie diese

14219 128 
817.027 1573.46 228.737 1.65905 
0 0 0 25 41 0 0 0 16 17 19 94 111 0 0 0 
140 65 15 11 5 0 0 1 34 5 0 0 0 0 0 0 
0 0 0 66 90 5 0 0 44 30 12 140 140 19 0 2 
140 55 5 12 4 1 0 8 52 0 0 0 0 0 0 2 
0 0 0 64 104 12 0 0 61 5 2 64 140 64 5 20 
140 8 0 1 5 5 3 58 44 0 0 0 0 0 0 4 
0 0 1 51 81 44 13 0 40 2 1 61 36 30 76 46 
140 1 0 1 1 0 13 96 20 0 0 0 0 0 0 4 

712.401 2643.9 183.285 1.45477 
0 0 5 32 54 116 16 0 106 24 3 12 63 135 13 15 
135 43 0 0 0 1 1 8 10 1 0 0 0 0 0 0 
0 4 53 70 106 15 1 0 69 29 35 78 125 39 11 12 
135 74 1 5 5 1 3 23 24 3 0 0 0 0 0 0 
0 0 16 21 111 94 79 10 19 3 15 25 20 19 135 98 
135 7 0 1 1 1 66 135 15 0 0 0 0 0 0 5 
0 0 0 0 2 26 48 3 0 0 0 0 0 2 91 23 
0 0 0 0 0 0 21 22 0 0 0 0 0 0 0 0 

ich glaube, das Problem ist, dass das C++ Tokens [ 0] .ToInt() Wert von KeyNum hat einen Wert, während mein Delphi StrToInt (Token [0]) immer 0 zurückgibt.

Ich würde mich freuen, wenn mir jemand mit diesem Code helfen kann und wo ich falsch gelaufen bin.

Wir danken Ihnen im Voraus.

+0

Tun Sie einige Debugging nächste –

+0

Statt 'string.ToInt', schauen Sie, welches Ergebnis Sie erhalten, wenn Sie' TryStrToInt' verwenden. IOW, debuggen. –

+0

Danke Rudi. Werde das versuchen. – AndyC

Antwort

2

Sie werden LinePos nicht nach jedem Lesen von List.Strings[LinePos] inkrementieren.

Wenn die X/Y/Scale/Orientation Werte bevölkern, sind Sie Inkrementieren nicht TokenPos nach jedem Mal, wenn Sie von Tokens[TokenPos] lesen.

Der C++ - Code führt diese Inkremente aus.

Sie erhöhen TokenPos vor dem Lesen der X Wert, der falsch ist. Sie überspringen den Wert in Tokens[0]. Der C++ - Code verwendet Post-Increments, nicht Pre-Increments.

Nebenbei, Sie verlieren auch die beiden Griffe von CreateProcess() zurückgegeben. Sie müssen CloseHandle() auf ProcInfo.hThread und ProcInfo.hProcess nach WaitForSingleObject() zurückrufen. Und Sie sollten auf ProcInfo.hProcess statt ProcInfo.hThread warten.

+0

Vielen Dank für die Hinweise, Remy. Ich habe den Delphi-Code aktualisiert und es scheint wie erwartet zu funktionieren. – AndyC

+0

Dann sollten Sie diese Antwort als akzeptiert markieren. –