상세 컨텐츠

본문 제목

[객체지향언어1] 명품 C++ Programming 3장 실습 문제

C++/문제 풀이

by uzichoi 2025. 4. 8. 18:02

본문

[C++] 명품 C++ Programming 3장 연습, 실습 문제 풀이

 

1. main()의 실행 결과가 다음과 같도록 Tower 클래스를 작성하라.

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Tower {
	int meter;
public:
	Tower();
	Tower(int n);
	int getHeight();
};

Tower::Tower() {
	meter = 1;
}

Tower::Tower(int n) {
	meter = n;
}

int Tower::getHeight() {
	return meter;
}

int main() {
	Tower myTower;	//1미터
	Tower seoulTower(100);	//100미터
	cout << "높이는 " << myTower.getHeight() << "미터" << endl;
	cout << "높이는 " << seoulTower.getHeight() << "미터" << endl;

	return 0;
}

 

 

2. 날짜를 다루는 Date 클래스를 작성하고자 한다. Date를 이용하는 main()과 실행 결과는 다음과 같다. 클래스 Date를 작성하여 아래 프로그램에 추가하라.

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <string>
using namespace std;

class Date {
	int year, month, day;
public:
	Date(int y, int m, int d);
	Date(const char* str);
	void show();
	int getYear();
	int getMonth();
	int getDay();
};

Date::Date(int y, int m, int d) {
	year = y;
	month = m;
	day = d;
}
Date::Date(const char* str) {
	char buffer[100];
	strcpy(buffer, str);
	year = stoi(strtok(buffer, "/"));
	month = stoi(strtok(NULL, "/"));
	day = stoi(strtok(NULL, "/"));
}
void Date::show() {
	cout << year << "년" << month << "월" << day << "일" << endl;
}
int Date::getYear() {
	return year;
}
int Date::getMonth() {
	return month;
}
int Date::getDay() {
	return day;
}
int main() {
	Date birth(2014, 3, 20);	//2014년 3월 20일
	Date independenceDay("1945/8/15");	//1945년 8월 15일
	independenceDay.show();
	cout << birth.getYear() << ',' << birth.getMonth() << ',' << birth.getDay() << endl;

	return 0;
}
  1.  E0280: 인수 목록이 일치하는 생성자의 인스턴스가 없습니다.
    • 오류 원인: 생성자에서 인수의 const 선언이 누락되었기 때문
    • 전달된 인자가 const 문자열이므로, 생성자에서도 해당 인수를 const로 선언해야 한다.
    • 또한, 생성자 매개변수를 받을 때, char* 대신 const char*로 선언하면 오류를 해결할 수 있다.   
  2. C2664:  'function' : 인수 n을(를) 'type1'에서 'type2'(으)로 변환할 수 없습니다.
    • Date::Date(const char* str)로 작성한다. 이때 str은 읽기 전용 문자열이므로 문자열을 직접 수정하는 strtok()을 사용할 수 없다. strtok() 함수는 문자열의 끝에 '\0'을 삽입하기 때문이다.
    • 임시 문자 배열 char buffer[100]에 str의 내용을 복사하면 원본을 보존하며 안전하게 buffer를 자를 수 있다.   

 

 

3. 은행에서 사용하는 프로그램을 작성하기 위해 은행 계좌 하나를 표현하는 클래스 Account가 필요하다. 계좌 정보는 계좌의 주인, 계좌 번호, 잔액을 나타내는 3 멤버 변수로 이루어진다. main() 함수의 실행 결과가 다음과 같도록 Account 클래스를 작성하라. 

<실행화면>

<소스코드>

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

class Account {
	string name;
	int id;
	int balance;
public:
	Account(string str, int ID, int bal);
	void deposit(int n) { balance += n; }
	int inquiry() {	return balance;	}	
	int withdraw(int n) { 
		balance -= n;
		return balance;
	};	
	string getOwner() { return name; }
};

Account::Account(string str, int ID, int bal) {
	name = str;
	id = ID;
	balance = bal;
}

