Language/C++

📌예제 - 은행 계좌 관리 시스템 (고급 구현)

e-cko 2025. 10. 31. 17:44
반응형

아래 요구사항을 만족하는 은행 계좌 관리 프로그램을 작성하시오.


🏗️ 클래스 구조

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

        }

    }

}

반응형