C-C++/명품 C++ Programming

[(개정판) 명품 C++ programming] 8장 실습 문제

최옥구 2023. 1. 7. 07:00
반응형

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

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

[결과]

[소스 코드]

#include <iostream>
using namespace std;

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; }
};

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

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

 


 

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

[결과]

[소스 코드]

#include <iostream>
using namespace std;

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; }
};

class NamedCircle : public Circle
{
	int radius;
	string name;
public:
	NamedCircle() {}
	void setName(string name) { this->name = name; }
	string getName() { return name; }
	void show()
	{
		cout << " 반지름이 " << radius << "인 " << name;
	}
};

int main()
{
	NamedCircle pizza[5];
	int radius, max;
	string name;

	cout << " 5개의 정수 반지름과 원의 이름을 입력하세요" << endl;
	for (int i = 0; i < 5; i++)
	{
		cout << i + 1 << " >> ";
		cin >> radius >> name;
		pizza[i].setRadius(radius);
		pizza[i].setName(name);
	}

	max = pizza[0].getRadius();
	int count;
	for (int i = 0; i < 5; i++)
	{
		if (max < pizza[i].getRadius())
		{
			max = pizza[i].getRadius();
			count = i;
		}
	}

	cout << "가장 면적이 큰 피자는 " << pizza[count].getName();

}

 


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

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

[결과]

[소스 코드]

#include <iostream>
using namespace std;

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; }
};

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

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

 


 

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

[결과]

[소스 코드]

#include <iostream>
using namespace std;

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; }
};

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

int main()
{	
	ColorPoint zeroPoint;
	zeroPoint.show();

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

 


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

5. BaseArray를 상속받아 큐처럼 작동하는 MyQueue 클래스를 작성하라. MyQueue를 활용하는 사례는 다음과 같다.

[결과]

[소스 코드]

#include <iostream>
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 : protected BaseArray
{
	int size, index = 0, pos = 0;
public:
	MyQueue(int size) : BaseArray(size)
	{
		this->size = size;
		for (int i = 0; i < size; i++)
			put(i, 0);
	}
	void enqueue(int n)
	{
		put(index, n);
		index++;
	}
	int capacity()
	{
		return getCapacity();
	}
	int length()
	{
		return index;
	}
	int dequeue()
	{
		int I = get(pos);
		put(pos, 0);
		pos++;
		index--;
		return I;
	}
};

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;
}

 


 

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

[결과]

[소스 코드]

#include <iostream>
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 : protected BaseArray
{
	int size, index = 0;
public:
	MyStack(int size) : BaseArray(size)
	{
		this->size = size;

	}
	void push(int n)
	{
		put(index, n);
		index++;
	}
	int capacity()
	{
		return getCapacity();
	}
	int length()
	{
		return index;
	}
	int pop()
	{
		int i = get(index-1);
		put(index-1, 0);
		index--;
		return i;
	}

};

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;
}

 


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

[결과]

[소스 코드]

#include <iostream>
using namespace std;

class BaseMemory
{
	char* mem; 
protected:
	BaseMemory(int size)
	{
		mem = new char[size];
	}
	void burnMemory(char x[], int burn)
	{
		for (int i = 0; i < burn; i++)
			mem[i] = x[i];
	}
	char getMemory(int i)
	{
		return mem[i];
	}
	void setMemory(int i, char x) 
	{
		mem[i] = x;
	}
};

class ROM : protected BaseMemory
{
	int RomSize, burn;
	char x[];
public:
	ROM(int size, char x[], int burn) : BaseMemory(size)
	{
		this->RomSize = size;
		this->burn = burn;
		burnMemory(x, burn);
	}
	char read(int i)
	{
		return getMemory(i);
	}
};

class RAM : protected BaseMemory
{
	int RamSize;
public:
	RAM(int size) : BaseMemory(size)
	{
		RamSize = size;
	}
	void write(int i, char x)
	{
		setMemory(i, x);
	}
	char read(int i)
	{
		return getMemory(i);
	}
};

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);
}

 


8. 다음 그림과 같은 상속 구조를 갖는 클래스를 설계한다.

모든 프린터는 모델명(model), 제조사(manufacturer), 인쇄 매수(printedCount), 인쇄 종이 잔량 (avaliableCount)을 나타내는 정보와 print( int pages) 멤버 함수를 가지며, print()가 호출할 때마다 pages 매의 용지를 사용한다. 잉크젯 프린터는 잉크 잔량(avaliableInk) 정보와 printInkJet(int pages) 멤버 함수를 추가적으로 가지며, 레이저 프린트는 토너 잔량 (avaliableToner) 정보와 역시 printLaser(int pages) 멤버 함수를 추가적으로 가진다. 각 클래스에 적절한 접근 지정으로 멤버 변수와 함수, 생성자, 소멸자를 작성하고, 다음과 같이 실행되도록 전체 프로그램을 완성하라. 잉크젯 프린터 객체와 레이저 프린터 객체를 각각 하나만 동적 생성하여 시작한다.

[결과]

[소스 코드]

#include<iostream>
using namespace std;

