1. 문제

 

2. Book 객체를 활용하는 사례이다.

 

(1) 세 개의 == 연산자 함수를 가진 Book 클래스를 작성하라.

 

 

2. 결과

 

 

 

3. 코드

 


#include <iostream>
#include <string>
using namespace std;

class Book {
	string title;
	int price, pages;
public : 
	Book(string title="", int price=0, int pages=0) {
		this->title = title; this->price = price; this->pages = pages;
	}
	void show() {
		cout << title << ' ' << price << "원 " << pages << " 페이지" << endl;
	}
	string getTitle() { return title; }
	bool operator == (int n) { 
		if( price == n ) return true;
		else return false;
	}
	bool operator == (string n) { 
		if( title == n ) return true;
		else return false;
	}
	bool operator == (Book n) {
		if( title == n.title && price == n.price && pages == n.pages ) return true;
		else return false;
	}
};

int main() {
	Book a("명품 C++", 30000, 500), b("고품 C++", 30000, 500);
	if( a == 30000 ) cout << "정가 30000원" << endl;
	if( a == "명품 C++" ) cout << "명품 C++ 입니다." << endl;
	if( a == b ) cout << "두 책이 같은 책입니다." << endl;
}

 

 

4. 설명

 

 연산자 "=="를 오버로딩하여서 매개 변수가 다른 함수 3개를 구현합니다.

 

매개변수가 int 형일 시 price와 비교를 하도록 구현하고, string 형 일시 title과 비교하도록합니다.

 

또한, Book 클래스와 사용했을 시 tilte, price, pages를 비교하여서 다 같다면 return true;를 아니면 return false;를 해줍니다.

 

 


 

 

 

1. 문제

 

2. Book 객체를 활용하는 사례이다.

 

(2). 세 개의 == 연산자를 프렌드 함수로 작성하라.

 

 

2. 결과

 

 

 

3. 코드

 


#include <iostream>
#include <string>
using namespace std;

class Book {
	string title;
	int price, pages;
public : 
	Book(string title="", int price=0, int pages=0) {
		this->title = title; this->price = price; this->pages = pages;
	}
	void show() {
		cout << title << ' ' << price << "원 " << pages << " 페이지" << endl;
	}
	string getTitle() { return title; }
	friend bool operator == (Book b, int n);
	friend bool operator == (Book b, string n);
	friend bool operator == (Book b1, Book b2);
};
bool operator == (Book b, int n) { 
		if( b.price == n ) return true;
		else return false;
	}
bool operator == (Book b, string n) { 
		if( b.title == n ) return true;
		else return false;
	}
bool operator == (Book b1, Book b2) {
		if( b1.title == b2.title && b1.price == b2.price && b1.pages == b2.pages ) return true;
		else return false;
	}

int main() {
	Book a("명품 C++", 30000, 500), b("고품 C++", 30000, 500);
	if( a == 30000 ) cout << "정가 30000원" << endl;
	if( a == "명품 C++" ) cout << "명품 C++ 입니다." << endl;
	if( a == b ) cout << "두 책이 같은 책입니다." << endl;
}

 

 

4. 설명

 

 (1)번과 같은 기능을 하는 == 연산자 기능을 하는 함수들을 프렌드 함수로 작성하면 됩니다.

 

Book b 변수를 추가적으로 매개변수로 받아서 이용한다는 점과 friend를 붙이는 것 빼고는 구현하는 방법은 똑같습니다.

 

 

 

 

1. 문제

 

1. Book 객체에 대해 다음 연산을 하고자 한다.

 

(1) +=, -= 연산자 함수를 Book 클래스의 멤버 함수로 구현하라.

 

 

2. 결과

 

 

3. 코드

 


#include <iostream>
#include <string>
using namespace std;

class Book {
	string title;
	int price, pages;
public : 
	Book(string title="", int price=0, int pages=0) {
		this->title = title; this->price = price; this->pages = pages;
	}
	void show() {
		cout << title << ' ' << price << "원 " << pages << " 페이지" << endl;
	}
	string getTitle() { return title; }
	void operator +=(int n) { price += n; }
	void operator -=(int n) { price -= n; }
};

int main() {
	Book a("청춘", 20000, 300), b("미래", 30000, 500);
	a += 500;
	b -= 500;
	a.show();
	b.show();
}

 