int main() {
	Account a("kitae", 1, 5000);	//id 1번, 잔액 5000원, 이름이 kitae인 계좌 생성
	a.deposit(50000);
	cout << a.getOwner() << "의 잔액은 " << a.inquiry() << endl;
	int money = a.withdraw(20000);	//20000원 출금.  withdraw()는 출금한 실제 금액 리턴
	cout << a.getOwner() << "의 잔액은 " << a.inquiry() << endl;

	return 0;
}

 

 

4. CoffeeMachine 클래스를 만들어 보자. main() 함수와 실행 결과가 다음과 같도록 CoffeeMachine 클래스를 작성하라. 에스프레소 한 잔에는 커피와 물이 각각 1씩 소비되고, 아메리카노의 경우 커피는 1, 물은 2가 소비되고, 설탕 커피는 커피 1, 물 2, 설탕 1이 소비된다. CoffeeMachine 클래스에는 어떤 멤버 변수와 어떤 멤버 함수가 필요한지잘 판단하여 작성하라. 

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

class CoffeeMachine {
	int coffee, water, sugar;
public:
	CoffeeMachine(int a, int b, int c);
	void drinkEspresso();
	void drinkAmericano();
	void drinkSugarCoffee();
	void show();
	void fill();
};

CoffeeMachine::CoffeeMachine(int a, int b, int c) {
	coffee = a;
	water = b;
	sugar = c;
}

void CoffeeMachine::drinkEspresso() {
	coffee--;
	water--;
}

void CoffeeMachine::drinkAmericano() {
	coffee--;
	water-=2;
}

void CoffeeMachine::drinkSugarCoffee() {
	coffee--;
	water-=2;
	sugar--;
}

void CoffeeMachine::show() {
	cout << "커피 마신 상태,\t" << "커피:" << coffee << "\t물:" << water << "\t설탕:" << sugar << endl;
}

void CoffeeMachine::fill() {
	coffee = 10;
	water = 10;
	sugar = 10;
}

int main() {
	CoffeeMachine java(5, 10, 3);
	java.drinkEspresso();
	java.show();
	java.drinkAmericano();
	java.show();
	java.drinkSugarCoffee();
	java.show();
	java.fill();
	java.show();

	return 0;
}

 

 

5. 랜덤 수를 발생시키는 Random 클래스를 만들자. Random 클래스를 이용하여 랜덤한 정수를10개 출력하는 사례는 다음과 같다. Random 클래스가 생성자, next(), nextInRange() 3개의 멤버 함수를 가지도록 작성하고 main() 함수와 합쳐 하나의 cpp 파일에 구현하라.

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

class Random {
public:
	Random();
	int next();
	int nextInRange(int start, int end);
};

Random::Random() {
	srand(time(NULL));
}

int Random::next() {
	return rand() % RAND_MAX;
}

int Random::nextInRange(int start, int end) {
	int range = end - start + 1;
	return start + rand() % range;
}

int main() {
	Random r;
	
	cout << "-- 0에서 " << RAND_MAX << "까지의 랜덤 정수 10 개--" << endl;
	for (int i = 0; i < 10; i++) {
		int n = r.next();	//0에서 RAND_MAX(32767) 사이의 랜덤한 정수
		cout << n << ' ';
	}

	cout << endl << endl << "-- 2에서 " << "4까지의 랜덤 정수 10 개--" << endl;
	for (int i = 0; i < 10; i++) {
		int n = r.nextInRange(2,4);	//2에서 4 사이의 랜덤한 정수
		cout << n << ' ';
	}
	cout << endl;

	return 0;
}
  1. seed값 설정
    • srand((unsigned)time(NULL)); 최초 1회만 초기화해야 하므로 생성자 함수에 위치해야 한다.
    • srand((unsigned)time(0)): time(0)이 기준으로 삼는 시간은 1970년 1월 1일 00:00:00 UTC(협정 세계시)로, 흔히 말하는 'Epoch Time' 또는 'UNIX 시간의 시작점'이다. 즉, 해당 시점부터 지금까지 지난 초(second)가 저장된다. 덧붙여 time(0)은 1초 단위로만 변화며, 더욱 정밀한 시간 측정이 필요하다면 clock()함수를사용해야 한다. 
    • <cstdlib>, <ctime> 헤더파일을 모두 포함해야 사용할 수 있다.
  2. 난수 범위 설정
    • range = end - start + 1;
    • n = start + rand()%range;

 

 

