[C++] 직원 관리 프로그램 만들기
🌈 프로그래밍/C++

[C++] 직원 관리 프로그램 만들기

반응형

 

안녕하세요? 수구리입니다.

 

 

지난 포스팅에서는 C++의 유니폼 초기화에 대해서 알아보았었죠?

 

 

2021.08.20 - [C++] - [C++] 유니폼 초기화란?

 

[C++] 유니폼 초기화란?

안녕하세요? 수구리입니다. 저번 포스팅에서는 C++ 이 객체 지향 언어인데 그 특성에 대해서 알아보았었죠? 2021.08.20 - [C++] - [C++] 객체 지향 언어의 특성에 대하여 [C++] 객체 지향 언어의 특성에 대

tasddc.tistory.com

 

이번 포스팅에서는 이전에 Employee 클래스관련 예제들을 확장해서 직원 관리 콘솔 프로그램을 한번 만들어 보도록 하겠습니다!

 

 

먼저 실행화면부터 보겠습니다.

 

 

첫 실행화면

대충 이런 형태입니다.

 

우선 1번부터 0번까지 사용자가 입력할 수 있도록 대기상태이구요

 

해당 목록을 입력하면 직원을 등록, 해고, 승진 시킬 수 있고

 

모든 직원을 조회하거나 현재 직원만 조회 또는 지금은 일하고 있진 않지만 이전에 일했던 직원들의 목록까지 출력해줍니다.

 

그리고 종료를 하려면 0을 입력하면 프로그램이 종료가 됩니다!

 

 

1번 메뉴 입력 후 이름 입력

예시로 홍길동이라는 사람을 추가한 뒤, 4번을 입력해서 조회해보도록 하겠습니다.

 

 

전체 직원 조회(4번) 입력 후 실행 화면

이렇게 현재 직원 정보가 모두 출력이 되어지는데요~

 

Employee Number와 Salary는 입력하지 않아도 자동으로 입력된 모습입니다.

 

default 값이 존재한다는 말이겠죠?

 

계속 사원이 1명씩 추가되면 1001, 1002, ... 이렇게 증가해 나갈 것입니다!

 

그러면 자세한 구현으로 넘어가보도록 하겠습니다!

 

1.6 첫 C++ 프로그램

  • 이번 파트에서는 앞서 배운 내용들을 토대로 하여 간단한 콘솔 프로그램을 만들어 볼 예정이다.
  • 앞서 했었던 예제 중, 직원 데이터베이스 예제를 확장한 버전이다.

1.6.1 직원 관리 시스템

  • 이 시스템은 아래와 같은 기능을 제공한다.
    • 직원 채용
    • 직원 해고
    • 직원 승진
    • 과거와 현재 직원 모두 조회
    • 현재 직원 모두 조회
    • 과거 직원 모두 조회
  • Employee 클래스는 직원 한 명에 대한 정보를 표현
  • Database 클래스는 모든 직원을 관리함
  • UserInterface 를 통해서 프로그램을 다루도록 함.

1.6.2 Employee 클래스

Employee.h

// Employee.h
#pragma once // 같은 파일을 여러번 불러오지 않도록 함.

#include <string>

// Records라는 네임스페이스에 속하도록 선언
namespace Records {
    // 신입직원의 기본 급여 정의
    const int kDefaultStartingSalary = 30000; // 상수는 앞에 k를 붙이는 관례

    class Employee
    {
    public:
        // default 생성자 & 성, 이름을 받는 생성자
        Employee() = default;
        Employee(const std::string& firstName, const std::string& lastName);

        // 정수 type의 매개변수를 받음. 기본값이 정해져 있어서 매개변수가 없다면 default값으로
        void promote(int raiseAmount = 1000);
        void demote(int demeritAmount = 1000);
        void hire(); // 직원 고용
        void fire(); // 직원 해고.
        void display() const;// 직원 정보 콘솔 출력

        // getter & setter
        void setFirstName(const std::string& firstName);
        const std::string& getFirstName() const;

