[C++] 명품C++ Programming 8장 : 실습문제

녹차·2024년 6월 29일
0

C++

목록 보기
9/11

Chapter7 문제 [7/9]

문제 1~2에 적용되는 원을 추상화한 Circle 클래스가 있다.

class Circle{
    int radius;
public:
    Circle(int radius=0) { this->radius = radius; }
    int getRadius() { return radius; }
    void setRadius(int radius) { this->radius = radius; }
    double getArea() { return 3.14*radius*radius; }
};

8-1

다음 코드가 실행되도록 Circle을 상속받은 NamedCircle 클래스를 작성하고 전체 프로그램을 완성하라.

NamedCircle waffle(3, "waffle"); // 반지름이 3이고 이름이 waffle인 원
waffle.show();

[결과값]
반지름이 3인 waffle

#include<iostream>

using namespace std;

class Circle
{
	int r;
public:
	Circle(int r = 0) { this->r = r; }
	int getR() { return r; }
	void setR(int r) { this->r = r; }
	double getArea() { return 3.14 * r * r; }
};

class NameCircle : public Circle
{
	string name;
public:
	NameCircle(int r, string name)
	{
		this->setR(r);
		this->name = name;
	}
	void show() {
		cout << "반지름이 " << getR() << "인 " << name;
	};

};


int main()
{
	NameCircle waffle(3, "waffle");
	waffle.show();
}

8-2

다음과 같이 배열을 선언하여 다음 실행 결과가 나오도록 Circle을 상속받은 NamedCircle 클래스와 main() 함수 등 필요한 함수를 작성하라.

NamedCircle pizza[5];

[결과값]
5 개의 정수 반지름과 원의 이름을 입력하세요
1>> 5 크림피자
2>> 8 치즈피자
3>> 25 대왕피자
4>> 30 블랙홀피자
5>> 15 마늘피자
가장 면적이 큰 피자는 블랙홀피자입니다.

#include<iostream>

using namespace std;

class Circle
{
	int r;
public:
	Circle(int r = 0) { this->r = r; }
	int getR() { return r; }
	void setR(int r) { this->r = r; }
	double getArea() { return 3.14 * r * r; }
};

class NameCircle : public Circle
{
	string name;
public:
	NameCircle(int r = 0, string name = "")
	{
		this->setR(r);
		this->name = name;
	}
	void setName(string name) {
		this->name = name;
	};
	string getName() {
		return name;
	}
};


int main()
{
	NameCircle pizza[5];
	int pizzaR[5];
	string pizzaName[5];

	cout << "5 개의 정수 반지름과 원의 이름을 입력하세요" << endl;

	for (int i = 0; i < 5; i++)
	{
		cout << i + 1 << ">> ";
		cin >> pizzaR[i];
		pizza[i].setR(pizzaR[i]);

		cin >> pizzaName[i];
		pizza[i].setName(pizzaName[i]);

		cout << endl;
	}

	int bigR = 0;
	int bigNum = 0;

	for (int i = 0; i < 5; i++)
	{
		if (bigR < pizza[i].getR())
		{
			bigR = pizza[i].getR();
			bigNum = i;
		}
	}

	cout << "가장 면적이 큰 피자는 " << pizza[bigNum].getName() << "입니다";
}

문제 3~4에 적용되는 2차원 상의 한 점을 표현하는 Point 클래스가 있다.

class Point {
    int x,y;
public:
    point(int x, int y) { this->x = x; this->y = y; }
    int getX(){ return x; }
    int getY(){ return y; }
protected:
    void move(int x, int y) { this->x = x; this->y = y; }
};

8-3

다음 main() 함수가 실행되도록 Point 클래스를 상속받은 ColorPoint 클래스를 작성하고, 전체 프로그램을 완성하라.

int main() {
    ColorPoint cp(5, 5, "RED");
    cp.setPoint(10, 20);
    cp.setColor("BLUE");
    cp.show();
}

[결과값]
BLUE색으로 (10,20)에 위치한 점입니다.

#include<iostream>

using namespace std;

