2016-06-15 6 views
2

우리는 Firebird 2.5 데이터베이스 용 UDF를 Delphi (10 Seattle)에 작성하려고합니다.이 문자열은 입력 문자열에서 일부 문자를 제거해야합니다. 데이터베이스의 모든 문자열 필드는 유니 코드 UNICODE_CI_AI가있는 문자 집합 UTF8을 사용합니다.UTF8 문자열이있는 Delphi Firebird UDF

이 함수는 공백과 같은 일부 문자를 제거해야합니다. ; :/\와 문자열의 다른 문자. ascii 값이 < = 127 인 문자가 포함 된 문자열에 대해서는이 함수가 제대로 작동합니다. ascii 값이 127보다 큰 문자가 있으면 바로 UDF가 실패합니다. PAnsiChar 매개 변수 대신 PChar를 사용했지만 성공하지 못했습니다. 지금 우리는 문자의 ascii 값이 127 이상인지 검사하고, 그렇다면 문자열에서 해당 문자도 제거합니다.

우리가 원하는 것은 구두점 문자없이 원래 문자열을 반환하는 UDF입니다. 이것은 지금까지 우리의 코드

: 우리가 뉴스를 볼 수 있습니다 # 127 우리는 ASCII 값 <에 체크를 제거하면

unit UDFs; 

    interface 

    uses ib_util; 

    function UDF_RemovePunctuations(InputString: PAnsiChar): PAnsiChar; cdecl; 

    implementation 

    uses SysUtils, AnsiStrings, Classes; 

    //FireBird declaration: 
    //DECLARE EXTERNAL FUNCTION UDF_REMOVEPUNCTUATIONS 
    // CSTRING(500) 
    //RETURNS CSTRING(500) FREE_IT 
    //ENTRY_POINT 'UDF_RemovePunctuations' MODULE_NAME 'FB_UDF.dll'; 
    function UDF_RemovePunctuations(InputString: PAnsiChar): PAnsiChar; 
    const 
     PunctuationChars = [' ', ',', '.', ';', '/', '\', '''', '"','(', ')']; 
    var 
     I: Integer; 
     S, NewS: String; 
    begin 
     S := UTF8ToUnicodeString(InputString); 

     For I := 1 to Length(S) do 
     begin 
     If Not CharInSet(S[I], PunctuationChars) 
     then begin 
      If S[I] <= #127 
      then NewS := NewS + S[I]; 
     end; 
     end; 

     Result := ib_util_malloc(Length(NewS) + 1); 
     NewS := NewS + #0; 
     AnsiStrings.StrPCopy(Result, NewS); 
    end; 

    end. 

는 = (물론 문장 부호없이) 그것이 있어야로 모든 문자를 포함 하지만 우리가 생각하는 StrPCopy를 수행 할 때 문제가 발생합니다.

도움이 될 것입니다.

+0

'기능 AnsiStrings.StrPCopy (대상 : PAnsiChar가, CONST 출처 : AnsiString과)의 PAnsiChar를;'. NewS는 UniCode 문자열이고'StrPCopy'는'AnsiString'을 기대합니다. –

+0

나는 그것을 얻는다. 그래서 질문은 어떻게 유니 코드 문자열을 파이어 버드로 되 돌리는가? StrPCopy 대신 Move를 사용했지만 성공하지 못했습니다. Length (NewS)가 올바른 바이트 수를 반환하지 않아서 ib_util_malloc이 올바른 양의 메모리를 할당하지 않았기 때문입니까? – jdetaeye

+2

UTF8에서 유니 코드로 변환하는 이유를 알지 못합니다. S와 NewS를 'Utf8String'으로 만들고 모두 확실합니다. 'CharInSet'에는 ansichar 오버로드가 있습니다. –

답변

2

LU RD 덕분에 나는이 작업을했습니다.

대답은 내 문자열 변수를 String 대신 Utf8String으로 선언하고 입력 문자열을 유니 코드로 변환하지 않는 것이 었습니다.

나는이 같은 내 코드를 적응 :

//FireBird declaration: 
    //DECLARE EXTERNAL FUNCTION UDF_REMOVEPUNCTUATIONS 
    // CSTRING(500) 
    //RETURNS CSTRING(500) FREE_IT 
    //ENTRY_POINT 'UDF_RemovePunctuations' MODULE_NAME 'CarfacPlus_UDF.dll'; 
    function UDF_RemovePunctuations(InputString: PAnsiChar): PAnsiChar; 
    const 
     PunctuationChars = [' ', ',', '.', ';', '/', '\', '''', '"','(', ')', '-', 
          '+', ':', '<', '>', '=', '[', ']', '{', '}']; 
    var 
     I: Integer; 
     S: Utf8String; 
    begin 
     S := InputString; 

     For I := Length(S) downto 1 do 
     If CharInSet(S[I], PunctuationChars) 
     then Delete(S, I, 1); 

     Result := ib_util_malloc(Length(S) + 1); 
     AnsiStrings.StrPCopy(Result, AnsiString(S)); 
    end;