2014-09-16 14 views
6

Khi thử nghiệm StrUtils.SearchBuf với tùy chọn [soWholeWord,soDown], một số kết quả không mong muốn đã xảy ra.SearchBuf soWholeWord đầu ra không mong muốn

program Project1; 

Uses 
    SysUtils,StrUtils; 

function WordFound(aString,searchString: String): Boolean; 
begin 
    Result := SearchBuf(PChar(aString),Length(aString), 0, 0, searchString, 
    [soWholeWord,soDown]) <> nil; 
end; 

Procedure Test(aString,searchString: String); 
begin 
    WriteLn('"',searchString,'" in "',aString,'"',#9,' : ', 
    WordFound(aString,searchString)); 
end; 

begin 
    Test('Delphi','Delphi'); // True 
    Test('Delphi ','Delphi'); // True 
    Test(' Delphi','Delphi'); // False 
    Test(' Delphi ','Delphi'); // False 
    ReadLn; 
end. 

Tại sao ' Delphi'' Delphi ' không được coi là toàn bộ một từ?

Còn tìm kiếm ngược lại thì sao?

function WordFoundRev(aString,searchString: String): Boolean; 
begin 
    Result := SearchBuf(PChar(aString),Length(aString),Length(aString)-1,0,searchString, 
    [soWholeWord]) <> nil; 
end; 

Procedure TestRev(aString,searchString: String); 
begin 
    WriteLn('"',searchString,'" in "',aString,'"',#9,' : ', 
    WordFoundRev(aString,searchString)); 
end; 

begin 
    TestRev('Delphi','Delphi'); // False 
    TestRev('Delphi ','Delphi'); // True 
    TestRev(' Delphi','Delphi'); // False 
    TestRev(' Delphi ','Delphi'); // True 
    ReadLn; 
end. 

Tôi không có ý nghĩa gì cả. Ngoại trừ chức năng này là lỗi.

Kết quả tương tự trong XE7, XE6 và XE.


Cập nhật

QC127635 StrUtils.SearchBuf fails with [soWholeWord] option

+1

có lỗi khác nhau được đề cập trong QC ví dụ [Báo cáo số: 122357] (http://qc.embarcadero.com/wc/qcmain.aspx?d = 122357) – bummi

+1

@bummi, vâng tôi đã tìm kiếm QC và không tìm thấy kết quả phù hợp cho lần xuất hiện này. –

Trả lời

4

Nó trông giống như một lỗi với tôi. Dưới đây là đoạn code mà không tìm kiếm:

while SearchCount > 0 do 
begin 
    if (soWholeWord in Options) and (Result <> @Buf[SelStart]) then 
    if not FindNextWordStart(Result) then Break; 
    I := 0; 
    while (CharMap[(Result[I])] = (SearchString[I+1])) do 
    begin 
    Inc(I); 
    if I >= Length(SearchString) then 
    begin 
     if (not (soWholeWord in Options)) or 
     (SearchCount = 0) or 
     ((Byte(Result[I])) in WordDelimiters) then 
     Exit; 
     Break; 
    end; 
    end; 
    Inc(Result, Direction); 
    Dec(SearchCount); 
end; 

Mỗi vòng while vòng lặp chúng tôi kiểm tra nếu soWholeWord là trong các tùy chọn, và sau đó tiến tới sự bắt đầu của từ kế tiếp. Nhưng chúng tôi chỉ thực hiện điều đó nếu

Result <> @Buf[SelStart] 

Hiện tại, Result là con trỏ hiện tại vào bộ đệm, ứng cử viên cho một trận đấu. Và do đó, kiểm tra này kiểm tra xem chúng tôi có đang bắt đầu chuỗi tìm kiếm hay không.

Thử nghiệm này có nghĩa là chúng tôi không thể chuyển qua văn bản không phải chữ số để bắt đầu từ đầu tiên, nếu chuỗi tìm kiếm bắt đầu bằng văn bản không phải chữ và số.

Bây giờ, bạn có thể quyết định để loại bỏ các thử nghiệm cho

Result <> @Buf[SelStart] 

Nhưng nếu bạn làm điều đó bạn sẽ thấy rằng bạn không còn phù hợp với từ nếu nó nằm ngay lúc bắt đầu của chuỗi. Vì vậy, bạn sẽ chỉ thất bại theo một cách khác. Cách đúng đắn để giải quyết vấn đề này là đảm bảo rằng FindNextWordStart không thăng tiến nếu chúng tôi ở đầu chuỗi và văn bản có chữ và số.

tôi đoán là tác giả ban đầu đã viết code như thế này:

if (soWholeWord in Options) then 
    if not FindNextWordStart(Result) then Break; 

Sau đó, họ phát hiện ra rằng từ lúc bắt đầu của chuỗi sẽ không phù hợp và thay đổi mã để:

if (soWholeWord in Options) and (Result <> @Buf[SelStart]) then 
    if not FindNextWordStart(Result) then Break; 

Và không ai kiểm tra những gì đã xảy ra nếu chuỗi bắt đầu bằng văn bản không phải chữ và số.

Something như thế này dường như để hoàn thành công việc:

if (soWholeWord in Options) then 
    if (Result <> @Buf[SelStart]) or not Result^.IsLetterOrDigit then 
    if not FindNextWordStart(Result) then Break; 
+2

'Và không ai kiểm tra những gì đã xảy ra nếu chuỗi bắt đầu bằng văn bản không phải chữ và số'. Sigh, rất nhiều năm và không ai tìm thấy điều này trước đây. Bài kiểm tra là tầm thường và nó làm cho tôi tự hỏi liệu RTL có được kiểm tra đơn vị bởi Emba hay không. Cảm ơn, tôi sẽ gửi một QC sau. –

+2

Hmm. Đừng bắt đầu tôi !! –

+0

@DavidHeffernan Tôi đã thay thế mã ban đầu bằng mã đề xuất của bạn và vẫn không hoạt động, ví dụ được đề cập trả về cùng một kết quả. Delphi 10.1 hoặc 10.2. –

Các vấn đề liên quan