4. 설명

 

 operator를 사용하여서 클래스의 멤버 함수로 구현 하였습니다. 

 

"+=" 연산을 하면 클래스 변수에 저장되어 있는 price 값이 입력한 값과 += 계산이 되도록 구현하시면 됩니다.

 

이와 마찬가지로 "-=" 연산도 클래스 변수에 저장되어 있는 price 값과 -= 계산이 되도록 구현하면 됩니다.

 

 


 

 

1. 문제

 

1. Book 객체에 대해 다음 연산을 하고자 한다.

 

(2) +=, -= 연산자 함수를 Book 클래스 외부 함수로 구현하라.

 

 

2. 결과

 

 

3. 코드

 


#include <iostream>
#include <string>
using namespace std;

class Book {
	string title;
	int price, pages;
public : 
	Book(string title="", int price=0, int pages=0) {
		this->title = title; this->price = price; this->pages = pages;
	}
	void show() {
		cout << title << ' ' << price << "원 " << pages << " 페이지" << endl;
	}
	string getTitle() { return title; }
	friend Book operator +=(Book &b, int n);
	friend Book operator -=(Book &b, int n);
};
Book operator +=(Book &b, int n) {
	b.price += n; 
	return b;
}
Book operator -=(Book &b, int n) { 
	b.price -= n; 
	return b;
}

int main() {
	Book a("청춘", 20000, 300), b("미래", 30000, 500);
	a += 500;
	b -= 500;
	a.show();
	b.show();
}

 

 

4. 설명

 

 클래스 외부 함수로 구현하기 위해서는 클래스의 public이 아닌 멤버 변수에도 접근해야 되므로 프렌드 함수로 구현 합니다.

 

프렌드 함수로 구현할 시 (Book &b, int n) 이처럼 b를 참조 변수로 선언합니다. 그런 후 구현부에서 b.price += n; 을 한 후 다시 b를 return 합니다.

 

 

main 함수에서 보면 "a += 500;" 에서 b가 Book 클래스 변수 a이고 int n이 500 이라고 보시면 됩니다.

 

 

 

 

1. 문제

 

Up & down 게임 만들기

 

Up & Down 게임 프로그램을 작성해보자. 게임에 참석하는 사람은 2명이며, 번갈아 가며 다음과 같이 숨겨진 답에 접근해 간다. Up & Down 게임은 전체적으로 UpAndDownGame 클래스로 작성하고 static 멤버로만 구성하라. 선수를 표현하기 위해 Person 클래스를 작성하고 main() 함수는 프로그램을 시작시키는 기능 정도로만 구현하라.

 

 

 

2. 결과

 

 

 

 

3. 코드

 

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;

class Person {
	string s[2];
	int n;
public :
	Person(){ s[0] = "류현진"; s[1] = "손연재"; n=-1; }
	string getName() { 
		n++;
		if( n == 2) {
			n = 0;
			return s[n];
		}
		else return s[n]; }
};

class UpAndDownGame {
	static int result;
	static int low, high;
public :
	UpAndDownGame() { srand( (unsigned)time(0) ); }
	static void Game() ;
};

int UpAndDownGame::high = 99;
int UpAndDownGame::low = 0;
int UpAndDownGame::result = 0;
void UpAndDownGame::Game() {
	int number; Person p;
	cout << "Up & Down 게임을 시작합니다." << endl;
	result = rand() % 100;
	while(1) {
		string name = p.getName();
		cout << "답은 " << low << "과 " << high << "사이에 있습니다." << endl;
		cout << name << ">>";
		cin >> number;

		if( number > result )
			high = number;
		else if( number < result )
			low = number;
		else { 
			cout << name << "이(가) 이겼습니다!!" << endl;
			break;
		}
	}
}

int main() {
	UpAndDownGame gg;
	gg.Game();
}

 

 

4. 설명

 

- Person 클래스는 사람의 이름을 저장하는 클래스 입니다. 

 

-> 생성자에서 이름을 초기화 합니다.

-> getName() 멤버 함수는 저장된 이름들을 호출할 때마다 번갈아가면서 return 합니다.

 

 

- UpAndDownGame 클래스는 게임을 전체적으로 관리하는 클래스입니다.

 

-> static 변수 low, high, result를 선언합니다.

-> static 변수를 이용하기 위하여 game() 멤버 함수도 static으로 선언합니다.

 

