02 : 02 유틸리티클래스와집합클래스 학습목표 유틸리티클래스를이용하여객체생성법과사용법을익힌다. MFC 에서 C++ 의업캐스팅이적용되는원리를이해한다. 배열, 리스트, 맵클래스동작원리와사용법을익힌다.
콘솔응용프로그램 특징 메시지구동방식을사용하지않으므로 C/C++ 언어에대한지식만있으면곧바로실습이가능하다. 상당수의 MFC 클래스를사용할수있다. 유틸리티클래스, 집합클래스, 파일입출력클래스,... 알고리즘을개발할때유용하다. 1
MFC 콘솔응용프로그램작성 (1/2) 프로젝트생성 2
MFC 콘솔응용프로그램작성 (2/2) 1 단계옵션설정 3
MFC 콘솔응용프로그램분석 (1/5) 파일구성 StdAfx.h, StdAfx.cpp 미리컴파일된헤더 Console.rc, Resource.h 리소스정보 Console.h, Console.cpp 구현코드 4
MFC 콘솔응용프로그램분석 (2/5) Console.cpp 코드 CWinApp theapp; // 유일한전역응용프로그램객체 using namespace std; // 표준 C++ 라이브러리를사용할수있도록한다. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nretcode = 0; if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine( ), 0)) { cerr << _T("Fatal Error: MFC initialization failed") << endl; nretcode = 1; } 5
MFC 콘솔응용프로그램분석 (3/5) Console.cpp 코드 (cont d) else { CString strhello; strhello.loadstring(ids_hello); cout << (LPCTSTR)strHello << endl; } } return nretcode; 6
MFC 콘솔응용프로그램분석 (4/5) 문자열리소스 7
MFC 콘솔응용프로그램분석 (5/5) 실행파일생성과정 API & MFC 라이브러리 C/C++ 라이브러리 console.h, stdafx.h console.cpp, stdafx.cpp 컴파일러 console.obj stdafx.obj resource.h 링커 console.exe console.rc 각종리소스 ( 문자열, 아이콘,...) 리소스컴파일러 console.res 8
유틸리티클래스 (1/3) API 데이터타입 - 기본형 데이터타입 BOOL 또는 BOOLEAN BYTE, WORD, DWORD, LONG 정의 TRUE 또는 FALSE 8 비트, 16 비트, 32 비트, 32 비트 ( 모두 unsigned) U* unsigned * 예 ) UCHAR, UINT, ULONG,... HANDLE H* 32 비트핸들 * 을가리키는핸들예 ) HBITMAP( 비트맵 ), HBRUSH( 브러시 ), HCURSOR( 커서 ), HDC( 디바이스컨텍스트 ), HFONT( 폰트 ), HICON( 아이콘 ), HINSTANCE( 인스턴스 ), HMENU( 메뉴 ), HPEN( 펜 ), HWND( 윈도우 ) 9
유틸리티클래스 (2/3) API 데이터타입 - 기본형 (cont d) 데이터타입 P* = LP* (L)PSTR, (L)PCSTR (L)PTSTR, (L)PCTSTR COLORREF 정의 * 에대한포인터예1) PBOOL, PBYTE, PLONG,... 예2) LPBOOL, LPBYTE, LPLONG,... ANSI 문자열 ANSI 또는유니코드문자열 32비트 RGB (red, green, blue 각각 8비트 ) 색상값 10
유틸리티클래스 (3/3) API 데이터타입 - 구조체 데이터타입정의용도 POINT typedef struct tagpoint { LONG x; LONG y; } POINT, *PPOINT; 점의 x, y 좌표 ( 주로마우스커서의위치를나타낼때사용한다.) RECT typedef struct tagrect { LONG left; LONG top; LONG right; LONG bottom; } RECT, *PRECT; SIZE typedef struct tagsize { LONG cx; LONG cy; } SIZE, *PSIZE; 사각형왼쪽상단과오른쪽하단좌표 사각형폭과높이 11
CString 클래스 (1/3) 특성 가변길이문자열을지원한다. 프로그램실행도중문자열길이를자유롭게바꿀수있다. 최대길이는 (INT_MAX - 1) 이다. const char* 나 LPCTSTR 대신 CString 객체를직접사용할수있다. 이때는 CString 객체에대해 (LPCTSTR) 연산자를명시적으로적용하는것이좋다. CString str = " 안녕하세요."; cout << (LPCTSTR)str << endl; // 실행결과? cout << str << endl; // 실행결과? 12
CString 클래스 (2/3) 객체생성및초기화 CString str1; str1 = " 안녕하세요."; CString str2(" 오늘은 "); CString str3(str2); CString str4 = str1 + " " + str2 + " 즐거운날입니다."; cout << (LPCTSTR)str1 << endl; cout << (LPCTSTR)str2 << endl; cout << (LPCTSTR)str3 << endl; cout << (LPCTSTR)str4 << endl; str4 += " 하하하 "; cout << (LPCTSTR)str4 << endl; 13
CString 클래스 (3/3) CString::Format( ) CString str; str.format("x=%d, y=%d", 100, 200); MessageBox(NULL, (LPCTSTR)str, "CString 연습 ", MB_OK); CString::LoadString( ) CString str; str.loadstring(ids_hello); MessageBox(NULL, (LPCTSTR)str, "CString 연습 ", MB_OK); 14
CPoint, CRect, CSize 클래스 클래스정의 클래스이름 CPoint CRect CSize 정의 class CPoint : public tagpoint class CRect : public tagrect class CSize : public tagsize 업캐스팅 void SomeFunc(RECT* rect) {... } RECT r1; CRect r2; SomeFunc(&r1); // OK! SomeFunc(&r2); // OK! (Upcasting) 15
CPoint 클래스 생성자 CPoint::CPoint (int x, int y); 예 CPoint pt1(10, 20); POINT pt = {30, 40}; CPoint pt2(pt); pt1.offset(40, 30); pt2.offset(20, 10); if(pt1 == pt2) cout << " 두점의좌표가같습니다." << endl; else cout << " 두점의좌표가다릅니다." << endl; 16
CRect 클래스 (1/2) 생성자 CRect::CRect (int l, int t, int r, int b); 사각형의폭과높이 int CRect::Width (); int CRect::Height (); 좌표의포함여부판단 BOOL CRect::PtInRect (POINT point); 17
CRect 클래스 (2/2) 예 CRect rect1; rect1.setrect(0, 0, 200, 100); CRect rect2(0, 0, 200, 100); if(rect1 == rect2) cout << " 두사각형의좌표가같습니다." << endl; else cout << " 두사각형의좌표가다릅니다." << endl; RECT rect = {100, 100, 300, 200}; CRect rect3(rect); cout << rect3.width() << " " << rect3.height() << endl; CPoint pt(200, 150); if(rect3.ptinrect(pt)) cout << " 점이사각형내부에있습니다." << endl; else cout << " 점이사각형외부에있습니다." << endl; 18
CSize 클래스 생성자 CSize::CSize (int x, int y); 예 CSize size1(100, 200); SIZE size = {100, 200}; CSize size2(size); i cout << size2.cx << " " << size2.cy << endl; if(size1 == size2) // 두객체내용이같은지확인한다. cout << " 크기가같습니다." << endl; else cout << " 크기가다릅니다." << endl; 19
CTime, CTimeSpan 클래스 CTime 클래스 절대적인시간 ( 예를들면, 현재시각 ) 을처리한다. CTimeSpan 클래스 시간의차이값을처리한다. 두클래스모두내부적으로시간값을 64비트로저장한다. 20
CTime 클래스 예 // 현재시각구하기 CTime thetime; thetime = CTime::GetCurrentTime(); // 화면에출력하기 CString str = thetime.format( Format("%A %A, %B %d, %Y"); cout << (LPCTSTR)str << endl; str.format(" 현재시각은 %d시 %d분입니다.", thetime.gethour(), thetime.getminute()); cout << (LPCTSTR)str << endl; 21
CTimeSpan 클래스 예 // 시간차구하기 CTime starttime = CTime::GetCurrentTime(); Sleep(2000); CTime endtime = CTime::GetCurrentTime(); CTimeSpan elapsedtime = endtime - starttime; CString str; str.format("%d초가지났습니다.", elapsedtime.gettotalseconds()); cout << (LPCTSTR)str << endl; 22
배열클래스 (1/7) MFC 배열클래스의특징 배열인덱스를잘못참조하는경우오류를발생시킨다. 배열크기가가변적이다. 템플릿클래스 afxtempl.h 헤더파일 클래스이름데이터타입 사용예 CArray 프로그래머가결정 CArray<CPoint, CPoint&> array; 23
배열클래스 (2/7) 비템플릿클래스 afxcoll.h 헤더파일 클래스이름데이터타입사용예 CByteArray BYTE CByteArray array; CWordArray WORD CWordArray array; CDWordArray DWORD CDWordArray array; CUIntArray UINT CUIntArray array; CStringArray CString CStringArray array; CPtrArray void 포인터 CPtrArray array; CObArray CObject 포인터 CObArray array; 24
배열클래스 (3/7) 생성과초기화 CStringArray array; array.setsize(5); for(int i=0; i<5; i++){ CString string; string.format("%d년이지났습니다.", i*10); array[i] = string; } for(i=0; i<5; i++) cout << (LPCTSTR)array[i] << endl; 25
배열클래스 (4/7) 원소삽입과삭제 CUIntArray array; array.setsize(5); for(int i=0; i<5; i++) array[i] = i; // 배열원소삽입 array.insertat(3, 77);\ for(i=0; i<array.getsize(); i++) cout << array[i] << endl; cout << endl; // 배열원소삭제 array.removeat(3); for(i=0; i<array.getsize(); i++) cout << array[i] << endl; 26
배열클래스 (5/7) 템플릿배열클래스 #include "stdafx.h" #include "Console.h" #include <afxtempl.h> CWinApp theapp; using namespace std; struct Point3D { int x, y, z; Point3D() {} Point3D(int x0, int y0, int z0) { x = x0; y = y0; z = z0; } }; 27
배열클래스 (6/7) int _tmain(int argc, TCHAR* argv[ ], TCHAR* envp[ ]) { int nretcode = 0; if (!AfxWinInit(...)) { // 생략... } else { CArray<Point3D, Point3D&> array; array.setsize(5); for(int i=0; i<5; i++) { Point3D pt(i, i*10, i*100); array[i] = pt; } 28
배열클래스 (7/7) } for(i=0; i<5; i++) { Point3D pt = array[i]; cout << pt.x << ", " << pt.y << ", " << pt.z << endl; } } return nretcode; 29
리스트클래스 (1/8) MFC 리스트클래스 Head Tail 템플릿클래스 afxtempl.h 헤더파일 클래스이름데이터타입 사용예 CList 프로그래머가결정 CList<CPoint, CPoint&> list; 30
리스트클래스 (2/8) 비템플릿클래스 afxcoll.h 헤더파일 클래스이름데이터타입 사용예 CObList CObject 포인터 CObList list; CPtrList t void 포인터 CPtrList t list; CStringList CString CStringList list; 31
리스트클래스 (3/8) 생성과초기화 char *szfruits[ ] = { " 사과 ", " 딸기 ", " 포도 ", " 오렌지 ", " 자두 " }; CStringList list; for(int i=0; i<5; i++) list.addtail(szfruits[i]); 32
리스트클래스 (4/8) 순환 // 리스트제일앞에서출발하여순환한다. POSITION pos = list.getheadposition(); while(pos!= NULL){ CString string = list.getnext(pos); cout << (LPCTSTR)string << endl; } cout << endl; // 리스트제일뒤에서출발하여순환한다. pos = list.gettailposition(); while(pos!= NULL){ CString string = list.getprev(pos); cout << (LPCTSTR)string << endl; } 33
리스트클래스 (5/8) 항목삽입과삭제 // POSITION 타입의변수 pos 는이전의예제에서선언한것이다. pos = list.find(" 포도 "); list.insertbefore(pos, " 살구 "); list.insertafter(pos, " 바나나 "); list.removeat (pos); // 항목삽입과삭제후결과를확인한다. pos = list.getheadposition(); while(pos!= NULL){ CString string = list.getnext(pos); cout << (LPCTSTR)string << endl; } 34
리스트클래스 (6/8) 템플릿리스트클래스 #include "stdafx.h" #include "Console.h" #include <afxtempl.h> CWinApp theapp; using namespace std; struct Point3D { int x, y, z; Point3D() {} Point3D(int x0, int y0, int z0) { x = x0; y = y0; z = z0; } }; 35
리스트클래스 (7/8) int _tmain(int argc, TCHAR* argv[ ], TCHAR* envp[ ]) { int nretcode = 0; if (!AfxWinInit(...)) { // 생략... } else { CList<Point3D, Point3D&> list; for(int i=0; i<5; i++) list.addtail(point3d(i, i*10, i*100)); POSITION pos = list.getheadposition(); 36
리스트클래스 (8/8) } while(pos!= NULL) { Point3D pt = list.getnext(pos); cout << pt.x << ", " << pt.y << ", " << pt.z << endl; } } return nretcode; 37
맵클래스 (1/9) 맵동작원리 키 데이터 해시함수 데이터 MFC 맵클래스구현 키 데이터 키데이터키데이터키데이터 키데이터키데이터 38
맵클래스 (2/9) 템플릿클래스 afxtempl.h 헤더파일 클래스이름데이터타입 사용예 CMap 프로그래머가결정 CMap<CString, CString&, CPoint, CPoint&> map; 39
맵클래스 (3/9) 비템플릿클래스 afxcoll.h 헤더파일 클래스이름키 데이터사용예 CMapWordToOb WORD CObject 포인터 CMapWordToOb map; CMapWordToPtr WORD void 포인터 CMapWordToPtr map; CMapPtrToWord void 포인터 WORD CMapPtrToWord map; CMapPtrToPtr void 포인터 void 포인터 CMapPtrToPtr map; CMapStringToOb 문자열 CObject 포인터 CMapStringToOb map; CMapStringToPtr 문자열 void 포인터 CMapStringToPtr map; CMapStringToString 문자열 문자열 CMapStringToString map; 40
맵클래스 (4/9) 생성, 초기화, 검색 CMapStringToString map; map[" 사과 "] = "Apple"; map[" 딸기 "] = "Strawberry"; map[" 포도 "] = "Grape"; " map[" 우유 "] = "Milk"; CString str; if(map.lookup(" 딸기 ", str)) cout << " 딸기 -> " << (LPCTSTR)str << endl; 41
맵클래스 (5/9) 순환 POSITION pos = map.getstartposition(); while(pos!= NULL){ CString strkey, strvalue; map.getnextassoc(pos, strkey, strvalue); cout << (LPCTSTR)strKey << " -> " << (LPCTSTR)strValue << endl; } 42
맵클래스 (6/9) 삽입과삭제 map.removekey( RemoveKey(" 우유 "); map[" 수박 "] = "Watermelon"; // 항목삽입과삭제후결과를확인한다. // POSITION 타입의변수 pos는이전의예제에서선언한것이다. pos = map.getstartposition(); while(pos!= NULL){ CString strkey, strvalue; map.getnextassoc(pos, p strkey, strvalue); cout << (LPCTSTR)strKey << " -> " << (LPCTSTR)strValue << endl; } 43
맵클래스 (7/9) 템플릿맵클래스 #include "stdafx.h" #include "Console.h" #include <afxtempl.h> CWinApp theapp; using namespace std; UINT AFXAPI HashKey(CString& str) { LPCTSTR key = (LPCTSTR) str; UINT nhash = 0; while(*key) nhash = (nhash<<5) + nhash + *key++; return nhash; } 44
맵클래스 (8/9) int _tmain(int argc, TCHAR* argv[ ], TCHAR* envp[ ]) { int nretcode = 0; if (!AfxWinInit(...)) { // 생략... } else { CMap<CString, CString&, UINT, UINT&> map; map[cstring (" 사과 ")] = 10; map[cstring (" 딸기 ")] = 25; map[cstring (" 포도 ")] = 40; map[cstring (" 수박 ")] = 15; 45
맵클래스 (9/9) } UINT ncount; if(map.lookup(cstring(" 수박 "), ncount)) cout << " 수박 " << ncount << " 상자가남아있습니다." << endl; } return nretcode; 46