C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[60291] Re:Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리...
장성호 [nasilso] 1521 읽음    2010-02-22 18:45
자꾸 이런 저런 답변이  달리니까 재미있네요
저는 제리압빠님의 글에 대해서만 한두가지 의견을 적어봅니다.

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 ));
:
: }
: //---------------------------------------------------------------------------
:
: 즐 플 하세염~~~!

+ -

관련 글 리스트
60276 황당한 일이 생겨서리... 복이 1630 2010/02/21
60277     Re:황당한 일이 생겨서리... 한수동 1393 2010/02/21
60278         Re:Re:황당한 일이 생겨서리... 장성호 1605 2010/02/22
60282             Re:Re:Re:황당한 일이 생겨서리... Nibble 1468 2010/02/22
60283                 Re:Re:Re:Re:황당한 일이 생겨서리... Lynx 1378 2010/02/22
60284                     Re:Re:Re:Re:Re:황당한 일이 생겨서리... Nibble 1326 2010/02/22
60288                         Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리... 제리압빠. 1391 2010/02/22
60291                             Re:Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리... 장성호 1521 2010/02/22
60296                                 Re:Re:Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리... 제리압빠. 1194 2010/02/23
60298                                     Re:Re:Re:Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리... Nibble 1228 2010/02/23
60299                                         Re:Re:Re:Re:Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리... 제리압빠. 1424 2010/02/23
60292                                 Re:Re:Re:Re:Re:Re:Re:Re:황당한 일이 생겨서리... Nibble 1229 2010/02/23
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.