-> 입력받은 값이 정답보다 크다면 high값을 수정하고 작다면 low 값을 수정하고 같다면 종료합니다.

 

※ 주의하실 점은 랜덤 한 수( result)는 while문 밖에서 한 번만 구해 저장하여야 합니다. 또한 이름은 while안에서 string 변수 하나의 저장을 해놔야지 나중에 종료 시 누가 이겼는지를 이름을 이용할 수 있습니다.

 

 

 

 

1. 문제

 

8. 디버깅에 필요한 정보를 저장하는 Trace 클래스를 만들어보자. 저자의 경험에 의하면, 멀티태스크 프로그램을 개발하거나 특별한 환경에서 작업할 때, Visual Studio의 디버거와 같은 소스 레벨 디버거를 사용하지 못하는 경우가 더러 있었고, 이때 실행 도중 정보를 저장하기 위해 Trace 클래스를 만들어 사용하였다. Trace 클래스를 활용하는 다음 프로그램과 결과를 참고하여 Trace 클래스를 작성하고 전체 프로그램을 완성하라. 디버깅 정보는 100개로 제한한다.

 

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
#include <string>
using namespace std;

class Trace {
	static string *tag;
	static string *info;
	static int num;
public :
	static void put(string ptag, string pinfo) {
		tag[num] = ptag;
		info[num] = pinfo;
		num++;
	}
	static void print(string ptag="모든") {
		if( ptag == "모든" )
			cout << "----- " << ptag << " Trace 정보를 출력합니다. -----" << endl;
		else
			cout << "----- " << ptag << "태그의 Trace 정보를 출력합니다. -----" << endl;

		for(int i=0; i< num;i++) {
			if( ptag == "모든" )  cout << tag[i] <<":" << info[i] << endl;
			else if( tag[i] == ptag )  cout << tag[i] <<":" << info[i] << endl;
		}
	}
};
int Trace::num = 0;
string *Trace::tag = new string[100];
string *Trace::info = new string[100];

void f() {
	int a, b, c;
	cout << "두 개의 정수를 입력하세요>>";
	cin >> a >> b;
	Trace::put("f()", "정수를 입력 받았음");
	c = a + b;
	Trace::put("f()", "합 계산");
	cout << "합은 " << c << endl;
}

int main() {
	Trace::put("main()", "프로그램 시작합니다");
	f();
	Trace::put("main()", "종료");

	Trace::print("f()");
	Trace::print();
}

 

 

4. 설명

 

 static으로 string*형 변수 tag, info와 int형 num을 선언합니다.

 

- static 변수를 초기화하기 위해서는 클래스 밖에서 "::"를 사용하여서 초기화하여야 합니다. 이러한 이유는 static 변수는 언제든 사용할 수 있어야 하지만 클래스 생성자 안에서 초기화를 한다면 클래스의 객체가 생성되기 전까지는 초기화가 실행되지 않기 때문입니다.

 

-> 디버깅 정보는 100개로 제한하므로 크기가 100인 배열로 초기화 합니다.

-> 마찬가지로 static 변수를 사용하기 위해서는 static 메소드 이어야 합니다.

 

 

 

- print()함수는 매개변수 태그를 하나 입력받아 그의 해당하는 태그를 출력합니다. 여기서 매개변수의 "모든"이라는 디폴트 값을 주어서 매개변수 없을 경우 모든 태그와 정보를 출력하도록 하였습니다.

 

 

 

1. 문제

 

7. 다음과 같은 static 멤버를 가진 Random 클래스를 완성하라(Open Challenge 힌트 참고). 그리고 Random 클래스를 이용하여 다음과 같이 랜덤한 값을 출력하는 main() 함수도 작성하라. main()에서 Random 클래스의 seed() 함수를 활용하라.

 

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

class Random {
public :
	static void seed() { srand( (unsigned)time(0) ); }
	static int nextInt(int min=0, int max=32767 ) { 
		int n = min + (rand() % (max-min+1) ); 
		return n; 
	}
	static char nextAlphabet();
	static double nextDouble();
};
char Random::nextAlphabet() {
	int n = rand() % 2;
	if( n == 0) {
		n = 65 + rand() % 26;
		return n;
	}
	else {
		n = 97 + rand() % 26;
		return n;
	}
}
double Random::nextDouble() {
	double n = rand() / (double)(RAND_MAX+1);

	return n;
}