class Point
{
	int x, y;
public:
	int getX() { return x; }
	int getY() { return  y; }

protected:
	void move(int x, int y) {
		this->x = x;
		this->y = y;
	}
};

class ColorPoint : public Point
{
	string color;
public:
	ColorPoint(int x, int y, string color)
	{
		x = getX();
		y = getY();
		this->color = color;
	}
	void show()
	{
		cout << color << "색으로 (" << getX() << "," << getY() << ")에 위치한 점입니다";
	}
	void setPoint(int x, int y)
	{
		move(x, y);
	}
	void setColor(string name)
	{
		this->color = name;
	}
};


int main()
{
	ColorPoint cp(5, 5, "RED");
	cp.setPoint(10, 20);
	cp.setColor("BLUE");
	cp.show();
}

8-4

다음 main() 함수가 실행되도록 Point 클래스를 상속받는 ColorPoint 클래스를 작성하고, 전체 프로그램을 완성하라.

int main() {
    ColorPoint zeroPoint; // BLACK 색에 (0, 0) 위치의 점
    zeroPoint.show(); // zeroPoint를 출력한다.
    
    ColorPoint cp(5, 5);
    cp.setPoint(10, 20);
    cp.setColor("BLUE");
    cp.show(); // cp를 출력한다.
}

[결과값]
BLACK색으로 (0,0)에 위치한 점입니다.
BLUE색으로 (10,20)에 위치한 점입니다.

#include<iostream>

using namespace std;

class Point
{
	int x, y;
public:
	int getX() { return x; }
	int getY() { return  y; }

protected:
	void move(int x, int y) {
		this->x = x;
		this->y = y;
	}
};

class ColorPoint : public Point
{
	string color;
public:
	ColorPoint(int x = 0, int y = 0, string color = "BLACK")
	{
		move(x, y);
		this->color = color;
	}
	void show()
	{
		cout << color << "색으로 (" << getX() << "," << getY() << ")에 위치한 점입니다" << endl;
	}
	void setPoint(int x, int y)
	{
		move(x, y);
	}
	void setColor(string name)
	{
		this->color = name;
	}
};


int main()
{
	ColorPoint zeroPoint; //BLACK 색에 (0, 0) 위치의 점
	zeroPoint.show();

	ColorPoint cp(5, 5);
	cp.setPoint(10, 20);
	cp.setColor("BLUE");
	cp.show();
}

문제 5~6에 적용되는 BaseArray 클래스는 다음과 같다.

class BaseArray {
    int capacity; // 배열의 크기
    int *mem; // 정수 배열을 만들기 위한 메모리의 포인터
protected: // 생성자가 protected 
    BaseArray(int capacity=100){
        this->capacity = capacity; mem = new int [capacity];
    }
    ~BaseArray() { delete [] mem; }
    void put(int index, int val) { mem[index] = val; }
    int get(int index) { return mem[index]; }
    int getCapacity() { return capacity; }
};

8-5, 상속을 이용한 Queue 문제

BaseArray를 상속받아 큐처럼 작동하는 MyQueue 클래스를 작성하라.

MyQueue를 활용하는 사례는 다음과 같다.

MyQueue mQ(100);
 int n;
 cout << "큐에 삽입할 5개의 정수를 입력하라>> ";
 for(int i=0; i<5; i++){
     cin >> n;
     mQ.enqueue(n); // 큐에 삽입 
 }
 cout << "큐의 용량:" << mQ.capacity() << ", 큐의 크기:" << mQ.length() << endl;
 cout << "큐의 원소를 순서대로 제거하여 출력한다>> ";
 while(mQ.length() != 0){
     cout << mQ.dequeue() << ' '; // 큐에서 제거하여 출력 
 }
 cout << endl << "큐의 현재 크기 : " << mQ.length() << endl;    
[틀린 답]
#include<iostream>

using namespace std;

class BaseArray
{
	int capacity;
	int* mem;
public:
	BaseArray(int capacity = 100) {
		//cout << "BaseArray() 생성자 실행 현재" << endl;
		this->capacity = capacity;
		mem = new int[capacity];
	};
	~BaseArray() { delete[] mem; }
	void put(int index, int val) {
		mem[index] = val;
	}
	int get(int index) { return mem[index]; }
	int getCapacity() { return capacity; }
};

