오호.. SubString에서 해당 데이타 사이즈 만큼 String 동적으로 만들어서 리턴하는 거는 대강 알고 있었는데염.
제가 개념을 좀 다르게 가지고 있었군염.. ㅎㅎ
결국은 잘 모르고 쓰는 메소드는 독이 될수 있겠군염..
char *a = "abc1234";
char buff[4+1];
strncpy( buff , a + 3 , 4 );
buff[sizeof(buff)-1] = 0x00;
int x = atoi( buff );
Label1->Caption = buff ;
가 결과적으로 더 빠르다는 거군요...
덕분에 TControl 관련 해서 존거 배웠습니당.
틈틈히 빌더 공부하러 들어오는데 Q/A 같이 풀어나가는 거 많큼 좋은게 없군요.
이런 성실한 답변도 달아주시고 덕분에 많은 부분이 해소가 되었습니다.
수고~~!
PS : Vcl 소스들도 좀 까봐야 되겠네요 ~~!
장성호 님이 쓰신 글 :
: 자꾸 이런 저런 답변이 달리니까 재미있네요
: 저는 제리압빠님의 글에 대해서만 한두가지 의견을 적어봅니다.
:
:
str.t_str(); 이부분은?
:
: 앞의 저의 답변에도 얘기했듯이 2009에서
: 기본 String이 AnsiString이 아니라 UnicodeString이라서 그럴것입니다.
:
: AnsiString으로 하면 여전이 str.c_str()로 char *를 얻어올것입니다.
:
: ---------------------------------------------------------------------------------
: 그리고 제리압빠님의 코드에서
:
Edit->Text 를 가져오는 부분에 대해
:
: 제리압빠님의 코드중에 짭게 부분에 대해 조금 의견을 달겠습니다.
:
: // 잛게
: Label1->Caption = Edit1->Text.SubString( 4 , Edit1->Text.Length() - 3 );
: x = Label1->Caption.ToInt();
: ShowMessage( x );
:
:
: 제리압빠님뿐만 아니라 많은 분들이 위와같은 식으로 코딩하는 경우를 왕왕 보아서요
:
: 위 코드에서
: Label1->Caption 과 Edit1->Text 에 대한 접근은
: TControl 클래스의 Caption 프로퍼티와 Text 프로퍼티에 접근합니다.
: TControl에서 Caption과 Text는 근본적으로 똑같습니다.
:
:
문제는
: TControl의 Caption을 읽을때
: 그냥 내부 String변수를 return하지 않는다는 것입니다.
:
: 여러단계의 과정을 거쳐서 String결과를 return합니다.
:
:
TControl클래스 Caption가져올때 소스
: 다음은 TControl클래스이 Caption이나 Text를 가져올때 호출되는 GetText함수 소스입니다.
:
:
: function TControl.GetText: TCaption;
: var
: Len: Integer;
: begin
: Len := GetTextLen;
: SetString(Result, PChar(nil), Len);
: if Len <> 0 then GetTextBuf(Pointer(Result), Len + 1);
: end;
:
: function TControl.GetTextLen: Integer;
: begin
: Result := Perform(WM_GETTEXTLENGTH, 0, 0);
: end;
:
: function TControl.GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;
: begin
: Result := Perform(WM_GETTEXT, BufSize, Longint(Buffer));
: end;
:
:
: C++Builder로 변환하면 다음과 같습니다.
:
:
: String __fastcall TControl::GetText()
: {
: int Len=GetTextLen(); // 문자열의 길이를 확인합니다.
: String Result; // String변수를 새로 선언하고
: Result.SetLength(Len); // 문자열 길이만큼 메모리를 확보합니다.
: if(Len!=0)
: GetTextBuf(Result.c_str(), Len + 1); //확보된 buffer에 WM_GETTEXT로 string을 받아옵니다.
:
: return Result;
: }
:
: int __fastcall TControl::GetTextLen()
: {
: return this->Perform(WM_GETTEXTLENGTH, 0, 0);
: }
:
: int __fastcall TControl::GetTextBuf(char *Buffer,int BufSize)
: {
: return this->Perform(WM_GETTEXT, BufSize, Longint(Buffer));
: }
:
:
: TEdit든 TLabel이든 VCL의 모든 Control의 Caption이나 Text에 접근할때 마다 위 함수들이 호출됩니다.
:
:
제라아빠님의 코드에서는?
:
: // 잛게
: Label1->Caption = Edit1->Text.SubString( 4 , Edit1->Text.Length() - 3 );
: x = Label1->Caption.ToInt();
: ShowMessage( x );
:
:
: 위 코드에서는
: TControl::GetText가 3번 호출되었구
: TControl::SetText가 1번 호출되었습니다.
: (SetText내부적으로 GetText가 한번 호출되니 GetText는 4번이 되겠네요)
:
: 또한 메세지 핸들러 함수에서
: WM_GETTEXT,WM_SETTEXT , WM_GETTEXTLENGTH등을 받아서 처리하는 부분도 있구요
:
: 그러니까 TEdit의 Text값을 한번 가져오는데 굉장히 복잡한 과정에
: 여러함수들이 호출되어진다는 것입니다.
:
: -----------------------------------------------------------------------
: 그리고 또 하나
:
: ShowMessage( x ); //이 부분에서는
:
: ShowMessage는 기본적으로 int형을 받지 않고 String형을 받습니다.
: 즉 ShowMessage( x) 할때 String클래스에서
: 숫자를 IntToStr함수 등을 통해 문자열로 다시 변환하게 됩니다.
:
: 뭐 제리아빠님은 그냥 제대로 Label1->Caption에 내용이 들어있나 확인하기 위함인것 같지만..
:
:
:
결론적으로..
: String변수하나 선언해두고
: 거기에다가 Edit->Text를 받아서 처리하는것이
: 속도면에서 훨씬더 빠를것입니다.
:
: 일부러 트집잡으려구 답변단것은 아니구요
: 앞서 얘기했듯이 많은 BCB , Delphi 개발자들이 TEdit등 TControl의 Text값을 가져오는것이
: 그냥 내부 String변수를 return해주는것으로 착각하고 코딩하는 경우를 왕왕 보아서 댓글 단것입니다.
:
:
진짜 황당한 코드
: 심지어 다음과 같은식의 코드도 보았습니다.
:
: strcpy( Edit1->Text.c_str() , "문자열 복사") ;
:
:
: 위에 GetText 의 vcl소스를 보면 알수 있듯이
: TEdit의 Text나 TLabel의 Caption은 내부 변수를 return한느것이 아니라
: 새로 메모리를 할당해서 내용을 복사해 return하는 것이므로
: 에러가 나지 않더라도(에러날수도 있음)
: 실제 Edit->Text에는 아무 변화를 줄수 없는 코드가 되죠
:
: TControl의 Text나 Caption프로퍼티에 대한 비슷한 착각에서 코딩문제일것 같구요..
:
: 그럼..
:
:
:
: 제리압빠. 님이 쓰신 글 :
: : 소스코드 일부만 있는거 같은데용..
: : str.t_str().... 이 부분은 2009에서 새로 지원하는 String의 메소든가 보군요..
: :
: : 저는 아직 6.0 을 쓰는 처지라..유유
: : 음.. 작성하신 코드 상으로는 풀어보면.
: : 1) char 어레이를 초기화 한다.
: : 2) String 형 데이타에서 특정 부위(?) 만큼의 숫자 필드 영역을 잘라서 char배열에 담는다.
: : 3) int형으로 형변환 한다.
: : 4) int형을 다시 형변환 하여 String( Caption )에 담는다..
: :
: : 순으로 진행이 되는데요..
: :
: : 나열한거에 보다 시피 형변환이 좀 빈번히 발생하는게 아닌가 싶네요.
: : 윗분들 말씀하신 거에 좀더 사족을 달아 보자면..
: :
: : 위에서 거치는 형변환을 좀 줄이자 입니다.
: : 윗분들 코드 사례를 보면 char *어레이 형 데이타가 필요 없어지지요.
: : ( 내부에서 쓸일이 없다면 말입니다.. )
: : 이부분을 좀 줄여서 2단게로 만들어 버리는게 제 개인적인 생각으로 좀 더 나은 생각이 아닌가 사려 됩니다.
: :
: : // 1 필요한 데이타 부분을 Label에 바로 담아 버립니다.
: : Label1->Caption = Edit1->Text.SubString( 4 , Edit1->Text.Length() - 3 );
: : // 2. Label1을 버퍼로 사용하였으므로 가공을 위한 인트형으로 바로 세트 한다.
: : int ibuff = Data.ToInt();
: :
: : 이렇게 되면 좀 더 효율이 올라가지 않으려나요...
: : Label을 사용하지 않을 계획이라면 윗분들의 예제 처럼 바로 Int 변수에 결과를 담아 버리는 것도 괜챦구요..
: :
: : 만약 위에 사용하신 데이타가 "abc1234" 가 Fixed length 타입의 전문 이라고 하면...아래 처리 부분 처럼 하면
: : 될 듯 싶네요.. fixed length 인 경우 가공작업이 좀 필요하기도 합니다. 널스트링 이 없는 관계로.. 하지만 파일에서
: : 로드하는 경우라면 파일에 구조체 통으로 바이너리 타입 저장 이라면 별 문제 업겠지용.
: : //---------------------------------------------------------------------------
: :
: : #pragma pack( push , 1);
: : typedef struct tag_x
: : {
: : char ABC[3];
: : char NUMS[4];
: : }st_x;
: :
: : #pragma pack(pop);
: :
: : void __fastcall TForm1::Button1Click(TObject *Sender)
: : {
: : // 원본 ..
: : String Data = Edit2->Text;
: : char buff[4+1];
: : int x;
: : memset( buff , 0x00 , sizeof( buff ));
: : strncpy( buff , (Edit2->Text.c_str())+3 , Edit2->Text.Length() - 3 );
: :
: : x = atoi( buff );
: : ShowMessage( x );
: :
: :
: : // 잛게
: : Label1->Caption = Edit1->Text.SubString( 4 , Edit1->Text.Length() - 3 );
: : x = Label1->Caption.ToInt();
: : ShowMessage( x );
: :
: : // 고정전문 방식. 뒷부분에 다른 문자열이 있다면 잘라 담는 처리를 위한 버퍼 필요함( 1234 ) 다음
: : st_x sbuff;
: : memcpy( &sbuff , Edit2->Text.c_str() , sizeof( sbuff ));
: : Label3->Caption = sbuff.NUMS;
: : ShowMessage( atoi( sbuff.NUMS ));
: :
: : }
: : //---------------------------------------------------------------------------
: :
: : 즐 플 하세염~~~!