int main() {
	Random::seed();
	int i;

	cout << "1에서 100까지 랜덤한 정수 10개를 출력합니다" << endl;
	for(i=0; i<10; i++) cout << Random::nextInt(1, 100) << ' ';

	cout << endl << "알파벳을 랜덤하게 10개를 출력합니다" << endl;
	for(i=0; i<10; i++) cout << Random::nextAlphabet() << ' ';

	cout << endl << "랜덤한 실수를 10개를 출력합니다" << endl;
	for(i=0; i<5; i++) cout << Random::nextDouble() << ' ';
	cout << endl;
	for(i=0; i<5; i++) cout << Random::nextDouble() << ' ';
	cout << endl;

}

 

 

4. 설명

 

- nextInt()함수는 랜덤한 정수를 구하는 함수 입니다.

 

 이전 글들에서도 설명한적이 있듯이 범위가 min ~ max의 랜덤한 수를 구하기 위해서는

 

int n = min + ( rand() % (max-min+1) );

을 해주셔야 합니다.

=> 이러한 이유는 간단하게 말하자면 rand() % 100 은 rand()가 어떤 랜덤한 수가 와도 나머지이므로 결과는 0~99 사이의 값 입니다. 이 사실을 이해하셨다면 스스로 범위를 잘 조절할 수 있으실 겁니다.

 

 

- nextAlphabet() 함수는 랜덤한 알파벳을 리턴하는 함수입니다.

 

 랜덤한 알파벳인데 소문자인지 대문자인지도 랜덤하게 결정되므로 우선 

 
int n = rand() % 2;

 

를 하여서 0과 1중 랜덤하게 변수 n의 저장합니다.

 

=> 그 다음 0일 경우는 65~90 무작위 대문자를 return 합니다. 또한 1일 경우 97~122 무작위 소문자를 return 합니다.

 

이러한 방법으로 랜덤하게 알파벳을 구할 수 있습니다.

 

 

- nextDouble() 함수는 범위가 0 이상 1미만인 랜덤한 실수를 return하는 함수입니다.

 

double n = rand() / (double)(RAND_MAX+1);

을 하면 0이상 1미만의 무작위 실수를 구할 수 있습니다.

 

=> RAND_MAX는 헤더파일 cstdlib의 정의 되어 있으므로 랜덤 값 중 최대 값 32767을 저장하고 있습니다. 그래서 +1을 해주어서 1미만의 값이 나오도록 합니다.

 

 

1. 문제

 

6. 동일한 크기의 배열을 변환하는 다음 2개의 static 멤버 함수를 가진 ArrayUtility2 클래스를 만들고, 이 클래스를 이용하여 아래 결과와 같이 출력되도록 프로그램을 완성하라.

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class ArrayUtility2 {
public :
	static int* concat(int s1[], int s2[], int size){
		int* p = new int[size];
		int n = size/2;
		for(int i=0; i< n; i++) {
			p[i] = s1[i];
			p[i+n] = s2[i];
		}
		return p;
	}
	static int* remove(int s1[], int s2[], int size, int& retSize) {
	
		for(int i=0; i< size; i++) {
			for(int j=0; j< size; j++) {
			 if(s1[i] == s2[j] ) s1[i] =NULL;
			} 
		}
		for(int i=0; i< size ; i++) 
			if(s1[i] !=NULL) retSize++;
		
		int *p = new int [retSize];
		int n=0;
		for(int i=0; i< size; i++)
			if(s1[i] !=NULL ) { p[n] = s1[i]; n++; }

		if(retSize == 0) return NULL;
		else return p;
	}
};

int main() {
	int x[5], y[5], retsize=0, size;

	cout << "정수를 5 개 입력하라. 배열 x에 삽입한다>>";
	cin >> x[0] >> x[1] >> x[2] >> x[3] >> x[4];
	cout << "정수를 5 개 입력하라. 배열 y에 삽입한다>>";
	cin >> y[0] >> y[1] >> y[2] >> y[3] >> y[4];
	cout << "합친 정수 배열을 출력한다." << endl;

	size = sizeof(x)/4 + sizeof(y)/4;
	int *temp = ArrayUtility2::concat( x, y, size );
	for(int i=0; i< size;i++) cout << temp[i] << ' ';
	cout << endl;

	size = sizeof(x)/4;
	temp = ArrayUtility2::remove( x, y, size, retsize );
	cout << "배열 x[]에서 y[]를 뺀 결과를 출력한다. 개수는 " << retsize << endl;
	for(int i=0; i< retsize;i++) cout << temp[i] << ' ';
	cout << endl;
}

 

 

 

