C++. ATM Project ver.final

lsw·2021년 4월 12일
0

Mini Projects

목록 보기
7/11
post-thumbnail

1. 파이널 업데이트

  • 예외처리(exception handling)

    예외 처리에 관하여..

  1. 입금(deposit) 시 1원 미만의 값이 입력되면 예외 처리를 진행할 것

  2. 출금(withdraw) 시 잔액보다 높은 금액이 출금액으로 입력된다면 예외 처리를 진행할 것

    (If you wanna know detailed explanation about exception handling notion, check back to series C++ → exception handling course.. uploaded before)

  • 코드리뷰

    여지껏 여섯차례에 걸쳐 업데이트된 ATM Project의 최종버전 코드를 총 망라하여 리뷰하고자 함


2. 시퀀스

  • 각 입금, 출금에 해당하는 에외처리 클래스를 생성한다.
  • 생성한 클래스를 묶어주기 위해(간단히 표현하기 위해) 기초 클래스를 생성한다
  • 상기 세 클래스의 선언을 담을 "exception.h" 파일과 정의를 담을 "exception.cpp"파일을 생성한다.
  • 입금, 출금함수를 갖는 accounthandler클래스를 담고있는 "accounthandler.cpp" 파일에서 "exception.h" 파일을 인클루드(참조) 한다.
  • 실행이 잘 되는지 확인한다.

3. ATM 프로젝트 파이널 리뷰

each header-source pair

  • string pair(string.h - string.cpp)

    문자열에 관련하여

  1. 문자열 변수를 멤버로 지니는 클래스에서 번거로이 동적할당할 부담을 줄이고
  2. 다양한 기능의 연산자(이어붙이기 - '+', 카피 - '=', 비교 - '==', 입력 - '>>', 출력 - '<<') 오버로딩을 하는 string class의 선언-정의 파일

string.h

/*string.h*/
#pragma once // 중복 참조 방지
#include<iostream>
using namespace std;

class String
{
private:
	int len;  
	char* str;

public:
// 디폴트 생성자(동적할당 - 깊은복사)
	String();
// 인자를 갖는 생성자
	String(const char* Str);
// 복사생성자(복사 시 동적할당(깊은복사) : 선언 & 복사)
	String(const String& scopy);
// 대입연산자(복사 시 동적할당(깊은복사) : 선언 -> 복사)
	String& operator=(const String& scopy);
// str에 str2을 이어붙인 값을 반환(strcat역할)
	String operator+(const String& str2);
// str에 str2을 이어붙인 값으로 str을 재초기화
	String& operator +=(const String& str2);
// 두 문자열의 일치 비교(strcmp의 역할)
	bool operator==(const String& str2);
// string 출력, const선언
	friend ostream& operator<<(ostream& cout, const  String& str);
// string 입력(입력이기에 no const)
	friend istream& operator>>(istream& cin, String& str);
};

string.cpp

/*string.cpp*/
#include "string.h" 
#include <iostream>
#include<cstring> 
#include <cstdlib>
using namespace std;