class PrintMachine
{
    string model, manufacturer;
    int pcount, avaliablecount;
protected:
    PrintMachine(string model, string manufacturer, int avaliablecount) {
        this->model = model;
        this->manufacturer = manufacturer;
        this->avaliablecount = avaliablecount;
    }
    bool print(int pages) {
        if (avaliablecount < pages) {
            cout << "용지가 부족하여 프린트 할 수 없습니다.\n";
            return false;
        }
        for (int i = 0; i < pages; i++) {
            avaliablecount--;
        }
        return true;
    }
    string getModel() { return model; }
    string getmManufacturer() { return manufacturer; }
    int getAvaliablecount() { return avaliablecount; }
};

class PrintInkJet : public PrintMachine {
    int avlink;
public:
    PrintInkJet(string model, string manufacturer, int avaliablecount, int avlink) : PrintMachine(model, manufacturer, avaliablecount) {
        this->avlink = avlink;
    }
    bool printInkJet(int pages) {
        if (print(pages));
        else return false;
        if (avlink < pages) {
            cout << "잉크가 부족하여 프린트 할 수 없습니다.\n";
            return false;
        }
        for (int i = 0; i < pages; i++) {
            avlink--;
        }
        return true;
    }
    void show() {
        cout << getModel() << "\t," << getmManufacturer() << "\t,남은 종이 " << getAvaliablecount() << "장\t,남은 잉크 " << avlink << endl;
    }
};

class PrintLaser : public PrintMachine {
    int avltoner;
public:
    PrintLaser(string model, string manufacturer, int avaliablecount, int avltoner) : PrintMachine(model, manufacturer, avaliablecount) {
        this->avltoner = avltoner;
    }
    bool printLaser(int pages) {
        if (print(pages));
        else return false;
        if (avltoner < pages) {
            cout << "토너가 부족하여 프린트 할 수 없습니다.\n";
            return false;
        }
        for (int i = 0; i < pages; i++)
            avltoner--;
        return true;
    }
    void show() {
        cout << getModel() << " ," << getmManufacturer() << "\t,남은 종이 " << getAvaliablecount() << "장\t,남은토너 " << avltoner << endl;
    }
};

