1. 문제

 

10. 나라의 수도 맞추기 게임에 vector를 활용해보자. 나라 이름(nation)과 수도(capital) 문자열로 구성된 Nation 클래스를 만들고, vector<Nation> v;로 생성한 벡터를 이용하여 나라 이름과 수도 이름을 삽입할 수도 있고 랜덤하게 퀴즈를 볼 수도 있다. 

 

프로그램 내에서 벡터에 Nation 객체를 여러 개 미리 삽입하여 퀴즈를 보도록 하라. 실행 화면은 다음과 같으며, 저자는 9개 나라의 이름과 수도를 미리 프로그램에서 삽입하였다. 

 

문자열을 string 클래스를 이용하라.

 

2. 결과

 

 

3. 코드

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

class Nation {
	string nation;
	string capital;
public:
	Nation() { ; }
	void setNation(string na, string ca) {
		nation = na;
		capital = ca;
	}
	string getNation() { return nation; }
	string getCapital() { return capital; }
};


int main() {

	vector<Nation> v;
	Nation n;
	n.setNation("한국", "서울");
	v.push_back(n);
	n.setNation("중국", "베이징");
	v.push_back(n);
	n.setNation("일본", "도쿄");
	v.push_back(n);
	n.setNation("베트남", "하노이");
	v.push_back(n);
	n.setNation("인도", "뉴델리");
	v.push_back(n);
	n.setNation("필리핀", "마닐라");
	v.push_back(n);
	n.setNation("타이", "방콕");
	v.push_back(n);
	n.setNation("몰디브", "몰레");
	v.push_back(n);
	n.setNation("미국", "와싱턴");
	v.push_back(n);

	srand((unsigned)time(0));
	int sel;
	bool exit = true;
	string na, ca;
	int num = v.size() + 1;
	int choice = 0;
	int random;

	cout << "***** 나라의 수도 맞추기 게임을 시작합니다. *****" << endl;

	while (exit) {
		cout << "정보 입력: 1, 퀴즈: 2, 종료: 3 >> ";
		cin >> sel;

		switch (sel) {
		case 1:
			cout << "현재 " << v.size() << "개의 나라가 입력되어 있습니다." << endl;
			cout << "나라와 수도를 입력하세요(no no 이면 입력끝)" << endl;
			while (1) {
				cout << num << ">>";
				cin >> na >> ca;

				for (int i = 0; i< num - 1; i++) {
					if (v[i].getNation() == na) {
						cout << "already exists !!" << endl;
						choice = 1;
						break;
					}
				}
				if (na == "no" && ca == "no") break;
				else if (choice == 0) {
					n.setNation(na, ca);
					v.push_back(n);
					num++;
				}
				choice = 0;
			}
			break;
		case 2:
			while (1) {
				random = rand() % v.size();
				cout << v[random].getNation() << "의 수도는?";
				cin >> ca;
				if (ca == "exit") break;
				if (v[random].getCapital() == ca)
					cout << "Correct !!" << endl;
				else
					cout << "NO !!" << endl;
			}
			break;
		case 3:
			exit = false;
			break;
		}
	}
}

 

4. 설명

 

 

나라 이름과 수도 이름을 가지고 있는 Nation 클래스를 만든 후 이를 vector의 push_back으로 삽입합니다.

 

1번 입력에서 나올 때는 no no 즉 나라 이름과 수도 이름으로 no가 입력되었을 때 입력을 종료하도록 합니다.

 

2번 퀴즈에서는 exit가 입력되면 퀴즈가 종료되도록 합니다.

 

1. 문제

 

9. STL의 vector 클래스를 이용하는 간단한 프로그램을 작성해보자. vector 객체를 생성하고, 키보드로부터 정수를 입력받을 때마다 정수를 벡터에 삽입하고 지금까지 입력된 수와 평균을 출력하는 프로그램을 작성하라. 0을 입력하면 프로그램이 종료한다.

 

2. 결과

 

 

3. 코드

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

int main() {
	vector<int> v;
	int n;
	double avg;

	while(1) {
		cout << "정수를 입력하세요(0을 입력하면 종료)>>";
		cin >> n;
		v.push_back(n);
		if( n == 0) break;
		
		int sum=0;
		for(int i=0; i<v.size(); i++) {
			cout << v.at(i) << " ";
			sum += v.at(i);
		}
		
		avg = (double)sum / v.size();
		cout << endl << "평균 = " << avg << endl;
	}
}

 

 

4. 설명

 

 

push_back(n)으로 n을 뒤로 push(삽입) 합니다.

 

at(i)로 인덱스 i번 째의 수를 가져옵니다.

 