4. 설명

 

static int* concat() 함수는 2개의 int형 배열과 size를 입력 받으면, 크기가 size만큼인 int형 배열을 동적으로 생성한 후 2개의 배열을 연결한 배열 하나를 return 합니다.

 

static int* remove() 함수는 2개의 배열과 size 그리고 참조 변수 retSize를 입력 받습니다. 

 

그 후 첫 번째 배열과 두 번째 배열을 비교하여서 첫 번째 배열의 요소 중 두 번째 배열의 요소와 일치하지 않는 것의 수를 구한 후 retSize에 저장합니다. 그리고 이 과정에서 첫 번째 배열에서 일치하는 요소는 NULL값을 삽입합니다.

 

그 후 retSize 크기만큼의 int형 배열을 동적으로 생성한 후 첫 번째 배열의는 첫 번째 배열과 두 번째 배열 중 일치하지 않는 값 빼고는 다 NULL을 삽입하였으므로 NULL이 아니라면 동적 생성했던 배열의 요소로 삽입합니다.

 

 

그리고 이 동적 생성하였던 배열을 return함으로써 일치하지 않는 요소들만 저장되어있는 배열을 생성합니다.

 

 

 

1. 문제

 

5. 동일한 크기로 배열을 변환하는 다음 2개의 static 멤버 함수를 가진 ArrayUtility 클래스를 만들어라.

 

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class ArrayUtility {
public :
	static void IntToDouble(int source[], double dest[], int size) {
		for(int i=0; i< size; i++)
			dest[i] = (double)source[i];
	}
	static void doubleToInt(double source[], int dest[], int size) {
		for(int i=0; i< size; i++)
			dest[i] = (int)source[i];
	}
};

int main() {
	int x[] = {1,2,3,4,5};
	double y[5];
	double z[] = {9.9, 8.8, 7.7, 6.6, 5.6};

	ArrayUtility::IntToDouble(x, y, 5);
	for(int i=0; i<5; i++) cout << y[i] << ' ';
	cout << endl;

	ArrayUtility::doubleToInt(z, x, 5);
	for(int i=0; i<5; i++) cout << x[i] << ' ';
	cout << endl;
}

 

 

4. 설명

 

크기가 size인 int형 배열의 요소들을 double형으로 형변환 한 후 double 배열의 저장하는 IntToDouble()을 강제 형변환을 이용하여서 구현 합니다.

 

double형을 int형으로 바꾸는 doubleToInt() 함수도 마찬가지로 강제형변환을 이용하여서 int형으로 변환하도록 구현 합니다.

 

 

※ double형을 int형으로 강제 형변환하면서 데이터 손실이 발생하였습니다.

 

 

1. 문제

 

4. 다음 클래스에 중복된 생성자를 디폴트 매개 변수를 가진 하나의 생성자로 작성하고 테스트 프로그램을 작성하라.

 

 

2. 결과

 

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class MyVector {
	int *mem;
	int size;
public :
	MyVector(int n=100, int val=0);
	~MyVector() { delete [] mem; }
	void show() { for(int i=0; i<size;i++) cout << mem[i] << ' '; cout << endl; }
};

MyVector::MyVector(int n, int val) {
	mem = new int [n];
	size =  n;
	for(int i=0; i<size; i++) mem[i] = val;
}

int main() {

	MyVector a, b(4,5);
	
	a.show();
	b.show();
}

 

 

4. 설명

 

주어진 코드의 생성자를 살펴보면 디폴트 매개 값을 가진 MyVector(int n=100, int val=0); 생성자를 생성할 수 있습니다.

 

이 생성자는 크기가 n인 int형 배열을 동적으로 생성한 후 val 값으로 각 원소들을 초기화 하는 기능을 합니다.

 

구현이 잘 되었는지 확인하기 위하여 void show()함수를 생성하여서 결과를 확인 합니다.

 

또한 소멸자에서는 동적으로 생성하였던 int형 배열을 해제 시켜 줍니다.

 

+ Recent posts