// 디폴트 생성자 정의, len=0, str=NULL 값이 저장된다.
String::String()
{
    len = 0;
    str = 0;
}
// 인자가 있는 생성자 정의
String::String(const char* Str)
{
    len = strlen(Str) + 1; // '\n'을 포함할 길이 1 추가
    str = new char[len]; // 동적할당
    strcpy(str, Str); // 문자열 복사
}
// 복사생성자 정의
String::String(const String& scopy)
{
    len = scopy.len + 1;
    str = new char[len]; // 동적할당
    strcpy(str, scopy.str); // 복사
}
// 대입연산자의 정의
String& String::operator=(const String& scopy)
{
    len = scopy.len + 1;
    str = new char[len];
    strcpy(str, scopy.str);
    return *this;
}
// str에 str2이어붙인 값을 반환하는 함수('+'연산자 오버로드 함수)
String String::operator+(const String& str2)
{
// 좌피연산자가 디폴트 생성 객체 시 exit 
    if (str == NULL)
    {
        exit(1);
    }
// 이미 '\n'을 위한 공간 1은 기존 len에 의해 확보. 중복에 의한 길이 1을 빼준다
    int len2 = len + str2.len - 1;
// 초기화가 아닌 반환임에, 템포러리 변수를 지정해 준다.
    char* tempstr = new char[len2];
// 임시변수에 str문자열을 복사 
    strcpy(tempstr, str);
// str문자열 공간 뒤에 str2.str을 이어붙임
    strcat(tempstr, str2.str);
    String temps(tempstr); // tempstr 를 인자로 받는 생성자 호출을 통해 String 객체 생성
    return temps; // 반환(초기화x)
}
// 초기화 까지 진행하는 연산자 '+=' 오버로드 함수
String& String::operator +=(const String& str2)
{
// 마찬가지 디폴트 생성 객체 시 exit(오류)발생
    if (str == NULL)
    {
        exit(1);
    }
    *this = *this + str2; // 바로 위에서 정의한 '+'연산자 오버로드 함수를 호출, 재초기화
    return *this; // 초기화된 str을 반환하는 모습
}
// 두 string 일치 비교 함수, boolean
bool String::operator==(const String& str2)
{
    if (str == NULL)
    {
        exit(1);
    }
    if (strcmp(str, str2.str) == 0)
// 두 문자열이 같다면
        return true; // true 반환
    else
// 두 문자열이 다르다면
        return false; // false 반환
}
// 출력 : '<<'연산자 오버로드 함수
ostream& operator<<(ostream& cout, const String& str1) 
// 여기 cout에는 특정한 의미가 없다. 단지 ostream 객체 참조형 변수일 뿐.
{
    cout << str1.str << endl; // str1객체의 str변수를 출력한다.
    return cout;
}
// 입력 : '>>'연산자 오버로드 함수
istream& operator>>(istream& cin, String& str1)
{
    char str[100]; // 길이 100짜리 변수 생성
    cin >> str; // 변수 초기화
    str1 = String(str); // 대입연사자 호출, 해당변수를 인자로 받는 String객체로 복사진행
    return cin;
}
  • account(account.h - account.cpp)
  1. (순수)가상함수가 되며 실제 객체 생성까지 이어지지 않는 account class의 선언-정의와 관련한 파일
  2. 다른 class(high, normal)의 기초클래스가 된다.

account.h

#pragma once 
#include "string.h" 
#include<iostream>
using namespace std;

// Account class, Account * type인 ACCOUNT_PTR 형 선언
class Account;
typedef Account* ACCOUNT_PTR;

// 고객 등급과 관련한 이름공간 정의
namespace TYPE
{
	enum
	{
		NORMAL = 1, HIGH
	};
}

// 기능과 관련된 문자에 수의 의미를 담는 열거(enumerating)
enum
{
	MAKE = 1, DEPOSIT, WITHDRAW, SHOW, EXIT
};

/*기존 고객명, 고객계좌번호의 길이를 전역변수 선언을 이용해 정했다면, String class객체 이용
  시 입력받은 문자의 길이로 문자열의 길이를 할당하므로 이를 생략할 수 있다*/

// virtual class(만약 순수가상함수로 지정 시 실제 객체생성 불가능)
/*Account class*/
class Account
{
private:
// 문자열 변수인 계좌번호, 이름을 String 객체로 생성 
	String acc_id;
	String acc_name;
	double acc_balance; // 잔액

	// 생성자
public:
	Account(String acc_id, String acc_name, double acc_seed);

	// 기타 재료함수(추후 접근용)
	String Get_id(); // 계좌번호 반환
	double Get_balance(); // 계좌 잔액 반환
	virtual void Proccess_depos(double money)=0; 
/*입금함수 : 계좌 유형별 상이한 입금과정(이율로인한)에 의해 다르게 정의될 예정이며(오버로드)
  함수 접근 시 접근객체의 클래스에 맞는 오버로드함수 호출을 위해 virtual선언을 한 모습.
  Account클래스는 객체생성이 불필요한 클래스로, 순수가상 클래스로 지정하기 위해 입금 함수를
  순수가상 함수로 정의하는 모습 (=0)*/
	void Proccess_withdraw(double money); // 출금 함수
// 배열 인자들의 각 타입에 맞는 출력함수(Showinform function의 역할)
// (declared with 'friend' to access Accountclass member variables)
	friend ostream& operator<<(ostream& cout, Account& ref); // 반환형이 참조형일때
	friend ostream& operator<<(ostream& cout, ACCOUNT_PTR& Aref); // 반환형이 포인터형일때
};

account.cpp

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