평균 avg를 구할 때는 소숫점 아래 부분까지 구하므로 (double)형으로 형변환을 해준 후 계산한다.

 

 

 

1. 문제

 

8. 문제 7을 푸는 다른 방법을 소개한다.

bigger() 함수의 다음 라인에서 > 연산자 때문에

 

T에 Circle과 같은 클래스 타입이 대입되면, 구체화가 실패하여 컴파일 오류가 발생한다. 이 문제를 해결하기 위해 다음과 같은 추상 클래스 Comparable을 제안한다.

 

Circle 클래스가 Comparable을 상속받아 순수 가상 함수를 모두 구현하면, 앞의 bigger() 템플릿 함수를 사용하는데 아무 문제가 없다. Circle뿐 아니라, Comparable을 상속받은 모든 클래스를 bigger()에 사용할 수 있다.

Comparable을 상속받은 Circle 클래스를 완성하고 문제 7의 main()을 실행하여 테스트 하라.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
using namespace std;

class Circle;

class Comparable {
public:
	virtual bool operator > (Circle& op2) = 0;
	virtual bool operator < (Circle& op2) = 0;
	virtual bool operator == (Circle& op2) = 0;
};
class Circle : public Comparable {
	int radius;
public:
	Circle(int radius = 1) { this->radius = radius; }
	int getRadius() { return radius; }
	bool operator > (Circle& op2) {
		if (this->radius > op2.radius) return true;
		else return false;
	}
	bool operator < (Circle& op2) {
		if (this->radius < op2.radius) return true;
		else return false;
	}
	bool operator == (Circle& op2) {
		if (this->radius == op2.radius) return true;
		else return false;
	}
};

template <class T>
T bigger(T a, T b) {
	if (a > b) return a;
	else return b;
}

int main() {
	int a = 20, b = 50, c;
	c = bigger(a, b);
	cout << "20과 50중 큰 값은 " << c << endl;
	Circle waffle(10), pizza(20), y;
	y = bigger(waffle, pizza);
	cout << "waffle과 pizza 중 큰 것의 반지름은 " << y.getRadius() << endl;
}

 

4. 설명

 

앞에서 배웠던 연산자 재정의와 순수가상함수를 이용하여 7번에 문제를 해결하는 것을 보여준다.

 

각 연산자에 알맞은 비교방법으로 radius를 비교해주면 올바른 결과를 얻을 수 있다.

 

 

 

1. 문제

 

7. 다음 프로그램은 컴파일 오류가 발생한다. 소스의 어디에서 왜 컴파일 오류가 발생하는가?

 

아래 결과와 같이 출력되도록 프로그램을 수정하라.

 

2. 결과

 

 

3. 코드

#include <iostream>
using namespace std;


class Circle {
	int radius;
public:
	Circle(int radius = 1) { this->radius = radius; }
	int getRadius() { return radius; }
};

template <class T>
T bigger(T a, T b) {
	if (a > b) return a;
	else return b;
}
Circle bigger(Circle a, Circle b) {
	if (a.getRadius() > b.getRadius()) return a;
	else return b;
}

int main() {
	int a = 20, b = 50, c;
	c = bigger(a, b);
	cout << "20과 50중 큰 값은 " << c << endl;
	Circle waffle(10), pizza(20), y;
	y = bigger(waffle, pizza);
	cout << "waffle과 pizza 중 큰 것의 반지름은 " << y.getRadius() << endl;
}

 

4. 설명

 

처음 20과 50을 비교할 때는 잘 실행되지만, 그 다음 Circlr 클래스 변수를 비교할려면 오류가 발생한다.

 

그 이유는 클래스 변수를 비교할 수는 없기 때문이다. 그러므로 클래스 변수 안의 있는 비교할 수 있는 멤버 변수 radius를 비교하도록 따로 구현을 해주어야 한다.

 

 

1. 문제

 

6. 다음 함수는 매개 변수로 주어진 int 배열 src에서 배열 minus에 들어있는 같은 정수를 모두 삭제한 새로운 int 배열을 동적으로 할당받아 리턴한다. retSize는 remove() 함수의 실행 결과를 리턴하는 배열의 크기를 전달받는다.

 

템픔릿을 이용하여 remove를 일반화하라.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
using namespace std;

template <class T>
T* remove(T src[], int sizeSrc, T minus[], int sizeMinus, int& retSize) {
	int count = 0, choice = sizeMinus;
	T* re = new T;

	for (int i = 0; i<sizeSrc; i++) {
		for (int j = 0; j<sizeMinus; j++)
			if (src[i] != minus[j]) choice--;

		if (choice == 0) {
			re[count] = src[i];
			count++;
		}
		choice = sizeMinus;
	}
	retSize = count;
	return re;
}