6. 문제 5번을참고하여 짝수 정수만 랜덤하게 발생시키는 EvenRandom 클래스를 작성하고 EvenRandom 클래스를 이용하여 10개의 짝수를 랜덤하게 출력하는 프로그램을완성하라. 0도 짝수로 처리한다. 

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

class EvenRandom {
public:
	EvenRandom();
	int next();
	int nextInRange(int start, int end);
};

EvenRandom::EvenRandom() {
	srand((unsigned)time(0));
}

int EvenRandom::next() {
	int n = rand() % RAND_MAX;
	if (n % 2 == 1)		//n이 홀수이면 -- -> 짝수로 변환
		n--;
	return n;
}

int EvenRandom::nextInRange(int start, int end) {
	int range = end - start + 1;
	int n =  start + rand() % range;
	if (n % 2 == 1)
		n--;
	return n;
}

int main() {
	EvenRandom r;

	cout << "-- 0에서 " << RAND_MAX << "까지의 랜덤 정수 10 개--" << endl;
	for (int i = 0; i < 10; i++) {
		int n = r.next();	//0에서 RAND_MAX(32767) 사이의 랜덤한 정수
		cout << n << ' ';
	}

	cout << endl << endl << "-- 2에서 " << "10까지의 랜덤 정수 10 개--" << endl;
	for (int i = 0; i < 10; i++) {
		int n = r.nextInRange(2, 10);	//2에서 10 사이의 랜덤한 정수
		cout << n << ' ';
	}
	cout << endl;

	return 0;
}

 

 

7. 문제 5번을 참고하여 생성자를 이용해 짝수 홀수를 선택할 수 있도록 SelectableRandom 클래스를 작성하고 짝수 10개, 홀수 10개를 랜덤하게 발생시키는 프로그램을 작성하라.   

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

class SelectableRandom {
public:
	SelectableRandom();
	int evenNext();
	int oddNextInRange(int start, int end);
};

SelectableRandom::SelectableRandom() {
	srand((unsigned)time(0));
}

int SelectableRandom::evenNext() {
	int n = rand() % RAND_MAX;
	if (n % 2 == 1)		//n이 홀수이면 -- -> 짝수로 변환
		n--;
	return n;
}

int SelectableRandom::oddNextInRange(int start, int end) {
	int range = end - start + 1;
	int n = start + rand() % range;
	if (n % 2 == 0)
		n--;
	return n;
}

int main() {
	SelectableRandom r;

	cout << "-- 0에서 " << RAND_MAX << "까지의 짝수 랜덤 정수 10 개--" << endl;
	for (int i = 0; i < 10; i++) {
		int n = r.evenNext();	//0에서 RAND_MAX(32767) 사이의 랜덤한 정수
		cout << n << ' ';
	}

	cout << endl << endl << "-- 2에서 " << "9까지의 홀수 랜덤 정수 10 개--" << endl;
	for (int i = 0; i < 10; i++) {
		int n = r.oddNextInRange(2, 9);	//2에서 9사이의 랜덤한 정수
		cout << n << ' ';
	}
	cout << endl;

	return 0;
}

 

 

8. int 타입의 정수를 객체화한 Integer 클래스를 작성하라. Integer의 모든 멤버 함수를 자동 인라인으로 작성하라. Integer 클래스를 활용하는 코드는 다음과 같다.  

<실행화면>

<소스코드>

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

class Integer {
	int number;
public:
	Integer(int num1) { number = num1; };
	Integer(string str) { number = stoi(str); };	//stoi: string to int. 문자열을 정수로 변환
	int get() { return number; };
	void set(int num2) { number = num2; };
	int isEven() {
		if (number % 2 == 0)
			return 1;
		else 0;	//홀수이면 0 반환, 쓰레기값 반환 방지
	}
};

int main() {
	Integer n(30);
	cout << n.get() << ' ';		//30 출력
	n.set(50);
	cout << n.get() << ' ';

	Integer m("300");
	cout << m.get() << ' ';
	cout << m.isEven();

	return 0;
}

 

 