        void setLastName(const std::string& lastName);
        const std::string& getLastName() const;

        void setEmployeeNumber(int employeeNumber);
        int getEmployeeNumber() const;

        void setSalary(int newSalary);
        int getSalary() const;

        bool isHired() const;


    // 다른 코드에서 수정하지 못하도록 private로 데이터 맴버 선언
    private:
        std::string mFirstName;
        std::string mLastName;
        int mEmployeeNumber = -1;
        int mSalary = kDefaultStartingSalary;
        bool mHired = false;
    };
}

Employee.cpp

  • 생성자는 성, 이름을 인수로 받아 각각의 값을 해당 데이터 맴버에 설정하기만 한다.
// Employee.cpp

#include <iostream>
#include "Employee.h"

using namespace std;

namespace Records {
    // 성, 이름을 받아 각각의 값을 해당 데이터 맴버에 설정.
    Employee::Employee(const std::string& firstName, const std::string& lastName)
        : mFirstName(firstName)
        , mLastName(lastName)
    {
    }

    // 인수로 전달된 값을 의미에 맞게 바꿔서 setSalary 메서드로 전달.
    void Employee::promote(int raiseAmount)
    {
        setSalary(getSalary() + raiseAmount);
    }

    void Employee::demote(int demeritAmount)
    {
        setSalary(getSalary() - demeritAmount);
    }

    // mHired 변수 설정하는 고용, 해고 메서드
    void Employee::hire()
    {
        mHired = true;
    }

    void Employee::fire()
    {
        mHired = false;
    }

    // 현재 직원에 대한 정보를 콘솔 출력.
    void Employee::display() const
    {
        cout << "Employee: " << getLastName() << ", " << getFirstName() << endl;
        cout << "-------------------------" << endl;
        cout << (isHired() ? "Current Employee" : "Former Employee") << endl;
        cout << "Employee Number: " << getEmployeeNumber() << endl;
        cout << "Salary: $" << getSalary() << endl;
        cout << endl;
    }

    // getter & setter
    void Employee::setFirstName(const string& firstName)
    {
        mFirstName = firstName;
    }

    const string& Employee::getFirstName() const
    {
        return mFirstName;
    }

    void Employee::setLastName(const string& lastName)
    {
        mLastName = lastName;
    }

    const string& Employee::getLastName() const
    {
        return mLastName;
    }

    void Employee::setEmployeeNumber(int employeeNumber)
    {
        mEmployeeNumber = employeeNumber;
    }

    int Employee::getEmployeeNumber() const
    {
        return mEmployeeNumber;
    }

    void Employee::setSalary(int salary)
    {
        mSalary = salary;
    }

    int Employee::getSalary() const
    {
        return mSalary;
    }

    bool Employee::isHired() const
    {
        return mHired;
    }

}

EmployeeTest.cpp

  • 위의 작성된 코드를 간단하게 아래의 테스트 코드를 가지고 테스트 해보자.
// EmployeeTest.cpp

#include <iostream>
#include "Employee.h"

using namespace std;
using namespace Records;

int main()
{
    cout << "Testing the Employee class." << endl;

    Employee emp;
    emp.setFirstName("John");
    emp.setLastName("Doe");
    emp.setEmployeeNumber(71);
    emp.setSalary(50000);
    emp.promote();
    emp.promote(50);
    emp.hire();
    emp.display();

    return 0;
}

1.6.3 Database 클래스

  • Database 클래스는 표준 라이브러리에서 제공하는 std::Vector 클래스를 이용하여 Employee 객체를 저장한다.

Database.h

  • 신입 직원에 대한 직원번호는 DB에서 자동으로 할당.
  • 직원 번호의 시작값을 상수로 설정
// Database.h
// std::vector 클래스를 이용하여 Employee 객체 저장
#pragma once

#include <iostream>
#include <vector>
#include "Employee.h"

namespace Records {
    // 신입 직원에 대한 직원번호는 DB 내부에서 자동 할당을 위해 시작값을 상수로 정의
    const int kFirstEmployeeNumber = 1000;