/*about Account class*/
/*생성자*/
Account::Account(String Acc_id, String Acc_name, double acc_seed)
    :acc_balance(acc_seed)
{
// String클래스의 대입연산자 호출, 깊은복사 진행
    acc_id = Acc_id;  
    acc_name = Acc_name; 
}

/*기타 함수*/
// 계좌번호 반환
String Account::Get_id()
{
    return acc_id;
}
// 계좌 잔액 반환(소수점 표현을 위해 double)
double Account::Get_balance()
{
    return acc_balance;
}

/*입금함수 오버로드 1*/
// virtual 선언
void Account::Proccess_depos(double money)
{
    acc_balance += money; 
}
// 출금함수
void Account::Proccess_withdraw(double money)
{
    acc_balance -= money; // 잔액을 줄이고
}

// 전역함수("<<"operator overload functions)
ostream& operator<<(ostream& cout, Account& ref)
{
    cout << "계좌번호 : " << ref.acc_id ;
    cout << "성명 : " << ref.acc_name ;
    cout << "잔액 : " << ref.acc_balance << endl;;
    return cout;
}
ostream& operator<<(ostream& cout, ACCOUNT_PTR& pref)
{
    cout << *(pref); 
/*
*(ACCOUNT_PTR) = Account
<< Account 는 바로 위 "<<"연산자 오버로드 함수 호출 시그널
*/
    return cout;
}
  • normal(normal.h - normal.cpp)
  1. 일반계좌이자 Account클래스를 상속받은 유도클래스에 해당하는 normal class의 선언-정의와 관련한 파일
  2. 입금 시 일반이율이 추가 적용된다(attribute)

normal.h

#include "account.h"
#include "string.h"
#pragma once

class Normal : public Account
{
private:
	double acc_rate; // 일반 이율

public:
// 생성자
	Normal(String id, String name, double seed, double rate);
// 입금함수 오버로드 2
	void Proccess_depos(double money);
// 일반이율 반환함수
	double Getrate();
};

normal.cpp

#include "account.h"
#include "normal.h"

/*about Normal class*/
// 생성자
Normal::Normal(String Acc_id, String Acc_name, double acc_seed, double rate)
    : acc_rate(rate), Account(Acc_id, Acc_name, acc_seed) // Account클래스 생성자 차용
{
}

// 입금함수 오버로드 2
void Normal::Proccess_depos(double money)
{
// 총 입금액 = 입금액 + 잔액*이율
    Account::Proccess_depos(money + Account::Get_balance() * acc_rate);
}

/*
두가지 옵션 존재
1. normal클래스의 변수 접근성을 protected로 완화하여 high클래스에서 acc_rate에 직접 접근
할 수 있도록 함
2. 지금과 같이 변수접근성은 private으로 유지하며(정보은닉의 장점) 별도 이율 반환함수룰 
정의한다.
*/
// 이율 반환 함수
double Normal::Getrate()
{
    return acc_rate;
}
  • high(high.h - high.cpp)
  1. normal 클래스를 상속받는 클래스인 high 클래스의 선언-정의와 관련한 파일
  2. normal 클래스에 고객등급과 그에 따른 특별이율 변수가 추가된 high 클래스(attribute)

high.h

#include "normal.h"
#include "string.h"
#pragma once

class High : public Normal
{
private:
	// 고객등급 - 특별이율 변수
	char acc_type; 
	double acc_srate; 

public:
// 생성자
	High(String id, String name, double seed, double rate, char type);
// 입금함수 오버로드 3
	void Proccess_depos(double money);
};

high.cpp

#include "high.h"
  #include "account.h"

  High::High(String id, String name, double seed, double rate, char type)
      : Normal(id, name, seed, rate)
  {
      // 인자로 입력받은 등급별 상이한 이율 제공(초기화)
      switch (type)
      {
      case 'A':
      {
          acc_srate = 0.07;
          break;
      }
      case 'B':
      {
          acc_srate = 0.04;
          break;
      }
      case 'C':
      {
          acc_srate = 0.02;
          break;
      }
      default:
      {
          cout << "유형을 재입력 하세요" << endl;
      }
    }
  }

  // 입금함수 오버로드 3
  void High::Proccess_depos(double money)
  {
  // 총 입금액 = 입금액 + 원금*(이율 + 특별이율)
      Account::Proccess_depos(money + Account::Get_balance() * (Getrate() + acc_srate));
  }
  • accountarray(accountarray.h - accountarray.cpp)
  1. 고객정보를 저장할 배열생성을 위한 배열클래스(클래스 템플릿)의 선언-정의와 관련한 파일
  2. 해당 클래스 객체 생성 시 템플릿 인자에 따라 각기 다른 템플릿 클래스를 호출한다.

