챕터5. 실습 문제
2025. 3. 28. 00:07ㆍProgramming Languages/C++
5.7 실습 문제
문제 1: 은행 계좌 시스템
다양한 유형의 은행 계좌를 구현하는 클래스 계층 구조를 설계하세요:
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
// 추상 기본 클래스
class Account {
protected:
std::string accountNumber;
std::string ownerName;
double balance;
public:
Account(const std::string& number, const std::string& name, double initialBalance)
: accountNumber(number), ownerName(name), balance(initialBalance) {}
// 가상 소멸자
virtual ~Account() {}
// 모든 계좌 유형에 공통적인 메서드
virtual void deposit(double amount) {
if (amount > 0) {
balance += amount;
std::cout << amount << "원 입금 완료" << std::endl;
} else {
std::cout << "유효하지 않은 금액입니다." << std::endl;
}
}
// 순수 가상 함수 - 파생 클래스에서 구현해야 함
virtual bool withdraw(double amount) = 0;
// 계좌 정보 표시
virtual void displayInfo() const {
std::cout << "계좌번호: " << accountNumber << std::endl;
std::cout << "소유자: " << ownerName << std::endl;
std::cout << "잔액: " << balance << "원" << std::endl;
}
// 접근자 메서드
double getBalance() const { return balance; }
std::string getAccountNumber() const { return accountNumber; }
std::string getOwnerName() const { return ownerName; }
};
// 일반 계좌
class SavingsAccount : public Account {
private:
double interestRate; // 연이율 (%)
public:
SavingsAccount(const std::string& number, const std::string& name,
double initialBalance, double rate)
: Account(number, name, initialBalance), interestRate(rate) {}
// withdraw 구현
bool withdraw(double amount) override {
if (amount > 0 && balance >= amount) {
balance -= amount;
std::cout << amount << "원 출금 완료" << std::endl;
return true;
} else {
std::cout << "잔액 부족 또는 유효하지 않은 금액" << std::endl;
return false;
}
}
// 저축 계좌 전용 메서드: 이자 계산
void applyInterest() {
double interest = balance * (interestRate / 100.0);
balance += interest;
std::cout << interest << "원의 이자가 추가되었습니다." << std::endl;
}
// 계좌 정보 표시 오버라이딩
void displayInfo() const override {
Account::displayInfo();
std::cout << "계좌 유형: 저축 계좌" << std::endl;
std::cout << "이자율: " << interestRate << "%" << std::endl;
}
};
// 당좌 계좌 (마이너스 통장)
class CheckingAccount : public Account {
private:
double overdraftLimit; // 마이너스 한도
public:
CheckingAccount(const std::string& number, const std::string& name,
double initialBalance, double limit)
: Account(number, name, initialBalance), overdraftLimit(limit) {}
// withdraw 구현 - 마이너스 한도까지 출금 가능
bool withdraw(double amount) override {
if (amount > 0 && (balance + overdraftLimit) >= amount) {
balance -= amount;
std::cout << amount << "원 출금 완료";
if (balance < 0) {
std::cout << " (마이너스 잔액: " << balance << "원)";
}
std::cout << std::endl;
return true;
} else {
std::cout << "출금 한도 초과 또는 유효하지 않은 금액" << std::endl;
return false;
}
}
// 계좌 정보 표시 오버라이딩
void displayInfo() const override {
Account::displayInfo();
std::cout << "계좌 유형: 당좌 계좌" << std::endl;
std::cout << "마이너스 한도: " << overdraftLimit << "원" << std::endl;
}
};
// 은행 시스템 클래스
class Bank {
private:
std::string name;
std::vector<Account*> accounts;
public:
Bank(const std::string& bankName) : name(bankName) {}
~Bank() {
// 모든 계좌 메모리 해제
for (Account* account : accounts) {
delete account;
}
}
// 새 계좌 추가
void addAccount(Account* account) {
accounts.push_back(account);
}
// 계좌 검색
Account* findAccount(const std::string& accountNumber) {
for (Account* account : accounts) {
if (account->getAccountNumber() == accountNumber) {
return account;
}
}
return nullptr;
}
// 모든 계좌 정보 표시
void displayAllAccounts() const {
std::cout << "===== " << name << " 은행 계좌 목록 =====" << std::endl;
for (size_t i = 0; i < accounts.size(); i++) {
std::cout << "\n계좌 #" << (i + 1) << ":" << std::endl;
accounts[i]->displayInfo();
}
}
};
int main() {
Bank bank("C++ 은행");
// 계좌 생성
SavingsAccount* savings = new SavingsAccount("S123", "홍길동", 10000, 2.5);
CheckingAccount* checking = new CheckingAccount("C456", "김철수", 2000, 5000);
// 은행에 계좌 추가
bank.addAccount(savings);
bank.addAccount(checking);
// 계좌 정보 표시
bank.displayAllAccounts();
// 계좌 조작
std::cout << "\n===== 계좌 조작 =====" << std::endl;
Account* account = bank.findAccount("S123");
if (account) {
account->deposit(5000);
account->withdraw(3000);
// 저축 계좌면 이자 적용
SavingsAccount* savingsPtr = dynamic_cast<SavingsAccount*>(account);
if (savingsPtr) {
savingsPtr->applyInterest();
}
}
account = bank.findAccount("C456");
if (account) {
account->deposit(1000);
account->withdraw(7000); // 마이너스 통장 활용
}
// 업데이트된 계좌 정보 표시
std::cout << "\n===== 업데이트된 계좌 정보 =====" << std::endl;
bank.displayAllAccounts();
return 0;
}
문제 2: 도형 계층 구조 구현
다양한 도형(원, 직사각형, 삼각형 등)에 대한 계층 구조를 설계하고, 각 도형의 면적과 둘레를 계산하는 프로그램을 작성하세요.
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
// 추상 기본 클래스
class Shape {
protected:
std::string name;
public:
Shape(const std::string& n) : name(n) {}
virtual ~Shape() {}
virtual double area() const = 0;
virtual double perimeter() const = 0;
void printInfo() const {
std::cout << "도형: " << name << std::endl;
std::cout << "면적: " << area() << std::endl;
std::cout << "둘레: " << perimeter() << std::endl;
}
std::string getName() const { return name; }
};
// 원 클래스
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : Shape("원"), radius(r) {}
double area() const override {
return M_PI * radius * radius;
}
double perimeter() const override {
return 2 * M_PI * radius;
}
double getRadius() const { return radius; }
};
// 직사각형 클래스
class Rectangle : public Shape {
private:
double width;
double height;
public:
Rectangle(double w, double h) : Shape("직사각형"), width(w), height(h) {}
double area() const override {
return width * height;
}
double perimeter() const override {
return 2 * (width + height);
}
double getWidth() const { return width; }
double getHeight() const { return height; }
};
// 정사각형 클래스 (직사각형 파생)
class Square : public Rectangle {
public:
Square(double side) : Rectangle(side, side) {
name = "정사각형"; // 이름 재정의
}
};
// 삼각형 클래스
class Triangle : public Shape {
private:
double a, b, c; // 세 변의 길이
public:
Triangle(double side1, double side2, double side3)
: Shape("삼각형"), a(side1), b(side2), c(side3) {
// 삼각형 조건 검사
if (!isValid()) {
std::cout << "경고: 유효하지 않은 삼각형입니다." << std::endl;
}
}
bool isValid() const {
// 삼각형 부등식: 두 변의 합 > 나머지 한 변
return (a + b > c) && (a + c > b) && (b + c > a);
}
double area() const override {
if (!isValid()) return 0;
// 헤론의 공식
double s = (a + b + c) / 2;
return std::sqrt(s * (s - a) * (s - b) * (s - c));
}
double perimeter() const override {
return a + b + c;
}
};
// 도형 관리 클래스
class ShapeManager {
private:
std::vector<Shape*> shapes;
public:
~ShapeManager() {
for (Shape* shape : shapes) {
delete shape;
}
}
void addShape(Shape* shape) {
shapes.push_back(shape);
}
void printAllShapes() const {
std::cout << "\n===== 모든 도형 정보 =====" << std::endl;
for (size_t i = 0; i < shapes.size(); i++) {
std::cout << "\n" << (i + 1) << ". ";
shapes[i]->printInfo();
}
}
double getTotalArea() const {
double total = 0;
for (const Shape* shape : shapes) {
total += shape->area();
}
return total;
}
};
int main() {
ShapeManager manager;
// 다양한 도형 추가
manager.addShape(new Circle(5.0));
manager.addShape(new Rectangle(4.0, 6.0));
manager.addShape(new Square(5.0));
manager.addShape(new Triangle(3.0, 4.0, 5.0));
// 모든 도형 정보 출력
manager.printAllShapes();
// 전체 면적 계산
std::cout << "\n모든 도형의 총 면적: " << manager.getTotalArea() << std::endl;
return 0;
}
'Programming Languages > C++' 카테고리의 다른 글
| 포인터의 기본 (0) | 2025.03.28 |
|---|---|
| 포인터와 참조 (0) | 2025.03.28 |
| 다형성(Polymorphism) (0) | 2025.03.28 |
| 상속(Inheritance) (0) | 2025.03.28 |
| 객체 생성과 수명 주기 (0) | 2025.03.28 |