    class Database
    {
    public:
        // 성, 이름으로 신입 직원 추가
        Employee& addEmployee(const std::string& firstName,
                              const std::string& lastName);
        // 직원번호로 직원 조회
        Employee& getEmployee(int employeeNumber);
        // 성, 이름으로 직원 조회
        Employee& getEmployee(const std::string& firstName,
                              const std::string& lastName);

        // 모든 직원 정보를 출력
        void displayAll() const;
        // 현재 재직중인 직원 정보 출력
        void displayCurrent() const;
        // 퇴사한 직원 정보 출력
        void displayFormer() const;

    private:
        // mEmployees는 Employee 객체를 가지고 있는 배열
        std::vector<Employee> mEmployees;
        // 신입직원에 할당된 직원 번호를 기록하며 상수로 초기화
        int mNextEmployeeNumber = kFirstEmployeeNumber;
    };
}

Database.cpp

// Database.cpp

#include <iostream>
#include <stdexcept>
#include "Database.h"

using namespace std;

namespace Records {
    // 새로운 Employee 객체 생성 후 vector에 추가
    Employee& Database::addEmployee(const string& firstName, const string& lastName)
    {
        Employee theEmployee(firstName, lastName);
        // 다음 직원이 새로운 번호를 받기위해 1 증가
        theEmployee.setEmployeeNumber(mNextEmployeeNumber++);
        theEmployee.hire();
        mEmployees.push_back(theEmployee);

        return mEmployees[mEmployees.size() - 1];
    }

    // 범위기반 for문을 사용하여 mEmployees에 있는 모든 직원을 돌면서
    // 전달된 직원번호와 같은 직원을 찾는다.
    Employee& Database::getEmployee(int employeeNumber)
    {
        for (auto& employee : mEmployees) {
            if (employee.getEmployeeNumber() == employeeNumber) {
                return employee;
            }
        }
        // 없다면 예외 발생
        throw logic_error("No employee found.");
    }

    // 직원의 성, 이름을 받아와 해당 직원이 있는지 조회
    Employee& Database::getEmployee(const string& firstName, const string& lastName)
    {
        for (auto& employee : mEmployees) {
            if (employee.getFirstName() == firstName &&
                employee.getLastName() == lastName) {
                    return employee;
            }
        }
        // 없다면 예외 발생
        throw logic_error("No employee found.");
    }

    // 모든 직원에 대하여 Loop를 돌면서 일정 조건에 만족하는
    // 직원의 정보를 콘솔에 출력
    void Database::displayAll() const
    {
        for (const auto& employee : mEmployees) {
            employee.display();
        }
    }

    // 현재 재직중인 모든 직원 정보를 출력한다.
    void Database::displayCurrent() const
    {
        for (const auto& employee : mEmployees) {
            if (employee.isHired())
                employee.display();
        }
    }

    // 과거에 다녔었던 직원을 조회한다.
    void Database::displayFormer() const
    {
        for (const auto& employee : mEmployees) {
            if (!employee.isHired())
                employee.display();
        }
    }

}

DatabaseTest.cpp

  • 마찬가지로 위의 Database 클래스가 잘 동작하는지 확인해보자.
// DatabaseTest.cpp

// 정의한 Database의 기본 기능을 정의하는 테스트 코드
#include <iostream>
#include "Database.h"

using namespace std;
using namespace Records;

int main()
{
    Database myDB;

    Employee& emp1 = myDB.addEmployee("Greg", "Wallis");
    emp1.fire();

    Employee& emp2 = myDB.addEmployee("Marc", "White");
    emp2.setSalary(100000);

    Employee& emp3 = myDB.addEmployee("John", "Doe");
    emp3.setSalary(10000);
    emp3.promote();

    cout << "all employees: " << endl << endl;
    myDB.displayAll();

    cout << endl << "current employees: " << endl << endl;
    myDB.displayCurrent();

    cout << endl << "former employees: " << endl << endl;
    myDB.displayFormer();

    return 0;
}