class MyQueue : public BaseArray
{
	int capacity;
	int top;
public:
	MyQueue(int capacity){
		top = 0;
		this->capacity = capacity;
		//cout << "MyQueue() 생성자 실행 현재 size : "  << capacity << endl;
	};
	void enqueue(int n) {
		put(capacity, n);
		capacity++;
		//cout << "top :" << top << endl;
		top++;

		//cout << "enqueue() 실행 size : " << capacity << endl ;
	}
	int cpapcity() {
		return getCapacity();
	}
	int length() {
		return top;
	}
	int dequeue() {
		if (top == -1)
			return 0;

		return get(capacity - top--);
	}
};


int main()
{
	MyQueue mQ(100);
	int n;
	cout << "큐에 삽입할 5개의 정수를 입력하라>>";

	for (int i = 0; i < 5; i++)
	{
		cin >> n;
		mQ.enqueue(n); 
	}

	cout << "큐의 용량:" << mQ.cpapcity() << ", 큐의 크기:" << mQ.length() << endl;
	cout << "큐의 원소를 순서대로 제거하여 출력한다>>";

	while (mQ.length() != 0) {
		cout << mQ.dequeue() << ' ';
	}

	cout << endl << "큐의 현재 크기 : " << mQ.length() << endl;
}
[정답]
#include <iostream>
#include <string>
using namespace std;

class BaseArray {
	int capacity;
	int* mem;
protected:
	BaseArray(int capacity = 100) {
		this->capacity = capacity; mem = new int[capacity];
	}
	~BaseArray() { delete[] mem; }
	void put(int index, int val) { mem[index] = val; }
	int get(int index) { return mem[index]; }
	int getCapacity() { return capacity; }
};

class MyQueue : public BaseArray {
	int enindex;
	int deindex;
public:
	MyQueue(int size) : BaseArray(size) { enindex = 0; deindex = -1; }
	void enqueue(int n) {
		put(enindex, n);
		enindex++;
	}
	int capacity() { return getCapacity(); }
	int length() { return enindex; }
	int dequeue() {
		enindex--;
		deindex++; return get(deindex);
	}
};

int main() {
	MyQueue mQ(100);
	int n;
	cout << "큐에 삽입할 5개의 정수를 입력하라>> ";
	for (int i = 0; i < 5; i++) {
		cin >> n;
		mQ.enqueue(n);
	}
	cout << "큐의 용량:" << mQ.capacity() << ", 큐의 크기:" << mQ.length() << endl;
	cout << "큐의 원소를 순서대로 제거하여 출력한다>> ";
	while (mQ.length() != 0) {
		cout << mQ.dequeue() << ' ';
	}
	cout << endl << "큐의 현재 크기 : " << mQ.length() << endl;
}

풀지 못했던 이유

결과값 자체는 맞게 구현하였으니 디버깅 오류를 결국 해결하지 못해 솔루션을 보았다.

8-6, 상속을 이용한 Stack 문제

BaseArray 클래스를 상속받아 스택으로 작동하는 MyStack 클래스를 작성하라.

MyStack mStack(100);
    int n;
    cout << "스택에 삽입할 5개의 정수를 입력하라>> ";
    for(int i=0; i<5; i++){
        cin >> n;
        mStack.push(n); // 스택에 푸시 
    }
    cout << "스택 용량:" << mStack.capacity() << ", 스택 크기:" << mStack.length() << endl;
    cout << "스택의 모든 원소를 팝하여 출력한다>> ";
    while(mStack.length() != 0){
        cout << mStack.pop() << ' '; // 스택에서 팝 
    }
    cout << endl << "스택의 현재 크기 : " << mStack.length() << endl;
#include <iostream>
#include <string>
using namespace std;

class BaseArray {
	int capacity;
	int* mem;
protected:
	BaseArray(int capacity = 100) {
		this->capacity = capacity;
		mem = new int[capacity];
	}
	~BaseArray() { delete[] mem; }
	void put(int index, int val) { mem[index] = val; }
	int get(int index) { return mem[index]; }
	int getCapacity() { return capacity; }
};

