2014-11-05 2 views
-2

예를 들어, 문자열에서 'X'문자를 삭제하는 간단한 절차를 작성하고 싶다고합시다.PCHAR과 문자열 모두에서 작동하는 문자열을 수정하는 Delphi 프로 시저를 작성하려면 어떻게합니까?

문자열 및 PCHAR 매개 변수 모두에서 작동하도록 프로 시저를 디자인하려면 어떻게해야합니까?

내가로 정의하는 경우 :

절차 RemoveX (출처 : PChar는);

myString이 문자열 인 RemoveX (PCHAR (mystring))를 호출하는 것보다 'X'는 제거되지만 문자열 길이를 업데이트하지는 않습니다 ... 따라서 후속 myString : = myString + 'done' myString을 변경하지 않고 그대로 둡니다. 그리고 RemoveX를 호출 한 후 길이를 변경하고 싶지는 않습니다. RemoveX 프로 시저가 모든 것을 처리 할 것으로 기대합니다. 반면에 경우

나는로 정의 :

절차 RemoveX (VAR 소스 : 문자열); 나는 그것을를 PChar를 전달하는 방법을 모르는

...

+0

Remy의 답변에 따르면 다양한 유형의 단일 범용 함수를 작성하려고하면 합병증이 발생한다는 것을 알 수 있어야합니다. 이것은 ** overload ** 지시문의 요점입니다. 그것은 당신이 처리하고자하는 특정 유형에 맞춘 각각의 기능을 작성할 수 있도록합니다. 이점은 함수 이름이 동일하므로 사용자가 전달할 유형에 따라 다른 이름을 기억할 필요가 없다는 것입니다 (참고 : 이는 다른 유형이있는 모든 상황에서 적용됩니다. 비슷한 방법 - 문자열/PChar뿐 아니라 –

+0

과부하 개념을 알고 있습니다. 그러나 당신은 그 요점을 놓치고 있습니다. 문자열 길이를 수정하지 않는 함수의 경우 PCHAR 버전 만 필요하며 PCHAR에 캐스팅 된 문자열로 호출합니다. 정말 모든 문자열 함수에 과부하를 제공합니까? 나는 그렇지 않다. –

+0

아니요, 요점을 놓치고있는 것 같습니다. 'PChar'와 ** string **은 근본적인 차이점이 있습니다. 특히 문자열의 끝을 결정하는 방법. 그리고 문제는 길이를 수정하는 것이 아닙니다. 할당 된 메모리의 범위 내에서 작동하는 것입니다. (_ 버퍼 오버런 오류에 대해 들었습니까 _ _) 그리고 함수 호출자가 길을 지나갈 것을 기대하는 것은 정말로 빡빡합니다. (_WinAPI 스타일 델파이 문자열을 성공적으로 피할 수 있습니다 ._)에 관해서는 *** 내가 *** *** 모든 문자열 함수에 대한 과부하를 제공 할 것이라고? 두 버전이 모두 필요한 경우 예! 그러나 드물게 'PChar'가 전혀 필요하지 않습니다. –

답변

2

당신은이 하나의 매개 변수를 사용하여 구현할 수 없습니다. 두 가지 유형이 있습니다.

PChar 버전 위에 문자열 버전을 만들 수 있습니다.

procedure RemoveX(var str: string); 
var 
    P: PChar; 
begin 
    UniqueString(str); 
    P := PChar(str); 
    RemoveX(P); 
    str := P; 
end; 

마지막 줄에 대한 대안이 될 수있다 :

SetLength(str, StrLen(P)); 

어느 쪽이든,이 분명히 당신은 이미 PChar에 작동하는 기능 과부하 있다고 가정합니다. 그리고이 함수는 문자를 제거합니다. 분명히 그것은 PChar 버퍼를 확장 할 수 없습니다.

문자열이 공유되거나 (1보다 큰 개수) 또는 상수 인 경우 UniqueString을 호출해야합니다. 이 호출 후에 문자열 버퍼는 편집 가능하고 공유되지 않습니다.

이런 식으로 구현의 중복을 피할지 말지 모르겠지만 최선의 방법은 말할 수 없습니다. 디자인 드라이버에 따라 다릅니다. 코드의 단순성과 명확성이 중요하다면 중복을 피하는 것이 합리적입니다. 성능이 핵심이라면 두 가지 맞춤식 구현을 제공하는 것이 바람직 할 수 있습니다.

+0

나는 당신의 생각을 좋아합니다. UniqueString 호출이 여기에 불필요한가요? –

+2

입력시 문자열의 ref 수가 1보다 큰 경우는 어떻게됩니까? –

+3

문자열에 refcount가 -1 (상수 문자열) 인 경우 UniqueString도 필요합니다. –

5

PChar 버전의 측면에서 string 버전을 구현하거나 그 반대로 구현하는 것이 좋습니다.난 당신이, 독립적으로 조정할 수 있습니다 그들 이렇게 별도로 보관 것 예 :

procedure RemoveX(source : PChar); overload; 
procedure RemoveX(var source : string); overload; 

procedure RemoveX(source : PChar); 
var 
    P: PChar; 
    Len: Integer; 
begin 
    if source = nil then Exit; 
    Len := StrLen(source); 
    repeat 
    P := StrScan(source, 'X'); 
    if P = nil then Exit; 
    StrMove(P, P+1, Len - Integer(P-source)); 
    Dec(Len); 
    source := P; 
    until False; 
end; 

procedure RemoveX(var source : string); 
begin 
    source := StringReplace(source, 'X', '', [rfReplaceAll]); 
end; 

업데이트 : 당신은 정말 당신에게 다음 두 PCharString 입력을위한 하나의 구현을 사용하려면

function RemoveX(source : PChar; sourceLen: Integer): Integer; overload; 
procedure RemoveX(source : PChar); overload; 
procedure RemoveX(var source : string); overload; 

: 같은 것을 할 수 있습니다
function RemoveX(source : PChar; sourceLen: Integer): Integer; 
var 
    P: PChar; 
begin 
    Result := 0; 
    if (source = nil) or (sourceLen = 0) then Exit; 
    repeat 
    P := StrScan(source, 'X'); 
    if P = nil then Exit; 
    StrMove(P, P+1, sourceLen - Integer(P-source)); 
    Dec(sourceLen); 
    source := P; 
    until False; 
    Result := sourceLen; 
end; 

procedure RemoveX(source : PChar); 
begin 
    RemoveX(source, StrLen(source)); 
end; 

procedure RemoveX(var source : string); 
begin 
    UniqueString(source); 
    SetLength(source, RemoveX(PChar(source), Length(source))); 
end; 
+0

감사합니다. 그것은 실제로 의미가 있습니다. 나의 원초적 희망은 양쪽 모두를 위해 일할 단일 루틴을 갖는 것이었다. 문자열 길이를 수정하지 않는 루틴의 경우 쉽게 수행 할 수 있습니다. 그러나 현의 길이에 영향이있을 때 이상하게 보입니다. –

+0

@ Emmanuel 나는 당신이 함수를 두 번 구현하는 것을 피하고 싶다고 생각했다. 내가 오해 했습니까? –

+0

@Remy 문자열의 ref 카운트가 1이 아닌 이상 업데이트가 최종 오버로드에 적합하지 않습니다. –