int main() {
	int x[] = { 1, 10, 100, 5, 4 };
	int y[] = { 4, 6, 10, 9 };
	int size = 0;
	int* result = remove(x, 5, y, 4, size);

	for (int i = 0; i<size; i++)
		cout << result[i] << ' ';
	cout << endl;
}

 

4. 설명

 

x배열의 각 원소들을 for문으로 각 y원소들과 비교하여 제거할지를 판단합니다.

 

size 변수는 remove함수 내에서 배열의 크기를 저장합니다.

 

 

 

1. 문제

 

5. 다음 함수는 매개 변수로 주어진 두 개의 int 배열을 연결한 새로운 int 배열을 동적할당 받아 리턴한다.

 

concat가 int 배열뿐 아니라 다른 타입의 배열도 처리할 수 있도록 일반화하라.

 

2. 결과

 

 

 

3. 코드

#include <iostream>
using namespace std;

template <class T>
T* concat(T a[], int sizea, T b[], int sizeb) {
	T* sum = new T[sizea + sizeb];
	int i;
	for (i = 0; i<sizea; i++)
		sum[i] = a[i];
	for (i = sizea; i<sizea + sizeb; i++)
		sum[i] = b[i - sizea];
	return sum;
}

int main() {
	int x[] = { 1, 10, 100, 5, 4 };
	int y[] = { 7, 6, 10, 9 };
	int *a = concat(x, 5, y, 4);

	for (int i = 0; i<9; i++)
		cout << a[i] << ' ';
	cout << endl;
}

 

4. 설명

 

새로운 배열 하나를 동적 생성하여서 두 배열의 원소들을 차례대로 대입합니다.

 

main의 for문에서 9처럼 일일이 숫자를 입력하고 싶지 않으시다면

 

int size = sizeof(x) / 4 + sizeof(y)/4; 를 중간에 대입 후  size까지 for문을 실행시키면 됩니다.

 

이는 물론 x와 y가 int형 배열일 경우에 해당합니다.

 

 

 

1. 문제

 

4. 배열에서 원소를 검색하는 search() 함수를 템플릿으로 작성하라. search()의 첫번째 매개 변수는 검색하고자 하는 원소 값이고, 두 번째 매개 변수는 배여이며, 세 번째 매개 변수는 배열의 개수이다. search() 함수가 검색에 성공하면 true를, 아니면 false를 리턴한다. search()의 호출 사례는 다음과 같다.

 

2. 결과

 

 

 

3. 코드

#include <iostream>
using namespace std;

template <class T>
bool search( T se, T a[], int size) {
	for(int i=0; i<size; i++)
		if( a[i] == se ) return true;
	return false;
}

int main() {
	int x[] = {1, 10, 100, 5, 4};
	
	if( search(100, x, 5) ) cout << "100이 배열 x에 포함되어 있다" << endl;
	else cout << "100이 배열 x에 포함되어 있지 않다" << endl;
}

 

4. 설명

 

 

함수가 실행되면 size만큼 for문을 돌려서 찾는 원소가 있는지 비교합니다.

 

위 x에서 100이 아닌 다른 원소를 입력하면 포함되어 있지 않다는 결과가 나오게 됩니다.

 

 

1. 문제

 

3. 배열의 원소를 반대 순서로 뒤집는 reverseArray() 함수를 템플릿으로 작성하라. reverseArray()의 첫 번째 매개 변수는 배열에 대한 포인터이며 두 번째 매개 변수는 배열의 개수이다. reverseArray()의 호출 사례는 다음과 같다.

 

2. 결과

 

 

 

3. 코드

#include <iostream>
using namespace std;

template <class T>
void reverseArray(T a[], int size) {
	T imsi;
	for (int i = 0; i<size / 2; i++) {
		imsi = a[i];
		a[i] = a[size - i - 1];
		a[size - i - 1] = imsi;
	}
}

int main() {
	int x[] = { 1, 10, 100, 5, 4 };

	reverseArray(x, 5);
	for (int i = 0; i<5; i++) cout << x[i] << ' ';
}

 

4. 설명

 

 

원소의 순서를 뒤집는 reverseArray 함수입니다.

 

원소의 개수 size가 짝수일 경우 0~size/2까지 즉 size/2번 for문을 실행하여서 원소의 순서를 뒤집어주고,

 

size가 홀수일 경우는 가운데의 값의 순서는 그대로이므로 (size/2)-0.5번 만큼만 for문을 실행하여주면 순서가 뒤집어집니다.

 

+ Recent posts