9. Oval 클래스는 주어진 사각형에 내접하는 타원을 추상화한 클래스이다. Oval 클래스의 멤버는 모두 다음과 같다. Oval 클래스를 선언부와 구현부로 나누어 작성하라.

  • 정수값의 사각형 너비와 높이를 가지는 width, height 변수 멤버
  • 너비와 높이 값을 매개 변수로 받는 생성자
  • 너비와 높이를 1로 초기화하는 매개 변수 없는 생성자
  • weight와 height를 출력하는 소멸자
  • 타원의 너비를 리턴하는 getWidth() 함수 멤버
  • 타원의 높이를 리턴하는 getHeight() 함수 멤버
  • 타원의 너비와 높이를 변경하는 set(int w, int h) 함수 멤버
  • 타원의 높이와 높이를 화면에 출력하는 show() 함수 멤버

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Oval {	//선언부
	int width, height;
public:
	Oval();
	Oval(int w, int h);
	~Oval();
	int getWidth();
	int getHeight();
	void set(int w, int h);
	void show();
};

//구현부
Oval::Oval() {
	width = 1;
	height = 1;
}

Oval::Oval(int w, int h) {
	width = w;
	height = h;
}

Oval::~Oval() {
	cout << "Oval 소멸 : width = " << width << ", height = " << height << endl;
}

int Oval::getWidth() {
	return width;
}

int Oval::getHeight() {
	return height;
}

void Oval::set(int w, int h) {
	width = w;
	height = h;
}

void Oval::show() {
	cout << width << ", " << height << endl;
}

int main() {
	Oval a, b(3, 4);
	a.set(10, 20);
	a.show();
	cout << b.getWidth() << ", " << b.getHeight() << endl;


	return 0;
}

 

 

10. 다수의 클래스를 선언하고 활용하는 간단한 문제이다. 더하기(+), 빼기(-), 곱하기(*), 나누기(/)를 수행하는 4개의 클래스 Add, Sub, Mul, Div를 만들고자 한다. 이들은 모두 공통으로 다음 멤버를 가진다.

  • int 타입 변수 a, b: 피연산자
  • void setValue(int x, int y) 함수: 매개 변수 x, y를 멤버 a, b에 복사
  • int calculate() 함수: 연산을 실행하고 결과 리턴

main() 함수는 Add, Sub, Mul, Div 클래스 타입의 객체 a, s, m, d를 생성하고, 아래와 같이 키보드로부터 두 개의 정수와 연산자를 입력받고, a, s, m, d 객체 중에서 연산을 처리할 객체의 setValue() 함수를 호출한 후, calculate()를 호출하여 결과를 화면에 출력한다. 프로그램은 무한 루프를 돈다. 

<실행화면>

<소스코드>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Add {
	int a, b;
public:
	void setValue(int x, int y);
	int calculate();
};
void Add::setValue(int x, int y) {
	a = x;
	b = y;
}
int Add::calculate() {
	return a + b;
}

class Sub {
	int a, b;
public:
	void setValue(int x, int y);
	int calculate();
};
void Sub::setValue(int x, int y) {
	a = x;
	b = y;
}
int Sub::calculate() {
	return a - b;
}

class Mul {
	int a, b;
public:
	void setValue(int x, int y);
	int calculate();
};
void Mul::setValue(int x, int y) {
	a = x;
	b = y;
}
int Mul::calculate() {
	return a * b;
}


class Div {
	int a, b;
public:
	void setValue(int x, int y);
	int calculate();
};
void Div::setValue(int x, int y) {
	a = x;
	b = y;
}
int Div::calculate() {
	return a / b;
}

int main() {
	Add a;
	Sub s;
	Mul m;
	Div d;

	int x, y;
	char op;
	
	while (true) {
		cout << "두 정수와 연산자를 입력하세요>>";
		cin >> x >> y >> op;

		switch (op)
		{
		case '+':
			a.setValue(x, y);
			cout << a.calculate() << endl;
			break;
		case '-':
			s.setValue(x, y);
			cout << s.calculate() << endl;
			break;
		case '*':
			m.setValue(x, y);
			cout << m.calculate() << endl;
			break;
		case '/':
			d.setValue(x, y);
			cout << d.calculate() << endl;
			break;
		}
	}

	return 0;
}

 

 