1.6.4 사용자 인터페이스

  • 앞서 말했듯이 콘솔 응용프로그램이므로 메뉴 기반으로 사용자가 직원 데이터베이스에 쉽게 접근할 수 있도록 한다.
#include <iostream>
#include <stdexcept>
#include <exception>
#include "Database.h"

using namespace std;
using namespace Records;

int displayMenu();
void doHire(Database& db);
void doFire(Database& db);
void doPromote(Database& db);
void doDemote(Database& db);

int main()
{
    Database employeeDB;

    bool done = false;
    while (!done) {
        int selection = displayMenu();
        switch (selection) {
        case 0:
            done = true;
            break;
        case 1:
            doHire(employeeDB);
            break;
        case 2:
            doFire(employeeDB);
            break;
        case 3:
            doPromote(employeeDB);
            break;
        case 4:
            employeeDB.displayAll();
            break;
        case 5:
            employeeDB.displayCurrent();
            break;
        case 6:
            employeeDB.displayFormer();
            break;
        default:
            cerr << "Unknown command." << endl;
            break;
        }
    }

    return 0;
}

int displayMenu()
{
    // 화면에 메뉴를 출력 -> 사용자의 입력을 받음.
    // 숫자를 요청하면 숫자를 입력한다고 가정.
    // 잘못된 입력이 들어오면 예외 처리
    int selection;

    cout << endl;
    cout << "Employee Database" << endl;
    cout << "-----------------" << endl;
    cout << "1) Hire a new employee" << endl;
    cout << "2) Fire an employee" << endl;
    cout << "3) Promote an employee" << endl;
    cout << "4) List all employees" << endl;
    cout << "5) List all current employees" << endl;
    cout << "6) List all former employees" << endl;
    cout << "0) Quit" << endl;
    cout << endl;
    cout << "---> ";

    cin >> selection;

    return selection;
}

void doHire(Database& db)
{
    // 신입직원의 이름을 입력받아 DB에 그 직원에 대한 정보 추가요청
    string firstName;
    string lastName;

    cout << "First name? ";
    cin >> firstName;
    cout << "Last name? ";
    cin >> lastName;

    db.addEmployee(firstName, lastName);
}

void doFire(Database& db)
{
    int employeeNumber;

    cout << "Employee number? ";
    cin >> employeeNumber;

    try {
        Employee& emp = db.getEmployee(employeeNumber);
        emp.fire();
        cout << "Employee " << employeeNumber << " terminated." << endl;
    }
    catch (const std::logic_error& exception) {
        cerr << "Unable to terminate employee: " << exception.what() << endl;
    }
}

void doPromote(Database& db)
{
    int employeeNumber;
    int raiseAmount;

    cout << "Employee number? ";
    cin >> employeeNumber;
    cout << "How much of a raise? ";
    cin >> raiseAmount;

    try {
        Employee& emp = db.getEmployee(employeeNumber);
        emp.promote(raiseAmount);
    }
    catch (const std::logic_error& exception) {
        cerr << "Unable to promote employee: " << exception.what() << endl;
    }
}

void doDemote(Database& db) {
    int employeeNumber;
    int demeritAmount;

    cout << "Employee number? ";
    cin >> employeeNumber;
    cout << "How much of a demerit? ";
    cin >> demeritAmount;

    try
    {
        Employee& emp = db.getEmployee(employeeNumber);
        emp.demote(demeritAmount);
    }
    catch (const std::logic_error& exception)
    {
        cerr << "Unable to demote employee. " << exception.what() << endl;

    }

}
반응형

'🌈 프로그래밍 > C++' 카테고리의 다른 글

[C++] 동적 스트링 Part 2  (0) 2021.08.25
[C++] 동적 스트링 Part 1  (2) 2021.08.24
[C++] 유니폼 초기화란?  (2) 2021.08.20
[C++] 객체 지향 언어의 특성에 대하여  (0) 2021.08.20
[C++] 타입 추론에 대하여  (0) 2021.08.20