int main() {
    int pnum, pages;
    char yon;
    PrintInkJet* inkjet = new PrintInkJet("Officejet V40", "Hp", 5, 10);
    PrintLaser* laser = new PrintLaser("SCX-6x45", "삼성전자", 3, 20);
    cout << "현재 작동중인 2 대의 프린터는 아래와 같다\n";
    cout << "잉크젯 : ";
    inkjet->show();
    cout << "레이저 : ";
    laser->show();
    cout << endl;

    while (true) {
        cout << "프린터(1:잉크젯, 2:레이저)와 매수 입력>>";
        cin >> pnum >> pages;
        if (pnum == 1)
            if (inkjet->printInkJet(pages))
                cout << "프린트 하였습니다.\n";
        if (pnum == 2)
            if (laser->printLaser(pages))
                cout << "프린트 하였습니다.\n";
        if (pnum != 1 && pnum != 2) cout << "프린터를 잘못 선택하셨습니다.\n";
        inkjet->show();
        laser->show();
        while (true) {
            cout << "계속 프린트 하시겠습니까(y/n)>>";
            cin >> yon;
            cout << endl;
            if (yon == 'n')
                return 0;
            else if (yon == 'y')
                break;
            else
                cout << "잘못 입력하셨습니다.\n";
        }
    }
    delete inkjet;
    delete laser;

 


9. 비행기 예약 프로그램을 작성하라. 이 문제는 여러개의 클래스와 객체들을 다루는 연습을 위한 것이다. 클래스 사이의 상속 관계는 없다. 항공사 이름은 '한성항공'이고, 8개의 좌석을 가진 3대의 비행기로 서울 부산 간 운항 사업을 한다, 각 비행기는 하루에 한번만 운항하며, 비행 시간은 07시, 12시, 17시이다. 비행기 예약 프로그램은 다음 기능을 가진다.

- 비행 : 비행 시간, 사용자의 이름, 좌석 번호를 입력받아 예약한다.

- 취소 : 비행 시간, 사용자의 이름, 좌석 번호를 입력받고 예약을 취소한다.

- 예약 보기 : 예약된 좌석 상황을 보여준다.

[결과]

9번 문제는 참고를 많이 했습니다.

[선언부 AirLine.h]

#pragma once
#include <iostream>
using namespace std;

class Console {
public:
    static int select_menu();
    static int select_time();
    static int input_seat_num();
    static string input_name();
};

class Seat {
    string name;
public:
    Seat() { name = { "---" }; }
    void set_name(string name) { this->name = name; }
    void reset_name() { name = { "---" }; }
    string show_name() { return name; }

};

class Schedule {
    Seat* seat;
    string scname;
    int seat_num;
    string person_name;
public:
    Schedule() { seat = new Seat[8]; }
    ~Schedule() { delete[] seat; }
    void set_scname(string scname) { this->scname = scname; }
    void show_schedule();
    void set_resv(int seat_num, string person_name);
    void cancel_resv(int seat_num, string person_name);
};


class AirlineBook {
    Schedule* schedule;
    int menu;
    int time;
public:
    AirlineBook() {
        schedule = new Schedule[3];
        schedule[0].set_scname("07");
        schedule[1].set_scname("12");
        schedule[2].set_scname("17");
    }
    ~AirlineBook() { delete[] schedule; }
    void start();
};

[구현부 AirLine.cpp]

#include<iostream>
#include "AirLine.h"
using namespace std;

int Console::select_menu() {
    cout << "예약:1, 취소:2, 보기:3, 끝내기:4>> ";
    int menu;
    cin >> menu;
    return menu;
}

int Console::select_time() {
    cout << "07시:1, 12시:2, 17시:3>> ";
    int time;
    cin >> time;
    return time;
}

int Console::input_seat_num() {
    cout << "좌석 번호>> ";
    int seat_num;
    cin >> seat_num;
    if (seat_num < 1 || 8 < seat_num) {
        cout << "없는 좌석 번호 입니다. 처음 메뉴로 돌아갑니다.\n";
        return 0;
    }
    return seat_num;
}

string Console::input_name() {
    cout << "이름 입력>> ";
    string name;
    cin >> name;
    return name;
}

void AirlineBook::start() {
    while (true) {
        menu = Console::select_menu();
        if (menu == 1 || menu == 2) {
            time = Console::select_time();
            if (menu == 1) {
                switch (time) {
                case 1: {
                    schedule[0].show_schedule();
                    int seat_num = Console::input_seat_num();
                    if (seat_num == 0)
                        break;
                    string person_name = Console::input_name();
                    schedule[0].set_resv(seat_num, person_name);
                    break;
                }
                case 2: {
                    schedule[1].show_schedule();
                    int seat_num = Console::input_seat_num();
                    if (seat_num == 0)
                        break;
                    string person_name = Console::input_name();
                    schedule[1].set_resv(seat_num, person_name);
                    break;
                }
                case 3: {
                    schedule[2].show_schedule();
                    int seat_num = Console::input_seat_num();
                    if (seat_num == 0)
                        break;
                    string person_name = Console::input_name();
                    schedule[2].set_resv(seat_num, person_name);
                    break;
                }
                case 4:
                    cout << "잘못 선택하셨습니다. 처음 메뉴로 돌아갑니다.\n";
                }
            }
            else {
                switch (time) {
                case 1: {
                    schedule[0].show_schedule();
                    int seat_num = Console::input_seat_num();
                    if (seat_num == 0)
                        break;
                    string person_name = Console::input_name();
                    schedule[0].cancel_resv(seat_num, person_name);
                    break;
                }
                case 2: {
                    schedule[1].show_schedule();
                    int seat_num = Console::input_seat_num();
                    if (seat_num == 0)
                        break;
                    string person_name = Console::input_name();
                    schedule[1].cancel_resv(seat_num, person_name);
                    break;
                }
                case 3: {
                    schedule[2].show_schedule();
                    int seat_num = Console::input_seat_num();
                    if (seat_num == 0)
                        break;
                    string person_name = Console::input_name();
                    schedule[2].cancel_resv(seat_num, person_name);
                    break;
                }
                case 4:
                    cout << "잘못 선택하셨습니다. 처음 메뉴로 돌아갑니다.\n";
                }
            }
        }
        else if (menu == 3) {
            for (int i = 0; i < 3; i++) {
                schedule[i].show_schedule();
            }
        }
        else if (menu == 4) {
            cout << "예약 시스템을 종료합니다.";
            exit(0);
        }
        else {
            cout << "잘못 입력하셨습니다. 메뉴를 다시 선택해 주세요.\n";
        }
        cout << endl;
    }
}

void Schedule::show_schedule() {
    cout << this->scname << "시:";
    for (int i = 0; i < 8; i++)
        cout << "\t" << seat[i].show_name();
    cout << endl;
}

void Schedule::set_resv(int seat_num, string person_name) {
    if (seat[seat_num - 1].show_name() != "---")
        cout << "이미 예약된 자리입니다. 처음 메뉴로 돌아갑니다.\n";
    else seat[seat_num - 1].set_name(person_name);
}

void Schedule::cancel_resv(int seat_num, string person_name) {
    if (seat[seat_num - 1].show_name() == "---") {
        cout << "이미 비어있는 자리입니다. 처음 메뉴로 돌아갑니다.\n";
        return;
    }
    if (seat[seat_num - 1].show_name() != person_name) {
        cout << "예약된 이름과 일치하지 않습니다. 처음 메뉴로 돌아갑니다.\n";
        return;
    }
    seat[seat_num - 1].reset_name();
}

[소스 코드]

#include<iostream>
#include "AirLine.h"
using namespace std;

int main() {
    AirlineBook* air = new AirlineBook();
    cout << "***** 한성항공에 오신것을 환영합니다 *****\n\n";
    air->start();
    delete air;
}

 


 

책에서 나오는 힌트나 조건들의 일부는 저작자 존중을 위해 일부러 작성하지 않았습니다. 

개인 공부용으로 올리는 만큼 풀이에 대한 지적 감사하겠습니다.

반응형