11. 다음 코드에서 Box 클래스의 선언부와 구현부를 Box.h, Box.cpp 파일로 분리하고 amin() 함수 부분을 main.cpp로 분리하여 전체 프로그램을 완성하라. 

<실행화면>

<소스코드>

//Box.h

#ifndef BOX_H
#define BOX_H

class Box {
	int width, height;
	char fill;
public:
	Box(int w, int h) { setSize(w, h); fill = '*'; }
	void setFill(char f) { fill = f; }
	void setSize(int w, int h) {
		width = w;
		height = h;
	}
	void draw();	//박스 그리기
};

#endif BOX_H

클래스의 선언부를 작성할 때, #ifndef, #define, #endif 사용에 주의하자!!!!

//Box.cpp

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

void Box::draw() {
	for (int n = 0; n < height; n++) {
		for (int m = 0; m < width; m++)
			cout << fill;
		cout << endl;
	}
}
//main.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Box.h"
using namespace std;

int main() {
	Box b(10, 2);
	b.draw();	//박스를 그린다.
	cout << endl;
	b.setSize(7, 4);	//박스의 크기를 변경한다.
	b.setFill('^');		//박스의 내부를 채울 문자를 '^'로 변경한다.
	b.draw();

	return 0;
}

 

 

12. 컴퓨터의 주기억장치를 모델링하는 클래스 Ram을 구현하려고 한다. Ram 클래스는 데이터가 기록될 메모리 공간과 크기 정보를 가지고, 주어진 주소에 데이터를 기록하고(write), 주어진 주소로부터 데이터를 읽어 온다(read). Ram 클래스는 다음과 같이 선언된다.

class Ram {
	char mem[100 * 1024];	//1024K 메모리. 한 번지는 한 바이트이므로 char 타입 사용
	int size;
public:
	Ram();	//mem 배열을 0으로 초기화하고 size를 100*1024로 초기화
	~Ram();	//"메모리 제거됨" 문자열 출력
	char read(int address);	//address 주소의 메모리 바이트 리턴
	void write(int address, char value); //address 주소에 한 바이트로 value 저장
};

다음 main() 함수는 100번지에 20을 저장하고, 101번지에 30을 저장한 후, 100번지와 101번지의 값을 읽고 더하여 저장하는 코드이다. 실행 결과를 참고하여 Ram.h, Ram.cpp, main.cpp로 헤더 파일과 cpp 파일을 분리하여 프로그램을 작성하라. 

int main() {
	Ram ram;
	ram.write(100, 20);		//100 번지에 20 저장
	ram.write(101, 30);		//101 번지에 30 저장
	char res = ram.read(100) + ram.read(101);	//20 + 30 = 50
	ram.wrire(102, res);	//102 번지에 50 저장
	cout << "102 번지의 값 = " << (int)ram.read(102) << endl;	//102 번지 값 출력

	return 0;
}

<실행화면>

<소스코드>

//Ram.h

#ifndef RAM_H
#define RAM_H

class Ram {
	char mem[100 * 1024];	//1024K 메모리. 한 번지는 한 바이트이므로 char 타입 사용
	int size;
public:
	Ram();	//mem 배열을 0으로 초기화하고 size를 100*1024로 초기화
	~Ram();	//"메모리 제거됨" 문자열 출력
	char read(int address);	//address 주소의 메모리 바이트 리턴
	void write(int address, char value); //address 주소에 한 바이트로 value 저장
};

#endif RAM_H
//Ram.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Ram.h"
using namespace std;

Ram::Ram() {
	size = 100 * 1024;
	for (int i = 0; i < size; i++) {
		mem[i] = 0;
	}
}

Ram::~Ram() {
	cout << "메모리 제거됨" << endl;
}

char Ram::read(int address) {
	return mem[address];
}

void Ram::write(int address, char value) {
	mem[address] = value;
}
//main.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Ram.h"
using namespace std;

int main() {
	Ram ram;
	ram.write(100, 20);		//100 번지에 20 저장
	ram.write(101, 30);		//101 번지에 30 저장
	char res = ram.read(100) + ram.read(101);	//20 + 30 = 50
	ram.write(102, res);	//102 번지에 50 저장
	cout << "102 번지의 값 = " << (int)ram.read(102) << endl;	//102 번지 값 출력

	return 0;
}

관련글 더보기