class MyStack : public BaseArray {
	int pushindex;
	int popindex;
public:
	MyStack(int size) : BaseArray(size) { pushindex = 0; popindex = -1; }
	void push(int n) {
		put(pushindex, n);
		pushindex++;
		cout << "pushindex : " << pushindex << endl;
	}
	int capacity() { return getCapacity(); }
	int length() { return pushindex; }
	int pop() {
		pushindex--;
		return get(pushindex);
	}
};

int main() {
	MyStack mStack(100);
	int n;

	cout << "스택에 삽입할 5개의 정수를 입력하라>> ";

	for (int i = 0; i < 5; i++) {
		cin >> n;
		mStack.push(n);
	}

	cout << "스택의 용량:" << mStack.capacity() << ", 스택의 크기:" << mStack.length() << endl;
	cout << "스택의 원소를 순서대로 제거하여 출력한다>> ";

	while (mStack.length() != 0) {
		cout << mStack.pop() << ' ';
	}

	cout << endl << "스택의 현재 크기 : " << mStack.length() << endl;
}

8-7, 상속을 이용한 ROM&RAM 읽기/쓰기

아래와 같은 BaseMemory 클래스를 상속받는 ROM( Read Only Memory ), RAM 클래스를 작성하라. BaseMemory 에 필요한 코드를 수정 추가하여 적절히 완성하라.

  char x[5] = {'h', 'e', 'l', 'l', 'o'};
    ROM biosROM(1024*10, x, 5); // 10KB의 ROM 메모리. 배열 x로 초기화됨 
    RAM mainMemory(1024*1024); // 1MB의 ROM 메모리 
    
    // 0 번지에서 4번지까지 biosRom에서 읽어 mainMemory에 복사 
    for(int i=0; i<5; i++) mainMemory.write(i, biosROM.read(i));
    for(int i=0; i<5; i++) cout << mainMemory.read(i);

ROM은 읽기 전용 메모리이므로 작동 중에 값을 쓸 수가 없기 때문에, 공장에서 생산할 때 생산자가 요청한 데이터로 초기화하는데 이 작업을 굽는다( burn )라고 한다. 그러므로 ROM은 반드시 생성자에서 burn 작업이 일어나야 한다.

다음은 ROM과 RAM 메모리를 생성하고 사용하는 사례이다. ROM의 0번지에서 4번지까지 읽어 RAM 메모리의 0~4번지에 쓰고, 다시 RAM 메모리의 값을 화면에 출력한다. 전체 프로그램을 완성하라.

#include <iostream>
using namespace std;

class BaseMemory {
	char* mem;
protected:
	BaseMemory(int size) { mem = new char[size]; }
	~BaseMemory() { delete[] mem; }
	void setData(int index, char data) { mem[index] = data; }
	char getData(int index) { return mem[index]; }
};

class ROM : private BaseMemory {
	int length;
public:
	ROM(int size, char memory[], int len) : BaseMemory(size) {
		length = len;
		for (int i = 0; i < len; i++)
			setData(i, memory[i]);
	}
	char read(int index) { return getData(index); }
};

class RAM : private BaseMemory {
public:
	RAM(int size) : BaseMemory(size) { ; }
	void write(int index, int data) { setData(index, data); }
	char read(int index) { return getData(index); }
};

int main() {
	char x[5] = { 'h', 'e', 'l', 'l', 'o' };
	ROM biosROM(1024 * 10, x, 5);
	RAM mainMemory(1024 * 1024);

	for (int i = 0; i < 5; i++) mainMemory.write(i, biosROM.read(i));
	for (int i = 0; i < 5; i++) cout << mainMemory.read(i);
}

풀지 못한 이유

BaseMemory의 get/set을 이용한 생각을 하지 못하였다. 그리고 틈틈히 포인터(*)을 사용할 경우 소멸자에 delete까지 의식할 수 있도록 재풀이할 예정이다.

profile
CK23 Game programmer

0개의 댓글