accountarray.h

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

/*Accountarray클래스 템플릿*/
template <typename T> // 템플릿 인자 T
class Accountarray
{
private:
	T * arr;
	int len; // 배열 길이
/* 배열의 고유성 보장을 위해 복사와 관련한 복사생성자, 대입연산자는 접근성 'private'으로
제한 */
	Accountarray(Accountarray& Acopy);
	Accountarray& operator=(Accountarray& Acopy);

public:
/* 배열의 디폴트 길이를 100으로 하고자 함. 따라서 배열 길이에 대한 'len'인자를 받는 
생성자를 별도 정의하지 않겠음 -> 배열길이는 변함없이 100일 것이라는 얘기*/
	Accountarray(); // 디폴트 생성자
	T& operator[](int idx); // 피연산자가 const선언되지 않았을때 호출되는 함수
	T operator[](int idx) const; // 피연산자가 const선언되었을때 호출되는 함수 
	int Getlen(); // 배열길이 반환함수
  ~Accountarray(); // 동적할당으로 생성된 배열 소멸을 위한 소멸자
};

accountarray.cpp

#include "accountarray.h" // headerfile
#include <cstdlib> // exit..
#include "account.h"
#include <iostream>

/*생성자*/
template <typename T>
Accountarray<T>::Accountarray()
    :len(100) // 디폴트 len = 100
{
    arr = new T[100]; // 템플릿 인자에 맞는 동적할당
}

/*'[]'operator overload function 1(no const)*/
template <typename T>
T& Accountarray<T>::operator[](int idx)
{
// out of range
    if (idx < 0 || idx >= len)
    {
        cout << "out of range" << endl;
        exit(1);
    }
    return arr[idx]; 
/* 템플릿인자 T의 참조형 반환(no const라는 말은 접근하여 변경할 여지가 있다는 말. 따라서
참조형으로 반환한다*/
}

/*'[]'operator overload function 2(const)*/
template <typename T>
T Accountarray<T>::operator[](int idx) const
{
// out of range
    if (idx < 0 || idx >= len)
    {
        cout << "out of range" << endl;
        exit(1);
    }
    return arr[idx]; // const피연산자의 호출이기에 변경여지x -> 템플릿인자 체로 반환
}

/*소멸자*/
template <typename T>
Accountarray<T>::~Accountarray()
{
   delete []arr; // 프로그램 종료 전 동적할당 삭제
}
  • exception(exception.h - exception.cpp)
  1. 예외처리(exception handling) 클래스들을 관리하는 파일

exception.h

#pragma once

/*예외처리 클래스*/
/*기초클래스*/
class Accountexp // exception 클래스 통합관리 기초클래스
{
  int money;

  public:
// 생성자
  Accountexp(int moeny);
  virtual void Showmessage()=0; // 순수가상 함수 - 순수가상클래스화
};

/*유도클래스 1(입금 시 예외처리 클래스)*/
class Depositexp : public Accountexp
{
  int money;
  
  public:
  Depositexp(int money);
// 함수오버로드 1
  void Showmessage();
};

/*유도클래스 2(출금 시 예외처리 클래스)*/
class Withdrawexp : public Accountexp
{
  int money;

  public:
  Withdrawexp(int money);
// 함수오버로드 3
  void Showmessage();
};

exception.cpp

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

/*기초 예외처리 클래스*/
// 생성자
  Accountexp::Accountexp(int money):money(money){};
// Showmessage
  void Accountexp::Showmessage()
{
  cout << "오류가 발생했습니다!" << endl;
}

/*입금 예외처리 클래스*/
// 생성자
  Depositexp::Depositexp(int money):Accountexp(money){};
// Showmessage
  void Depositexp::Showmessage() // 예외처리 메세지
  {
    cout << "1원 이상의 값을 재입력 하세요" << endl;
  }

/*출금 에외처리 클래스*/
  //생성자
  Withdrawexp::Withdrawexp(int money):Accountexp(money){};
  // Showmessage
  void Withdrawexp::Showmessage() // 예외처리 메세지
  {
    cout << "잔액이 부족합니다. 값을 재입력하세요" << endl;
  }
  • accounthandler(accounthandler.h - accounthandler.cpp)
  1. controller class인 'accounthandler' 클래스를 담고있는 파일
  2. 계좌 생성 ~ 조회까지의 기능을 할 수 있는 함수들을 클래스 내부에 선언, 정의

