아래 요구사항을 만족하는 은행 계좌 관리 프로그램을 작성하시오.
🏗️ 클래스 구조
- Account 클래스는 추상 클래스(순수 가상 함수 포함) 이어야 한다.
- NormalAccount, HighCreditAccount, SavingsAccount 클래스를 파생시킨다.
⚠️ 예외 처리
- AccountException 을 기반으로
- 잘못된 입출금 요청 시 예외를 발생시키고, 호출부에서 처리한다.
🔄 형변환 연산자 활용
- 모든 계좌 중 SavingsAccount 만 출력하는 기능을 dynamic_cast 로 구현한다.
📚 STL 활용
- 모든 계좌는 std::vector<std::unique_ptr<Account>> 로 관리한다.
- 계좌 검색 시 std::find_if 와 람다 표현식을 사용한다.
💾 파일 입출력
- 프로그램 종료 시, 모든 계좌 정보를 accounts.txt 파일에 저장한다.
- 프로그램 실행 시, accounts.txt 를 읽어 계좌 정보를 복원한다.
🧠 스마트 포인터
- 모든 계좌는 std::unique_ptr<Account> 로 관리한다.
- 소멸자에서 delete 를 직접 호출하지 않는다.
🖥️ 실행 예시
계좌ID: 1001 / 이름: Kim / 잔액: 4000
계좌ID: 1002 / 이름: Lee / 잔액: 12100
계좌ID: 1003 / 이름: Park / 잔액: 5030
✅ [적립형 계좌 목록]
계좌ID: 1003 / 이름: Park / 잔액: 5030
📂 accounts.txt (예시 저장 내용)
Normal 1001 Kim 4000
High 1002 Lee 12100 5
Savings 1003 Park 5030
👉 이 문제를 기반으로 프로그램을 구현하시오.
스크롤을 내리면 제가 직접 작성한 코드가 있습니다.
먼저 직접 풀어보시고 참고만 해주시길 바라며, 피드백 환영입니다.
Account.h
#pragma once
#include <string>
#include "Exception.h"
class Account {
private:
unsigned short id;
std::string name;
unsigned int balance=0;
public:
Account(unsigned short id, std::string& name, unsigned int balance) :id(id), name(name), balance(balance) {}
const unsigned short getId();
const std::string& getName();
const unsigned int getBalance();
virtual unsigned int deposit(int money);
virtual unsigned int withdraw(int money);
virtual void showInfo() const;
};
class NormalAccount: public Account {
public:
NormalAccount(unsigned short id, std::string& name, unsigned int balance) :Account(id, name, balance) {}
};
class HighCreditAccount : public Account {
unsigned short credit;
public:
HighCreditAccount(unsigned short id, std::string& name, unsigned int balance, unsigned short credit) :Account(id, name, balance), credit(credit) {}
unsigned int deposit(int money) override;
virtual void showInfo() const override;
};
class SavingsAccount :public Account {
public:
SavingsAccount(unsigned short id, std::string& name, unsigned int balance) :Account(id, name, balance){}
unsigned int deposit(int money) override;
};
Account.cpp
#include <iostream>
#include "Account.h"
#include "Exception.h"
const unsigned short Account::getId()
{
return id;
}
const std::string& Account::getName()
{
return name;
}
const unsigned int Account::getBalance()
{
return balance;
}
unsigned int Account::deposit(int money)
{
if (money < 1)
throw DepositException();
return balance += money;
}
unsigned int Account::withdraw(int money)
{
if (money > balance)
throw WithdrawException();
return balance -= money;
}
void Account::showInfo() const
{
std::cout << "계좌: " << id << ", 이름: " << name << ", 잔액: " << balance << std::endl;
}
unsigned int HighCreditAccount::deposit(int money)
{
return Account::deposit(money+=money*(credit/100));
}
void HighCreditAccount::showInfo() const
{
std::cout << "계좌종류: High, ";
Account::showInfo();
}
unsigned int SavingsAccount::deposit(int money)
{
return Account::deposit(money+=money*0.01);
}
Bank.h
#pragma once
#include <vector>
#include <memory>
#include "Account.h"
class Bank {
std::vector<std::unique_ptr<Account>> accounts;
public:
bool init();
void account();
void deposit();
void withdraw();
void showInfo();
void showAllInfo();
};
Bank.cpp
#include <iostream>
#include <algorithm>
#include <string>
#include <fstream>
#include <sstream>
#include "Bank.h"
#include "Account.h"
using namespace std;
bool Bank::init() {
ifstream file("account.txt");
if (!file) {
std::cout << "계좌 정보 로딩 Error." << std::endl;
return false;
}
string acc;
while (getline(file, acc)) {
istringstream ac(acc);
unsigned short n;
unsigned short id;
string name;
unsigned int balance;
ac >> acc;
if (acc == "Normal") n = 1;
else if (acc == "High") n = 2;
else n = 3;
ac >> id >> name >> balance;
if (n == 1)
accounts.push_back(make_unique<NormalAccount>(id, name, balance));
else if (n == 2)
accounts.push_back(make_unique<HighCreditAccount>(id, name, balance, 3));
else
accounts.push_back(make_unique<SavingsAccount>(id, name, balance));
}
file.close();
return true;
}
void Bank::account()
{
short acc=1;
int id;
string name;
int balance;
while (1) {
cout << "1. 일반 계좌, 2.신용 계좌 3.세이브 계좌" << endl << "계좌 종류: ";
cin >> acc;
if (acc > 3 || acc < 1) {
cout << "올바른 1~3의 숫자만 입력해주세요." << endl;
continue;
}
break;
}
while (1) {
cout << "계좌 : ";
cin >> id;
if (cin.fail()) {
cout << "숫자만 입력해야 합니다." << endl;
cin.clear(); // 입력 스트림 오류 상태 초기화
cin.ignore(1000, '\n'); // 버퍼에서 잘못된 입력 제거
continue;
}
bool b = any_of(accounts.begin(), accounts.end(), [id](const std::unique_ptr<Account>& acc) { return acc->getId() == id; });
if (b) {
cout << "다른 계좌번호를 입력해주세요." << endl;
continue;
}
break;
}
while (1) {
cout << "이름: ";
cin >> name;
bool check = any_of(name.begin(), name.end(), [](char ch)
{ return isdigit(static_cast<unsigned char>(ch)) || ispunct(static_cast<unsigned char>(ch)); });
if (check) {
cout << "이름에 숫자나 특수문자는 입력할 수 없습니다." << endl;
continue;
}
break;
}
while (1) {
cout << "입금액: ";
cin >> balance;
if (balance < 1) {
cout << "1원 이상 입금 가능합니다." << endl;
continue;
}
break;
}
ofstream ofs("account.txt", ios::app);
if (!ofs) {
std::cout << "계좌 정보 로딩 Error." << std::endl;
return;
}
if (acc == 1) {
ofs << "Normal ";
accounts.push_back(make_unique<NormalAccount>(id, name, balance));
}
else if (acc == 2) {
ofs << "High ";
accounts.push_back(make_unique<HighCreditAccount>(id, name, balance, 3));
}
else {
ofs << "Saving ";
accounts.push_back(make_unique<SavingsAccount>(id, name, balance));
}
ofs << id << " " << name << " " << balance << endl;
ofs.close();
cout << "계좌 개설이 완료되었습니다." << endl;
}
void Bank::deposit()
{
unsigned int id;
while (1) {
cout << "계좌 : ";
cin >> id;
if (cin.fail()) {
cout << "숫자만 입력해야 합니다." << endl;
cin.clear(); // 입력 스트림 오류 상태 초기화
cin.ignore(1000, '\n'); // 버퍼에서 잘못된 입력 제거
continue;
}
vector<unique_ptr<Account>>::iterator i = find_if(accounts.begin(), accounts.end(), [id](unique_ptr<Account>& acc) { return acc->getId() == id; });
try {
if (i == accounts.end())
throw AccountNotFoundException();
else {
int balance = 0;
while (1) {
cout << "입금액 입력 : ";
cin >> balance;
try {
(*i)->deposit(balance);
cout << "입금이 완료되었습니다." << endl << "계좌 잔액: " << balance << endl;
return;
}
catch (AccountException& ex) {
ex.showException();
}
}
}
}
catch (AccountException& ex) {
ex.showException();
}
}
}
void Bank::withdraw()
{
unsigned int id;
while (1) {
cout << "계좌 : ";
cin >> id;
if (cin.fail()) {
cout << "숫자만 입력해야 합니다." << endl;
cin.clear(); // 입력 스트림 오류 상태 초기화
cin.ignore(1000, '\n'); // 버퍼에서 잘못된 입력 제거
continue;
}
vector<unique_ptr<Account>>::iterator i = find_if(accounts.begin(), accounts.end(), [id](unique_ptr<Account>& acc) { return acc->getId() == id; });
try {
if (i == accounts.end())
throw AccountNotFoundException();
else {
unsigned int balance = 0;
while (balance) {
cout << "출금액 입력 : ";
cin >> balance;
try {
(*i)->withdraw(balance);
cout << "출금이 완료되었습니다." << endl << "계좌 잔액: " << balance << endl;
return;
}
catch (AccountException& ex) {
ex.showException();
}
}
}
}
catch (AccountException& ex) {
ex.showException();
}
}
}
void Bank::showInfo()
{
unsigned int id;
while (1) {
cout << "계좌 : ";
cin >> id;
if (cin.fail()) {
cout << "숫자만 입력해야 합니다." << endl;
cin.clear(); // 입력 스트림 오류 상태 초기화
cin.ignore(1000, '\n'); // 버퍼에서 잘못된 입력 제거
continue;
}
vector<unique_ptr<Account>>::iterator i = find_if(accounts.begin(), accounts.end(), [id](unique_ptr<Account>& acc) { return acc->getId() == id; });
try {
if (i == accounts.end())
throw AccountNotFoundException();
else {
cout << endl;
if (dynamic_cast<SavingsAccount*>((*i).get()))
cout << "계좌종류: 세이브 계좌, ";
(*i)->showInfo();
cout << endl;
cout << endl;
return;
}
}
catch (AccountException& ex) {
ex.showException();
}
}
}
void Bank::showAllInfo()
{
cout << endl;
cout << endl;
for (unique_ptr<Account>& i : accounts) {
if (dynamic_cast<SavingsAccount*>(i.get()))
cout << "계좌종류: 세이브 계좌";
(i)->showInfo();
}
cout << endl;
}
Exception.h
#pragma once
class AccountException {
public:
virtual void showException() const = 0;
};
class DepositException: public AccountException {
void showException() const override;
};
class WithdrawException: public AccountException{
void showException() const override;
};
class AccountNotFoundException: public AccountException{
void showException() const override;
};
Exception.cpp
#include "Exception.h"
#include <iostream>
using namespace std;
void DepositException::showException() const
{
cout << "입금액은 0원 보다 커야합니다." << endl;
}
void WithdrawException::showException() const
{
cout << "잔액이 부족합니다." << endl;
}
void AccountNotFoundException::showException() const
{
cout << "해당 계좌를 찾을 수 없습니다." << endl;
}
main.cpp
#include "Bank.h"
#include <iostream>
int main() {
Bank bank;
if (!bank.init())
return 0;
while (1) {
unsigned short ch;
std::cout << "0. 종료" << std::endl;
std::cout << "1. 계좌 개설" << std::endl;
std::cout << "2. 입금" << std::endl;
std::cout << "3. 출금" << std::endl;
std::cout << "4. 계좌 검색" << std::endl;
std::cout << "5. 모든 계좌 출력" << std::endl;
std::cout << "선택: ";
std::cin >> ch;
switch (ch)
{
case 0:
return 0;
case 1:
bank.account();
break;
case 2:
bank.deposit();
break;
case 3:
bank.withdraw();
break;
case 4:
bank.showInfo();
break;
case 5:
bank.showAllInfo();
break;
default:
std::cout << "0~5 사이만 입력해주세요." << std::endl;
}
}
}
'Language > C++' 카테고리의 다른 글
| 📌예제 - 온라인 쇼핑몰 주문 관리 시스템 (0) | 2025.11.01 |
|---|---|
| 📌 Chapter 14 - 형변환 연산자 (C++ Casting Operators) (0) | 2025.10.30 |
| 📌 Chapter 13 - 예외처리 (Exception Handling) (0) | 2025.10.28 |
| 📌 Chapter 12 - 클래스 템플릿 (0) | 2025.10.24 |
| 📌 Chapter 12 - 템플릿 (0) | 2025.10.24 |