2016-05-13 143 views
0

我有一个C++ Builder XE5代码,我正在转换到Delphi。尽管我能够编译,但是KeyNum的值似乎总是在我的Delphi代码中返回0。问题可能在于解析字符串。C++字符串解析到Delphi

该函数获取文本文件并将信息传递给C++结构体。我把它转换成Delphi的打包记录。

C++代码

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代码(修正)

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; 

的文本文件中的数据看起来像这样

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 

我认为这个问题是,C++令牌[ 0] .ToNnt()KeyNum的值有一个值,而我的Delphi StrToInt(令牌[0])总是返回0。

如果有人能帮助我解决这个问题,并且出错了,我将不胜感激。

感谢您提前。

+0

接下来做一些调试 –

+0

而不是'string.ToInt',看看你使用TryStrToInt会得到什么结果。 IOW,调试。 –

+0

谢谢鲁迪。会试一试。 – AndyC

回答

2

在您每次从List.Strings[LinePos]读取之后,您不会递增LinePos

当填充X/Y/Scale/Orientation值,你是不是每次从Tokens[TokenPos]阅读时间后递增TokenPos

C++代码执行这些增量。

在读取X值之前,您正在递增TokenPos,这是错误的。您正在跳过Tokens[0]中的值。 C++代码使用后增量,而不是预增量。

在旁注中,您也泄漏了由CreateProcess()返回的两个手柄。在WaitForSingleObject()返回后,您必须在ProcInfo.hThreadProcInfo.hProcess上拨打CloseHandle()。你应该等待ProcInfo.hProcess而不是ProcInfo.hThread

+0

非常感谢雷米指针。我已经更新了Delphi代码以反映并且它似乎按预期工作。 – AndyC

+0

然后,您应该将此答案标记为已接受。 –