accounthandler.h

#include "accountarray.h"
#include "account.h"
#pragma once
/*Controller 클래스*/
class Accounthandler
{
private:
// 템플릿 클래스 호출, 객체(배열) acc 생성
	Accountarray<ACCOUNT_PTR> acc;
	int acc_count; // 고객 고유번호 
public:
	// 생성자
	Accounthandler();
	// 기능함수 선언(메뉴, 개설, 입금, 출금, 조회)
	void Menu();
	void Make();
	void Deposit();
	void Withdraw();
	void Show();
};

accounthandler.cpp

#include "accountarray.h"
#include "string.h"
#include "accounthandler.h"
#include <iostream>
#include "normal.h"
#include "high.h"
using namespace std;
#include "account.h"
#include "accountarray.cpp"
#include "exception.h"

/*about AccountHandler class*/
// 생성자
Accounthandler::Accounthandler()
    :acc_count(0) // 고객번호는 0부터 시작(배열 인자 : 0 ~ )
{
}

// 기능함수
// 메뉴함수
void Accounthandler::Menu()
{
    cout << "-------------------------------------------------" << endl;
    cout << "가능 업무" << endl;
    cout << "1. 계좌 생성 " << endl;
    cout << "2. 입금" << endl;
    cout << "3. 출금" << endl;
    cout << "4. 조회" << endl;
    cout << "5. 프로그램 종료" << endl;
}

// 계좌 생성함수
void Accounthandler::Make()
{
    String id; 
    String name;
    int balance;
    int type;
// 계좌 개설 관련 신상정보 입력
    cout << "계좌번호 : "; cin >> id;
    cout << "성명     : "; cin >> name;
    cout << "예치금   : "; cin >> balance;
    cout << "[계좌유형 결정]" << endl;
    cout << "(Normal=1/High=2) : "; cin >> type; 
    double rate;
    char acc_level;
    // 계좌 유형에 따라 다른 유형의 계좌 개설(동적할당)
    switch (type)
    {
    case TYPE::NORMAL: // 노멀타입(1) 결정 시
    {
        cout << "이율   : "; cin >> rate; // 일반이율
// 배열인자 acc[i]의 동적할당(Normal class)
        acc[acc_count++] = new Normal(id, name, balance, rate);
        break;
    }
    case TYPE::HIGH: // 하이타입(2) 결정 시
    {
        cout << "이율   : "; cin >> rate; // 일반이율
        cout << "고객등급 : "; cin >> acc_level; // 고객등급 입력 -> 특별이율 산출
// 배열인자 acc[i]의 동적할당(High class)
        acc[acc_count++] = new High(id, name, balance, rate, acc_level); 
    }
   }
}

// 입금함수 
void Accounthandler::Deposit()
{
    String id;
    int money;
// 계좌번호 입력
    cout << "계좌번호 입력 : "; cin >> id;
    for (int i = 0; i < acc_count; i++) // 계좌번호 일치 조회
    {
/*String클래스의 '=='연산자 오버로드 함수 호출*/
        if (acc[i]->Get_id() == id) // 일치 시
        {
          while(1) // 올바른 값이 입력될 때 까지 금액 입력 요구(무한)
          {
            cout << "금액(만원) : "; cin >> money;
// 예외처리 try ~ throw ~ catch
            try
            {
              if(money <=0)
              {
                throw Depositexp(money); // 예외를 객체(예외객체) 형태로 내보냄
              }
              break; 
/* 예외가 없다면 break;를 실행하여 루프에서 벗어날 것이고 예외가 있다면 break레이블을 뛰어넘어
catch로 넘어오게 됨. 결과적으로 catch에서 에러메세지를 출력할 뿐 반복문에서 벗어나지 못한다.
*/
            }
            catch(Accountexp & dref) 
// throw된 Depositexp객체를 상위클래스인 Accountexp형 매개변수로 받는다.
            {
              dref.Showmessage(); // Showmessage함수에 접근(virtual)
            }
          }
// 정상입금시 -> 입금함수 접근(virtual)
            acc[i]->Proccess_depos(money);
            cout << "정상 입금 되었습니다." << endl;
            break;// for~문 탈출 
        }
// 현재까지 입력된 acc_count 끝까지 중 일치항목이 없을 시
        else if (i == acc_count - 1)
            cout << "계좌번호가 정확히 입력되었는지 확인하세요" << endl;
    }
}

