development of fashion cad systemfashiontech.snu.ac.kr/note/fashioncad/11-more on...
TRANSCRIPT
Sungmin Kim
SEOUL NATIONAL UNIVERSITY
Development of Fashion CAD System
11. More on Class
Introduction Topics File System
ASCII
– FILE Pointer
Binary
– TFileStream Class
More on Class
Access Specifier (접근 지정자)
Operator Overloading (연산자 오버로딩)
Inheritance (상속)
– 상속에 의한 TFileStream 의 확장
2
File System File I/O UI 구성 TMainForm 에 Menu 추가
Dialog Box 추가
3
TOpenDialog TSaveDialog
File System File I/O UI 구성 Dialog Box 속성 설정
공통 설정
TOpenDIalog
– Name=OpenDialog, Title=Load Project
TSaveDialog
– Name= SaveDialog, Title=Save Project
4
File System File I/O UI 구성 File-Save Project 메뉴
5
void __fastcall TMainForm::SaveProject1Click(TObject *Sender){TChildForm *C=(TChildForm*)ActiveMDIChild;if (C){
SaveDialog->FileName="";if (SaveDialog->Execute()){
C->Garment->SaveToFile(SaveDialog->FileName);}
}}
File System File I/O UI 구성 File-Load Project 메뉴
TMainForm
TChildForm
6
void __fastcall TMainForm::LoadProject1Click(TObject *Sender){LoadDialog->FileName="";if (LoadDialog->Execute()){
new TChildForm(Application,LoadDialog->FileName,1);}
}
void __fastcall TMainForm::NewWindow1Click(TObject *Sender){new TChildForm(Application,"NewProject-"+AnsiString(MDIChildCount+1)+".Pattern",0);}
새 프로젝트/기존 프로젝트 구분 flag
__fastcall TChildForm::TChildForm(TComponent* Owner,AnsiString C,int Type): TForm(Owner){Caption=C;NewCanvas=new ptNewCanvas;Garment=new ptGarment;if (Type==1){
Garment->LoadFromFile(C);}
}
File System Save to File File의 종류
ASCII (Text) File
– 보통 사람이 이해할 수 있는 text 로 파일을 저장
– 용량이 크고 로딩 시간이 길지만 직관적 이해 및 부분적 수정이 가능함
– 소량의 단순한 데이터 저장에 사용
Binary File
– 보통 사람이 이해할 수 없는 2진수로 파일을 저장
– 용량이 작고 로딩 시간이 짧지만 이해 및 부분 수정이 불가능
– 사진, 음악 등 멀티 미디어 데이터 혹은 대용량 데이터 저장에 사용
File 저장 방법
File Pointer 생성
데이터 쓰기
File Pointer 닫기
7
File System Save to File ptGarment::SaveToFile 함수의 작성
Procedural parametric design 이므로 Step 만 저장하면 됨
– FILE pointer 를 쓰기 위해 ptGarment.h 함수에서 <stdio.h> 를 include 해야 함
8
void ptGarment::SaveToFile(AnsiString N){FILE *F=fopen(N.c_str(),"w+");fprintf(F,"Version=1\n"); // 20160624int i;fprintf(F,"Step=%d\n",StepNum);for(i=0;i<StepNum;i++){
Step[i]->SaveToFile(F);}
fclose(F);}
File System Save to File ptDesignStep::SaveToFile 함수의 작성
9
void ptDesignStep::SaveToFile(FILE *F){fprintf(F,"Version=1\n"); // 20160624fprintf(F,"%d\n",(int)Type);int i;fprintf(F,"%d\n",iParamNum);for(i=0;i<iParamNum;i++){
fprintf(F,"%d\n",iParam[i]);}
fprintf(F,"%d\n",fParamNum);for(i=0;i<fParamNum;i++){
fprintf(F,"%f\n",fParam[i]);}
fprintf(F,"%d\n",sParam.Length());fwrite(sParam.c_str(),1,sParam.Length(),F);}
File System Save to File ASCII 형식으로 저장된 파일의 예
10
Version=1Step=9Version=11020.0000000.000000
Version=1102300.0000000.000000
Version=121120.000000300.000000Version=1
52010
Version=152120
Version=152200
Version=18120
001021210110Pattern-1Version=114100
Version=112110
File System Load From File ptGarment::LoadFromFile 함수의 작성
Step을 불러와서 regenerate 하면 됨
11
void ptGarment::LoadFromFile(AnsiString N){FILE *F=fopen(N.c_str(),"r");int Version;fscanf(F,"Version=%d\n",&Version);int i;fscanf(F,"Step=%d\n",&StepNum);Step=(ptDesignStep**)calloc(StepNum,sizeof(ptDesignStep*));for(i=0;i<StepNum;i++){
Step[i]=new ptDesignStep;Step[i]->LoadFromFile(F);}
fclose(F);Regenerate();}
File System Load From File ptDesignStep::LoadFromFile 함수의 작성
12
void ptDesignStep::LoadFromFile(FILE *F){int Version;fscanf(F,"Version=%d\n",&Version);int i,d,n;fscanf(F,"%d\n",&d);Type=(StepType)d;fscanf(F,"%d\n",&n);for(i=0;i<n;i++){
fscanf(F,"%d\n",&d);AddIntParam(d);}
fscanf(F,"%d\n",&n);float f;for(i=0;i<n;i++){
fscanf(F,"%f\n",&f);AddFloatParam(f);}
fscanf(F,"%d\n",&n);char Buf[300];fread(Buf,1,n,F);sParam=AnsiString(Buf);}
File System Binary Type ptGarment::SaveToFileBinary 함수 작성
13
void ptGarment::SaveToFileBinary(AnsiString N){TFileStream *F=new TFileStream(N,fmCreate);WriteInt(F,1); // Version,20160624WriteInt(F,StepNum);int i;for(i=0;i<StepNum;i++){
Step[i]->SaveToFileBinary(F);}
delete F;}
void ptGarment::WriteInt(TFileStream *F,int n){F->WriteBuffer(&n,sizeof(int));}
File System Binary Type ptDesignStep::SaveToFileBinary 함수 작성
14
void ptDesignStep::SaveToFileBinary(TFileStream *F){WriteInt(F,1); // Version, 20160624WriteInt(F,(int)Type);WriteInt(F,iParamNum);int i;for(i=0;i<iParamNum;i++){
WriteInt(F,iParam[i]);}
WriteInt(F,fParamNum);for(i=0;i<fParamNum;i++){
WriteFloat(F,fParam[i]);}
WriteString(F,sParam);}
void ptDesignStep::WriteInt(TFileStream *F,int n){F->WriteBuffer(&n,sizeof(int));}
void ptDesignStep::WriteFloat(TFileStream *F,float n){F->WriteBuffer(&n,sizeof(float));}
void ptDesignStep::WriteString(TFileStream *F,AnsiString S){WriteInt(F,S.Length());F->WriteBuffer(S.c_str(),S.Length());}
File System Binary Type Binary 형식으로 저장된 파일의 예
일반 text editor로 확인 불가
15
File System Binary Type ptGarment::LoadFromFileBinary 함수 작성
16
void ptGarment::LoadFromFileBinary(AnsiString N){TFileStream *F=new TFileStream(N,fmOpenRead);int Version=ReadInt(F);StepNum=ReadInt(F);Step=(ptDesignStep**)calloc(StepNum,sizeof(ptDesignStep*));int i;for(i=0;i<StepNum;i++){
Step[i]=new ptDesignStep;Step[i]->LoadFromFileBinary(F);}
delete F;Regenerate();}
int ptGarment::ReadInt(TFileStream *F){int n;F->ReadBuffer(&n,sizeof(int));return n;}
File System Binary Type ptDesignStep::LoadFromFileBinary 함수 작성
17
void ptDesignStep::LoadFromFileBinary(TFileStream *F){int Version=ReadInt(F);Type=(StepType)ReadInt(F);int n=ReadInt(F);int i;for(i=0;i<n;i++){
AddIntParam(ReadInt(F));}
n=ReadInt(F);for(i=0;i<n;i++){
AddFloatParam(ReadFloat(F));}
sParam=ReadString(F);}
int ptDesignStep::ReadInt(TFileStream *F){int n;F->ReadBuffer(&n,sizeof(int));return n;}
float ptDesignStep::ReadFloat(TFileStream *F){float f;F->ReadBuffer(&f,sizeof(float));return f;}
AnsiString ptDesignStep::ReadString(TFileStream *F){int l=ReadInt(F);char *buf=new char[l+1]F->ReadBuffer(Buf,l);buf[l]=0; // line endAnsiString N=AnsiString(buf);delete[]buf;return N;}
More on Class Access Specifier Class Member 에 대한 접근을 제한하는 키워드
Public
– 외부 process 에서 자유롭게 접근이 가능
– 코드 작성은 쉽지만 외부에서 접근이 쉬워 오류 가능성이 높아짐
Private
– 내부 변수는 내부 함수에서만 접근이 가능하게 제한
– 변수/함수가 외부와 격리 (isolation)되어 안정성이 높아지며 수정이 용이해짐
Protected
– 외부에서는 접근이 불가능하지만 상속된 클래스에서는 참조 가능
18
More on Class Access Specifier ptDesignStep 의 예
iParamNum, iParam 은 public 멤버이므로 외부에서 access 가 가능
– a=S->iParamNum; 라고 해도 되는데 굳이 a=S->GetIntParam(); 이라고 했던 이유는 ?
– s=S->iParam[5]; 라고 해도 되는데 굳이 s=S->GetIntParam(5); 라고 했던 이유는 ?
내부의 복잡한 변수 이름을 감추는 기능 (encapsulation)
만약 iParam 에 일률적으로 2를 곱한 값을 전해줘야 한다면 ?
– 전체 소스를 찾아다니면서 iParam 을 다 수정할 필요 없이 GetIntParam() 함수만 수정하면 된다
19
public:int iParamNum;int *iParam;
void AddIntParam(int);int GetIntParamNum() {return iParamNum;}int GetIntParam(int);void SetIntParam(int,int);
More on Class Access Specifier ptDesignStep 의 예
Private 키워드를 사용한 경우
– S->iParamNum; 이나 S->iParam[5]; 등의 참조 (refer, access) 가 불가능하다
– 클래스 내부 변수가 임의로 설정되지 않도록 보호해야 하는 경우 필수적
» 클래스 작동에 필수적인 변수 값을 외부에서 임으로 변경할 수 없도록 한다
20
public:
void AddIntParam(int);int GetIntParamNum() {return iParamNum;}int GetIntParam(int);void SetIntParam(int,int);
private:int iParamNum;int *iParam;
More on Class Operator Overloading 필요성
int, float 과같은 기본형 변수의 경우 사칙 연산 등을 직관적으로 할 수 있다
수학적인 요소를 class화한 경우에도 이런 연산을 할 수 없을까 ?
ptPoint Class 의 경우
ptPoint class a,b,c 를 정의했을 때
– c.Add(a,b), c.Subtract(a,b) 라는 함수를 만드는 것 보다 c=a+b, c=a-b 와 같이 쓸 수 있다면 ?
ptPoint class a,b 와 float d 를 정의했을 때
– d=a.InnerProduct(b) 라는 함수를 만드는 것보다 d=a*b 라고 쓸 수 있다면 ?
21
More on Class Operator Overloading +, - 연산과 내적 계산
응용분야
행렬, 복소수 등 여러 data class 에 적용 가능
22
class ptPoint{public:
ptPoint();~ptPoint();ptPoint(ptPoint&);
ptPoint operator+(const ptPoint& N);ptPoint operator-(const ptPoint& N);float operator*(const ptPoint& N);
};
ptPoint ptPoint::operator+(const ptPoint& N){return ptPoint (x+N.x,y+N.y);}
ptPoint ptPoint::operator-(const ptPoint& N){return ptPoint (x-N.x,y-N.y);}
float ptPoint::operator*(const ptPoint& N){return x*N.x+y*N.y;}
More on Class Inheritance SaveToFileBinary/LoadFromFileBinary 에서의 문제점
WriteInt, ReadInt, WriteFloat, ReadFloat, WriteString, ReadString 등의 함수
– 해당 클래스에서 매번 정의를 따로 해야하는 문제가 있음
– 이 함수들이 TFileStream의 멤버 함수였다면 어땠을까 ?
상속 (Inheritance)로 해결 가능
기존에 존재하는 Class 의 모든 기능을 이어받은 새로운 클래스의 작성
– TFileStream 의 모든 멤버 변수, 함수를 '상속' 받은 새로운 클래스를 만든다
– 새로운 TNewFileStream 클래스에는 int, float, AnsiString I/O 에 필요한 함수를 만들 수 있다
23
More on Class Inheritance TNewFileStream 유닛 추가
24
//---------------------------------------------------------------------------#ifndef TNewFileStreamH#define TNewFileStreamH//---------------------------------------------------------------------------
#include <vcl.h>
class TNewFileStream : public TFileStream{public :
TNewFileStream(const AnsiString, Word);
void WriteInt(int);void WriteFloat(float);void WriteString(AnsiString);int ReadInt();float ReadFloat();AnsiString ReadString();
};
#endif
More on Class Inheritance TNewFileStream 유닛 추가
25
TNewFileStream::TNewFileStream(const AnsiString N, Word T) : TFileStream(N,T){}
void TNewFileStream::WriteInt(int n){WriteBuffer(&n,sizeof(int));}
void TNewFileStream::WriteFloat(float n){WriteBuffer(&n,sizeof(float));}
void TNewFileStream::WriteString(AnsiString S){WriteInt(S.Length());WriteBuffer(S.c_str(),S.Length());}
int TNewFileStream::ReadInt(){int n;ReadBuffer(&n,sizeof(int));return n;}
float TNewFileStream::ReadFloat(){float f;ReadBuffer(&f,sizeof(float));return f;}
AnsiString TNewFileStream::ReadString(){int l=ReadInt();char *buf=new char[l+1];ReadBuffer(buf,l);buf[l]=0; // line endAnsiString N=AnsiString(buf);delete[]buf;return N;}
More on Class Inheritance ptGarment::SaveToFileBinary/LoadFromFileBinary 함수 수정
26
void ptGarment::SaveToFileBinary(AnsiString N){TNewFileStream *F=new TNewFileStream(N,fmCreate);F->WriteInt(1); // Version,20160624F->WriteInt(StepNum);int i;for(i=0;i<StepNum;i++){
Step[i]->SaveToFileBinary(F);}
delete F;}
void ptGarment::LoadFromFileBinary(AnsiString N){TNewFileStream *F=new TNewFileStream(N,fmOpenRead);int Version=F->ReadInt();StepNum=F->ReadInt();Step=(ptDesignStep**)calloc(StepNum,sizeof(ptDesignStep*));int i;for(i=0;i<StepNum;i++){
Step[i]=new ptDesignStep;Step[i]->LoadFromFileBinary(F);}
delete F;Regenerate();}
More on Class Inheritance ptDesignStep::SaveToFileBinary/LoadFromFileBinary 함수 수정
27
void ptDesignStep::SaveToFileBinary(TNewFileStream *F){F->WriteInt(1); // Version, 20160624F->WriteInt((int)Type);F->WriteInt(iParamNum);int i;for(i=0;i<iParamNum;i++){
F->WriteInt(iParam[i]);}
F->WriteInt(fParamNum);for(i=0;i<fParamNum;i++){
F->WriteFloat(fParam[i]);}
F->WriteString(sParam);}
void ptDesignStep::LoadFromFileBinary(TNewFileStream *F){int Version=F->ReadInt();Type=(StepType)F->ReadInt();int n=F->ReadInt();int i;for(i=0;i<n;i++){
AddIntParam(F->ReadInt());}
n=F->ReadInt();for(i=0;i<n;i++){
AddFloatParam(F->ReadFloat());}
sParam=F->ReadString();}