공부 중 메모/수업 예제 (KGCA)

Cpp Template 예제 (student mgr)

라이피 (Lypi) 2018. 7. 17. 16:00
반응형

출처 : KGCA 게임 아카데미(http://www.kgcaschool.com/). 수업 예제 파일


솔직히 제대로 이해 못한 예제.

다시 볼 필요 있음.


header.h

#pragma once
#include <iostream>
#include <string>
#include <tchar.h>
#include <new>

using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::wstring;
using std::wcout;
using std::bad_alloc;

//예외 클래스 A
//사용하진 않음
class ExceptA
{
public:
	void What()
	{
		cout << "ExceptA" << endl;
	}
};

//예외 클래스 B
//사용하진 않음
class ExceptB
{
public:
	void what() {
		cout << "stu::GetName() this==NULL" << endl;
	}
};

template<typename T> void swapP(T* a, T* b)
{
	a->m_pNext = b;
	b->m_pPrev = a;
}

sub.h

#pragma once
#include "Header.h"

//점수를 저장하는 클래스
class sub
{
private:
	int  m_iKor;
	int  m_iEng;
	int  m_iMat;
public:
	//생성자에만 멤버 초기화 목록을 사용할 수 있다. (...몰랐다)
	void set(int kor, int eng, int mat) 
	{
		m_iKor = kor;
		m_iEng = eng;
		m_iMat = mat;
	}
	int  getKor() { return m_iKor; }
	int  getEng() { return m_iEng; }
	int  getMat() { return m_iMat; }
public:
	sub() : m_iKor(0), m_iEng(0), m_iMat(0) {}
	~sub() {}
};

stu.h

#pragma once
#include "sub.h"


//학생 정보를 저장하는 클래스
class stu
{
private:
	int      m_iIndex;
	wstring  m_strName;
	sub      m_sub;			//sub클래스를 멤버로 포함
	int      m_iTotal;
	double   m_dAverage;

public:
	void     setIndex(int iIndex);
	int      getIndex();
	
	void     setName(wstring name);
	wstring  getName();
	
	void     setSub(int m_iKor, int m_iEng, int m_iMat); //sub클래스를 세팅
	sub      getSub();                                   //sub클래스를 반환
	
	int      getTotal();
	double   getAverage();
public:
	stu();
	~stu();
};

//멤버 함수 정의
void     stu::setIndex(int iIndex)
{
	m_iIndex = iIndex;
}

int      stu::getIndex()
{
	return m_iIndex;
}

void     stu::setName(wstring name)
{
	m_strName = name;
}

wstring  stu::getName()
{
	
	if (this == nullptr) {	throw 0; }

	//try {
	//	if (this == nullptr) {
	//		ExceptB();
	//	}
	//}
	//catch (ExceptB& ex) {
	//	cout << "Catch Except A" << endl;
	//	ex.what();
	//}
	
	return m_strName;
}

void     stu::setSub(int m_iKor, int m_iEng, int m_iMat)
{
	m_sub.set(m_iKor, m_iEng, m_iMat);
	m_iTotal = m_iKor + m_iEng + m_iMat;
	m_dAverage = m_iTotal / 3.0;
}

sub      stu::getSub()
{
	return m_sub;
}

int      stu::getTotal()
{
	return m_iTotal;
}
double   stu::getAverage()
{
	return m_dAverage;
}

stu::stu()
{
	//cout << "stu" << endl;
	m_dAverage = 0.0;
	m_iTotal = 0;
	m_iIndex = -1;
	//m_pNext = nullptr;
	//m_pPrev = nullptr;
}

stu::~stu()
{
	
	//cout << "~stu" << endl;
}

node.h

#pragma once
#include "Header.h"

//list클래스에서 사용할 node 클래스 템플릿
template <class T>
class node
{
	//멤버를 public으로 둔 상태
public:
	T*     m_pData;   //임의의 클래스를 데이터로 가리킬 수 있다.
	node*  m_pNext;   //다음 노드를 가리키는 포인터
	node*  m_pPrev;   //다음 노드를 가리키는 포인터

public:
	void del() 
	{
		delete m_pData;
	}

	node()
	{
		m_pData = nullptr;            //가리키고 있는 데이터가 없음
		m_pNext = m_pPrev = nullptr;  //이어져 있는 노드가 없음.
	}

	~node()
	{
		delete m_pData;
		//cout << "node end" << endl;
	}
};

list.h

#pragma once
#include "node.h"

//연결리스트 클래스 템플릿
template <class T>
class list
{
public:
	int       m_iCount; //리스트에 저장된 노드의 수를 저장하는 변수 
	node<T>*  m_pHead;  //리스트의 시작 노드를 가리키는 포인터
	node<T>*  m_pTail;  //리스트의   끝 노드를 가리키는 포인터

public:
	int       size();  //리스트에 저장된 노드의 수를 반환

	bool      addLinkHead(T* pStud); //리스트 앞에 노드를 추가
	bool      addLinkTail(T* pStud); //리스트 뒤에 노드를 추가
	bool      delLink(T* pStud); //리스트에서 노드를 삭제

	void      delList(); //리스트 전체 삭제

	T*        getData(int iIndex);  //선택한 위치의 데이터를 반환
	
	node<T>*  getHead();            //헤드 포인터를 반환
	node<T>*  getTail();            //테일 포인터를 반환

	bool      sort(bool bUp);      //노드를 정렬함

	list();
	~list();
};

//멤버 함수 정의
template <class T> int       list<T>::size() 
{
	return m_iCount; 
}

template <class T> bool      list<T>::addLinkHead(T* pData)
{
	node<T>* pNode = new node<T>();
	pNode->m_pData = pData;

	//리스트에 데이터가 없는 경우
	if (m_pHead == NULL) { 
		m_pHead = pNode;
		m_pTail = pNode;
	}
	//이미 데이터가 있는 경우
	else
	{
		node<T>* pFirst = m_pHead;
		m_pHead = pNode;

		pNode -> m_pNext = pFirst;
		pFirst  -> m_pPrev = pNode;
	}
	m_iCount++;
	return true;
}

template <class T> bool      list<T>::addLinkTail(T* pData)
{
	node<T>* pNode = new node<T>();
	pNode->m_pData = pData;

	//리스트에 데이터가 없는 경우
	if (m_pHead == NULL) {
		m_pHead = pNode;
		m_pTail = pNode;
	}
	//이미 데이터가 있는 경우
	else
	{
		node<T>* pLast = m_pTail;
		m_pTail = pNode;

		pNode -> m_pPrev = pLast;
		pLast   -> m_pNext = pNode;
	}
	m_iCount++;
	return true;
}

template <class T> bool      list<T>::delLink(T* pStud)
{
	return true;
}

template <class T> void      list<T>::delList()
{
	node<T>* pDelNode = nullptr;
	node<T>* pNode = m_pHead;
	
	while (pNode != NULL) 
	{
		pDelNode = pNode;
		pNode = pNode->m_pNext;
		delete pDelNode;
	}

	m_pHead = nullptr;
	m_pTail = nullptr;
}

template <class T> T*        list<T>::getData(int iIndex)
{
	node<T>* pNode = m_pHead;
	while (pNode != nullptr) {
		if (pNode->m_pData->getIndex() == iIndex) {
			T* pData = pNode->m_pData;
			return pData;
		}
		pNode = pNode->m_pNext;
	}
	return NULL;
}

template <class T> node<T>*  list<T>::getHead() 
{
	return m_pHead; 
}

template <class T> node<T>*  list<T>::getTail()
{
	return m_pTail;
}


template <class T> bool      list<T>::sort(bool bUp)
{
	//정렬
}

template <class T>           list<T>::list()
{
	m_pHead = nullptr;
	m_pTail = nullptr;
	m_iCount = 0;
}

template <class T>           list<T>::~list()
{
	delList();
	//cout << "linkedlist end" << endl;
}

hashTable.h

#pragma once
#include "List.h"


//해쉬테이블
//무슨 역할인지 1도 모르겠음
template <class T>
class hashTable
{
public:
	list<T>*  m_pArray;
	int       m_iLength;

public:
	int       hash(const wchar_t* pName);
	void      insert(T* newitem);
              hashTable(int iLength = 20);
              ~hashTable();
};


//멤버 함수 정의
template <class T> int   hashTable<T>::hash(const wchar_t* pName)
{
	int iKey = 5381;
	int c;
	size_t hash = 0x811c9dc5;

	while (c = *pName++) {
		hash ^= c;
		hash *= 0x01000193;
	}

	//int c;
	//while (c = *pName++) {
	//	iKey = ((iKey << 5) + iKey) + c;
	//}

	//int iValue = 0;
	//int iLen = _tcslen(pName);
	//for (int iCnt = 0; iCnt < iLen; iCnt++) {
	//	iValue += pName[iCnt];
	//}
	//int iKey = (iValue * iValue) % m_iLength;

	return hash % m_iLength;
}

template <class T> void  hashTable<T>::insert(T* newitem)
{
	int iIndex = hash((newitem->getName().c_str()));
	m_pArray[iIndex].addLinkTail(newitem);
}

template <class T>       hashTable<T>::hashTable(int iLength)
{
	m_pArray = new list<T>[iLength];
	m_iLength = iLength;
}

template <class T>       hashTable<T>::~hashTable()
{
	delete[] m_pArray;
}

mgr.h

#pragma once
#include "HashTable.h"
#include "stu.h"

class mgr
{
private:
	list<stu> m_InitList;

public:
	list<stu> m_List;
	//hashTable<stu> m_hash;

public:
	bool inputDataHead(int iCnt = 10);
	bool inputDataTail(int iCnt = 10);


	void showData();
	void showData(stu* pStd);

	void release();

	void sortTotal(bool bUp = true);
	void sortIndex(bool bUp = true);

	stu* find(int iCnt);
	node<stu>* swap(node<stu>* a, node<stu>* b);

	mgr() {}
	~mgr() { release(); }

};


bool mgr::inputDataHead(int iCnt) {
	for (int iSt = 0; iSt < iCnt; iSt++) {
		stu* pStu = new stu;
		wstring name;
		for (int iname = 0; iname < 3; iname++) {
			char iNmae = 65 + rand() % 26;
			name += iNmae;
		}
		pStu->setIndex(iSt);
		pStu->setName(name);
		pStu->setSub(rand() % 100, rand() % 100, rand() % 100);

		//m_hash.insert(pStu);
		m_List.addLinkTail(pStu);
	}
	return true;
}


bool mgr::inputDataTail(int iCnt) {
	for (int iSt = 0; iSt < iCnt; iSt++) {
		stu* pStu = new stu;
		wstring name;
		for (int iname = 0; iname < 3; iname++) {
			char iNmae = 65 + rand() % 26;
			name += iNmae;
		}
		pStu->setIndex(iSt);
		pStu->setName(name);
		pStu->setSub(rand() % 100, rand() % 100, rand() % 100);

		//m_hash.insert(pStu);
		m_List.addLinkTail(pStu);
	}
	return true;
}

void mgr::showData()
{
	for (node<stu>* pNode = m_List.getHead(); 
		pNode != nullptr; 
		pNode = pNode->m_pNext) {
		stu* pData = pNode->m_pData;
		if (pData) {
			wcout << pData->getIndex() << L" " << pData->getName() << L" " << pData->getTotal() << endl;
		}
	}
}
void mgr::showData(stu* pStd)
{
	if (pStd == nullptr) { return; }
	wcout << " ======= "
		<< pStd->getIndex() << L" "
		<< pStd->getName().c_str() << L" "
		<< pStd->getSub().getKor() << L" "
		<< pStd->getSub().getEng() << L" "
		<< pStd->getSub().getMat() << L" "
		<< pStd->getTotal() << L" "
		<< endl;
}

void mgr::release()
{
	m_List.delList();
}

void mgr::sortTotal(bool bUp)
{
	//m_List.Sort(bUp);
	//정렬
	node<stu>* pNodeSrc = m_List.getHead();
	//가장 작은 것을 앞으로 이동시킨다.
	while (pNodeSrc && pNodeSrc->m_pNext) {
		node<stu>* pNodeSwap = pNodeSrc;
		stu* pStd = pNodeSwap->m_pData;

		for (node<stu>* pNodeDesk = pNodeSrc->m_pNext;
			pNodeDesk != nullptr;
			pNodeDesk = pNodeDesk->m_pNext)
		{
			stu* pDesk = pNodeDesk->m_pData;
			if (pNodeSwap->m_pData->getTotal() > pDesk->getTotal())
			{
				pNodeSwap = pNodeDesk;
			}
		}
		// pNodeSrc보다 크거나 작은 것이 있다.
		if (pNodeSrc != pNodeSwap) 	{
			pNodeSrc = swap(pNodeSrc, pNodeSwap);
		} 
		else {
			//pNodeSrc보다 크거나 작은 것이 없다.
			pNodeSrc = pNodeSrc->m_pNext;
		}
	}
	m_List.m_pTail = pNodeSrc;
}

void mgr::sortIndex(bool bUp)
{
	//m_List.Sort(bUp);
	//정렬
	node<stu>* pNodeSrc = m_List.getHead();
	//가장 작은 것을 앞으로 이동시킨다.
	while (pNodeSrc && pNodeSrc->m_pNext) {
		node<stu>* pNodeSwap = pNodeSrc;
		stu* pStd = pNodeSwap->m_pData;

		for (node<stu>* pNodeDesk = pNodeSrc->m_pNext;
			pNodeDesk != nullptr;
			pNodeDesk = pNodeDesk->m_pNext)
		{
			stu* pDesk = pNodeDesk->m_pData;
			if (pNodeSwap->m_pData->getIndex() > pDesk->getIndex())
			{
				pNodeSwap = pNodeDesk;
			}
		}
		// pNodeSrc보다 크거나 작은 것이 있다.
		if (pNodeSrc != pNodeSwap) {
			pNodeSrc = swap(pNodeSrc, pNodeSwap);
		}
		else {
			//pNodeSrc보다 크거나 작은 것이 없다.
			pNodeSrc = pNodeSrc->m_pNext;
		}
	}
	m_List.m_pTail = pNodeSrc;
}


stu* mgr::find(int iCnt)
{
	stu* pData = m_List.getData(iCnt);
	return pData;
}


node<stu>* mgr::swap(node<stu>* a, node<stu>* b)
{
	//NULL
	node<stu>* aprev = a->m_pPrev;
	node<stu>* anext = a->m_pNext;
	node<stu>* bprev = b->m_pPrev;
	node<stu>* bnext = b->m_pNext;

	//Head <-> b
	if (aprev != nullptr) {
		swapP<node<stu>>(aprev, b);
#pragma region KGCA
		//aprev->m_pNext = b;
		//b->m_pPrev = aprev;
#pragma endregion
	}
	else {
		m_List.m_pHead = b;
		b->m_pPrev = nullptr;
	}
	// b <-> c anext(c)
	if (anext != b) {
		swapP<node<stu>>(b, anext);
#pragma region KGCA
		//b->m_pNext = anext; // b -> c
		//anext->m_pPrev = b; // b <- c
#pragma endregion
	//초기 a -> c -> b 경우
		if (anext->m_pNext == b) {
			swapP<node<stu>>(anext, a);
#pragma region KGCA
			//anext->m_pNext = a; // c -> a
			//a->m_pPrev = anext; // c <- a
#pragma endregion
		}
		else {
			swapP<node<stu>>(bprev, a);
#pragma region KGCA
			//bprev->m_pNext = a;
			//a->m_pPrev = bprev;
#pragma endregion
		}
	}
	else  // b <-> a
	{
		b->m_pNext = a;     // b -> a
		a->m_pPrev = b;     // b <- a
		a->m_pNext = bnext; // a -> d
		if (bnext != nullptr) {
			bnext->m_pPrev = a; // a <- d
		}
	}
	// a <-> d anext(d) // 초기 a -> c -> b -> d 경우
	if (bnext != nullptr) {
		swapP<node<stu>>(a, bnext);
#pragma region KGCA
		//aprev->m_pNext = b;
		//b->m_pPrev = aprev;
#pragma endregion
	} 
	else {
		a->m_pNext = nullptr; // a -> d
	}

	if (anext == b) {
		return a;
	}
	return anext;
}

main.cpp

#include "Mgr.h"



int main()
{
	mgr g_CtlMgr;
	g_CtlMgr.inputDataTail();
	g_CtlMgr.showData();

	cout << endl << "총점으로 정렬" << endl;
	g_CtlMgr.sortTotal();
	g_CtlMgr.showData();
	g_CtlMgr.showData(g_CtlMgr.find(8));
	

	//10명만 있기 때문에 11은 검색되지 못한다.
	try {
		if (g_CtlMgr.find(11) == nullptr ) {
			throw 11;
			g_CtlMgr.showData(g_CtlMgr.find(11));
		}
	}
	catch (int ex) {
		cout << ex << "번 학생을 찾을 수 없습니다." << endl;
	}

	cout << "종료";
}


반응형