void Accounthandler::Withdraw()
{
// 입금함수의 과정과 동일
    String id;
    int money;
    cout << "계좌번호 입력 : "; cin >> id;
    for (int i = 0; i < acc_count; i++)
    {
        if (acc[i]->Get_id() == id) // 계좌번호 일치 확인
        {
          while(1) // 무한루프
          {
            cout << "금액(만원) : "; cin >> money;
// 예외처리 try ~ throw ~ catch
            try
            {
              if(acc[i] -> Get_balance() < money) // 잔액이 출금액보다 적다면
              {
                throw Withdrawexp(money); // 예외객체 전달
              }
              break;
            }
            catch(Accountexp & wref) // 마찬가지 상위 클래스인 Accountexp를 매개변수형으로
            {
               wref.Showmessage();
            }
          }
            acc[i]->Proccess_withdraw(money);
            cout << "정상 출금 되었습니다." << endl;
        }
        else if (i == acc_count - 1)
            cout << "계좌번호가 정확히 입력되었는지 확인하세요" << endl;
    }
}
// 조회함수
void Accounthandler::Show()
{
    cout << "------------------" << endl;;
    for (int i = 0; i < acc_count; i++)
    {
        cout << acc[i]; 
 /* 앞서 Accountclass 에서 정의한 friend ~형 '<<'연산자 오버로드 함수 호출
(public이기에 당연히 가능)
*/
    }
}

main.cpp

#include "account.h"
#include "accountarray.h"
#include "accounthandler.h"
#include "normal.h"
#include "high.h"
#include "string.h"
#include <iostream>
#include <cstring>
#include "accountarray.cpp"
int main()
{
	Accounthandler AH; // controller 객체 생성
	int choice;
	while (1)
	{
		AH.Menu();
		cout << "거래를 선택하세요 : "; cin >> choice;
		switch (choice)
		{
		case MAKE:
		{
			AH.Make(); // controller객체의 기능함수(생성)호출
			break;
		}
		case DEPOSIT:
		{
			AH.Deposit(); // 입금함수 호출
			break;
		}
		case WITHDRAW:
		{
			AH.Withdraw(); // 출금함수 호출
			break;
		}
		case SHOW:
		{
			AH.Show(); // 조회함수 호출
			break;
		}
		case EXIT:
		{
			cout << "거래를 종료합니다." << endl;
			return 0;
		}
		default:
		{
			cout << "다른 옵션을 선택하세요" << endl;
		}
    }
		while(1) // 올바른 옵션을 선택할 때까지 무한루프
		{
      char further[5];
		  cout << "거래를 계속 하시겠습니까?(yes / no) : "; cin >> further;
		try
    {
      if(strcmp(further,"no")==0) // no입력 시 거래 종료
      {
        cout << "거래를 종료합니다." << endl;
        return 0;
      }
      else if (strcmp(further, "yes")==0) // yes입력 시 계속
      {
        cout << "거래를 계속합니다." << endl;
        break; // yes입력 시 옵션선택 무한루프 탈출
      }
      else // yes도 no도 아닌것이 입력될 시 
      {
        throw 0; // 예외값 전달
      }

    }
     catch(int number) // 예외값 catch
    {
      if(number == 0) // 예외 전달인자가 0일 시
       {
        cout << "다른옵션을 고르십시오" << endl;
 // 에러메세지가 출력될 뿐, 옵션선택 루프에서 벗어나지 못한다.
       }
     }
    }
	}
 return 0;
}

4. 결과

  • 고객 2명을 저장
  • 입금, 출금 기능 확인(이율, 추가이율, 입력 범위 제한)
  • 조회기능 확인

4-1

4-2

4-3

4-4

4-5


5. 막을 내리며

객체의 특성을 배워감과 동시에 나만의 ATM기능 프로젝트를 구축했음에 보람차다. C를 통해 프로그래밍의 걸음마를 때고 C++를 통해 클래스를 알게 되었다. 자 이제 JAVA학습으로 넘어가자!!

모든 작업은 replit 에서 이루어 졌음을 알림.

profile
미생 개발자

0개의 댓글