밑의 소스는 string을 구분자로 하는 문자열을 잘라서 stringlist에 넣어주는
함수를 구현한 것입니다. (이름은 split이라고 했어요...)
제가 궁금한건 두가지입니다.
첫번째는
procedure split(separator, Content: string; Strings: TStrings);
넘어온 Strings가 call by value이기 때문에 이 함수내 부에서 Strings를 아무리 지지고 볶아도 함수를 호출한 곳에서의 StringList (밑의 소스에서는 MyList) 값에는 전혀 변화가 없어야 한다고 생각합니다.
그런데 아무런 문제가 없이 잘 돌아가더군요.
showMessage에서 에러가 떨어질 줄 알았는데 문자열 자르기가 잘 됩니다.
call by value로 넘겨준 변수의 원래 값에도 변화가 있는건가요?
두번째는
procedure split(separator, Content: string; var Strings: TStrings);
이렇게 var를 붙여 call by reference로 변수를 넘긴 경우 에러가 나더군요.
그래서 TStrings를 TStringList로 바꿔보았습니다. 그렇게 하니까 역시 잘 돌아갑니다. TStrings가 TStringList의 상위 클래스이니 상관 없을거라 생각하고 TStrings타입으로 만들었는데... var를 붙일 경우엔 함수에 정의된 파라미터와
완전히 일치되는 타입으로만 넣어야하는 것인지도 궁금하네요.. ^^;;
-------------------------------------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
procedure split(separator, Content: string; Strings: TStrings);
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
Mylist: TStringList;
test: string;
begin
Mylist := TStringList.Create;
Mylist.Clear;
test := 'test123#dep#test456#dep#test789&test&test\n-1111';
split('#dep#', test, Mylist);
showMessage(MyList[0]);
showMessage(MyList[1]);
showMessage(MyList[2]);
end;
procedure TForm1.split(separator, Content: string; Strings: TStrings);
var
i: integer;
position: integer;
sepa_leng: integer;
item: string;
sepa_content: string;
begin
position := 0;
sepa_leng := length(separator);
sepa_content := Content;
Strings.BeginUpdate;
try
i := Pos(separator, sepa_content);
while i > 0 do
begin
item := copy(sepa_content,position, i-1);
sepa_content := copy(sepa_content, i+sepa_leng, length(Content));
Strings.Add(item);
i := Pos(separator, sepa_content);
end;
Strings.Add(sepa_content)
finally
Strings.EndUpdate;
end;
end;
end.
----------------------------------------------------------------
으.. 지저분한 소스를 가지고 횡설수설 질문한 듯해 죄송합니다.. ^^;;;
아시는 분은 답변해주세요..
혹시 제가 만든 함수에 문제점이 있다면 그것도 지적해주시면 정말 감사드리겠습니다.. ^^;;
좋은 하루 되세요~~
첫번째 것은 Call By Value이기 때문에 Strings란 변수자체에는 아무런 변화가 없습니다. 파라매터 Strings 란 변수는 객체이구 4바이트를 차지하는 메모리 번지(포인터)일뿐입니다.
Split함수에는 Strings에 값을 대입하는 코드는 없군요.
Strings := nil; // 이런식으로... 직접적으로 변수값을 바꾸는 코드는 없습니다.
함수안에서 Strings.Add(item);하는 것은 Strings란 변수의 값을 바꾸는 것이 아니라 Strings가 참조하는 것을 변경시키죠... 변수파라매터 자체는 단지 4바이트 메모리 주소일뿐입니다.
call by value로 넘겨준 변수의 원래 값에도 변화는 없습니다.
쉽게 말해서 객체나 포인터 같이 메모리 번지를 가리키는 변수가 파파매터로 들어올때 이 메모리 번지는 바뀌지 않지만 이 메모리 번지의 내용은 바꿀수 있다는 얘기입니다.
두번째는 변수형이 일치해야 합니다.
^^ 항상 즐코하세요..