[C++] 심화프로그래밍 Week3

Yoons·2022년 9월 23일
0
post-thumbnail

실습 보고서 작성 요령


문제분석

  • 결과 화면을 캡쳐 하여 첨부, 해당 결과가 도출된 이유와 타당성 분석

프로그램 설계 및 알고리즘

  • 해결 방법에 따라 프로그램 설계 및 알고리즘 등 기술
  • e.g.) 문제 해결 과정 및 핵심 알고리즘 기술

소스코드 및 주석

  • 소스코드와 그에 해당하는 주석 첨부
  • 각각의 함수가 수행하는 작업, 매개변수, 반환 값 등을 명시
  • 소스코드 전체 첨부(소스코드 화면 캡처X, 소스코드는 복사/붙여넣기로 첨부)

결과 및 결과 분석

  • 결과 화면을 캡쳐 하여 첨부, 해당 결과가 도출된 이유와 타당성 분석

소감

  • 실습 문제를 통해 습득할 수 있었던 지식, 느낀 점 등을 기술

Prob 1


문제분석

실행 결과처럼 올바르게 나오도록 빈칸을 채우는 과제이다. 사용자에게 매개변수의 형식으로 w와 h를 입력 받고, width와 height의 default 값을 정해서 w와 h가 각각 그 값보다 클 경우 입력 받은 값으로, 그렇지 않다면 default 값으로 저장한다. main 함수에서는 멤버함수를 호출하고 앞의 과정을 거쳐 최종정인 결과를 출력하는 코드를 작성한다. 이 문항을 처음 봤을 때 두 가지 의문이 들었다. 첫 번째는 YoutubeSize라는 멤버함수가 2가지가 있는데, 왜 나눠서 사용하는지 몰랐다. 두 번째 의문은 ResizeWindow 멤버함수에서 바로 변수를 받아도 됐을텐데, 왜 GetWidth(), GetHeight()를 따로 만든 것인지 잘 이해가 가지 않는다.

프로그램 설계 및 알고리즘

  1. YoutubeSize class를 선언한다.
  2. class 내부에 private 멤버 변수와 public 멤버 함수를 선언한다.
  3. class에서 선언한 멤버 함수를 구현한다.
  4. (YoutubeSize()) YoutubeSize에 매개변수가 없을 때 default 값으로 초기화 하는 함수 구현
  5. (YoutubeSize(w,h)) YoutubeSize에 매개변수가 있을 때 ResizeWindow(w,h)를 실행하는 함수 구현
  6. (GetWidth(), GetHeight()) int형 값을 반환하는 GetWidth(), GetHeight() 함수 구현
  7. (ResizeWindow(w,h)) 입력 받은 w, h 값에 따라 조건식을 통해 width, height 값을 저장하는 ResizeWindow(w,h) 함수 구현
  8. (main) mainWindow 객체를 선언한다.
  9. (main) 매개변수와 함께 ResizeWindow(w,h)를 실행한다.
  10. (main) ResizeWindow(w,h)는 반환하는 값이 없으므로, cout을 이용해 GetWidth()와 GetHeight()를 출력하여 결과를 나타낸다.

소스코드 및 주석

#include <iostream>
using namespace std;

class YoutubeSize{ // Youtube class 선언
private: // private 멤버 변수 선언
    int w; // 입력 width
    int h; // 입력 height
    int width; // 최종 width
    int height; // 최종 height
public: // public 멤버 함수 선언
    YoutubeSize();
    YoutubeSize(int, int);
    int GetWidth();
    int GetHeight();
    void ResizeWindow(int, int);
};

YoutubeSize::YoutubeSize() : width(800), height(600) { } // 매개변수가 없는 경우 default
YoutubeSize::YoutubeSize(int w, int h) : YoutubeSize(){ // 매개변수가 있는 경우 ResizeWindow 실행
    ResizeWindow(w, h);
}

int YoutubeSize::GetWidth() {
    return width; // width 값 return
}

int YoutubeSize::GetHeight() {
    return height; // height 값 return
}

void YoutubeSize::ResizeWindow(int w, int h) {
    if (w > 800) width = w; // 입력 받은 width 값이 800보다 크면 입력 받은 값 사용
    else width = 800; // 아니면 default

    if (h > 600) height = h; // 입력 받은 height 값이 600보다 크면 입력 받은 값 사용
    else height = 600; // 아니면 default
}

int main(){ // main function
    YoutubeSize mainwindow;  // 객체 선언

    mainwindow.ResizeWindow(1080, 102); // 멤버 함수 실행
    cout << mainwindow.GetWidth() << " X " << mainwindow.GetHeight() << endl; // 반환 결과 출력

    mainwindow.ResizeWindow(437, 605);
    cout << mainwindow.GetWidth() << " X " << mainwindow.GetHeight() << endl; 

    mainwindow.ResizeWindow(2350, 2050);
    cout << mainwindow.GetWidth() << " X " << mainwindow.GetHeight() << endl; 

    return 0;
}

결과 및 결과 분석


width는 800, height는 600으로 입력 받은 값(매개변수 값)이 각각 이 보다 작을 경우 default값을 출력하고 그것보다 크면 그 값을 그대로 이용한다. 첫 번째 출력의 경우 각각 1080, 102를 입력 받았다. width는 문제가 안되지만 height 값이 600보다 작으므로 입력 받은 102가 아닌 default값을 출력한다. 두 번째 출력의 경우 각각 437, 605를 받았다. 첫 번째 출력과는 반대로 height는 문제가 없지만 width가 800보다 작으므로 default값을 출력한다. 세 번째 출력의 경우 각각 2350, 2050으로 문제가 되지 않아 입력 받은 그대로 출력되는 것을 볼 수 있다.

소감

지금까지의 과제 문제 중 가장 시간이 많이 걸린 문제인 것 같다. 그 이유로는 우선 첫 번째로 '위임생성자'라는 모르는 개념이 있었다. 위임생성자 개념은 중복된 함수를 간소화하기 위해 사용된다. 문제분석 단계에서 YoutubeSize 함수가 왜 두 개나 있는지 모르겠다고 했는데, 그 이유는 변수값 초기화와 ResizeWindow 함수를 모두 실행하기 위해 나눈 것으로 보이며 이 단계에서 위임생성자가 사용된다. 두 번째로 ResizeWindow 함수의 반환형이 void여서 어떻게 출력해야할지 몰랐기 때문이다. GetWidth와 GetHeigt 함수가 모두 int형을 반환하므로 이 함수들을 사용해야한다는 것은 예상했지만, 출력문에 함수를 사용하는 아이디어를 빨리 생각하지 못해서 시간이 걸렸다. 세 번째 이유로는 컴퓨터가 코드를 읽는 순서를 잘 이해하지 못한 것이다. 컴퓨터는 위에서 아래로, 왼쪽에서 오른쪽으로 코드를 읽는데, main 함수를 먼저 읽고 그 이후에 main에서 호출한 정의 함수를 읽는다고 생각해 문제를 이해하는데 시간이 걸렸다. 이 문제를 해결하는 과정에서 컴파일 오류가 나기도 했다. 위임생성자는 c++11버전에서만 컴파일 되는데, 버전이 달라서 생긴 문제였다. 이는 버전을 변경하여 간단히 해결했다. 처음보는 오류를 봤을 때는 당황하기도 한다. 이번 문제는 시간이 오래 걸린만큼 기억에 남고 배운 것이 많은 문제였다. 이 문제에서 사용된 개념들에 대해 조금 더 공부해야겠다는 생각이 들었다.


Prob 2


문제분석

해당 과제는 치킨집 수익 및 판매자 잔액을 출력하는 프로그램이다. 매일 튀킬 수 있는 치킨은 60마리, 1마리의 가격은 18,000이라고 가정한다. class를 이용해야하므로 ChickenSeller라는 class를 생성한다. 접근지정자도 사용해야하므로 private, public을 적절하게 사용해서 멤버 변수와 멤버 함수를 생성한다. 멤버 변수에서는 구매할 치킨 개수, 남은 치킨, 판매 수익, 현재 잔액을 선언 및 초기화한다. 멤버 함수에서는 구매할 치킨 개수를 입력 받아 판매자의 남은 치킨, 판매 수익과 구매자의 현재 잔액을 계산하고 출력하도록 하면 될 것이다.

(추가기능 고안) 이 프로그램이 현실적으로 사용 가능 하려면 치킨을 추가적으로 구매할 수 있어야하므로 조건문과 반복문을 이용하여 계속 구매한다면 이전의 과정을 다시 진행하고, 아니라면 반복문을 빠져나가는 기능을 추가적으로 구현한다.

프로그램 설계 및 알고리즘

  1. 문제에서 요구한 대로 Chicken 클래스를 선언한다.
  2. 클래스 내부에 접근지정자를 적절히 이용하여 멤버 변수를 선언 및 초기화하고 멤버 함수는 함수의 역할에 맞춰 클래스 내부에 구현한다.
  3. (Calculate function) cin을 이용해 구매할 치킨 개수를 입력 받는다.
  4. (Calculate function) 구매할 치킨 개수가 60마리를 초과한다면 판매할 수 없으므로 현재 남은 치킨 개수와 함께 에러메세지를 출력하고 60마리 이하라면 남은 치킨 개수, 판매 수익을 계산한다.
  5. (Calculate function) 구매할 치킨 개수의 총 가격이 구매자의 잔액을 초과하면 구매가 진행되면 안되므로, 초과하면 모자란 금액과 함께 에러메세지를 출력하고 아니라면 구매를 진행하고 결과를 출력한다. 이때 이게 몇 번째 주문인지 확인할 수 있도록 변수 i를 선언하고 증감연산자를 사용하여 저장 및 출력한다.
  6. (main function) 클래스 객체와 변수를 선언한다.
  7. (main function) 구매를 더 진행할지, 종료할지 입력 받고 while문에서 무한 loop를 진행한다.
  8. (main function) 입력 받은 문자열이 buy인 경우 클래스 내부의 멤버함수를 호출하고, exit인 경우 시스템이 종료된다는 메세지와 함께 break로 무한 loop를 빠져나간다.

소스코드 및 주석

#include <iostream>
#include <string>
using namespace std;

class ChickenSeller { // ChickenSeller class 선언
private: // private 멤버 변수 선언 및 초기화
    int sRemain = 60; // 남은 치킨
    int sRevenue = 0; // 판매 수익
    int bRemain = 80000; // 현재 잔액
    int bChicken = 0; // 구매 개수
    int i = 0; // 주문 번호
public: // public 멤버 함수
    int Calculate(){ // Calculate 함수 선언
        cout << "How many chickens are you going to buy? : ";
        cin >> bChicken; // 구매 개수 입력
        if (bChicken <= sRemain){ // 구매 개수 <= 남은 치킨 : 구매 가능
            sRemain = sRemain - bChicken; // main 함수의 반복문이 끝날 때까지 남은 치킨을 누적해서 계산한다
            sRevenue = sRevenue + bChicken*18000; // main 함수의 반복문이 끝날 때까지 판매 수익을 누적해서 계산한다

            if (bChicken*18000 <= bRemain){ // 구매 개수*마리 당 가격 <= 현재 잔액 : 구매 가능
                bRemain = bRemain - (bChicken*18000); // main 함수의 반복문이 끝날 때까지 현재 잔액을 누적해서 계산한다
                i++; // 주문 번호 증가

                cout << endl << "#" << i << endl; // 결과 출력
                cout << "+++++++++++++++++++++++" << endl;
                cout << "판매자 현항" << endl;
                cout << "남은 치킨 : " << sRemain << endl;
                cout << "판매 수익 : " << sRevenue << endl;
                cout << "-----------------------" << endl;
                cout << "구매자 현황" << endl;
                cout << "현재 잔액 : " << bRemain << endl;
                cout << "구매 개수 : " << bChicken << endl;
                cout << "+++++++++++++++++++++++" << endl << endl;
            }
            else { // 구매 개수*마리 당 가격 > 현재 잔액 : 구매 불가능
                cout << "ERROR : " << bChicken*18000-bRemain << " is not enough." << endl;
            }
        }
        else{ // 구매 개수 > 남은 치킨 : 구매 불가능
            cout << "ERROR : There are only " << sRemain << " chickens left." << endl;
        }
    };
};

int main(){ // main 함수 선언
    ChickenSeller maincalcul; // 객체 선언
    string type; // 변수 선언

    while (true){ // 무한 loop
        cout << "Select the type(buy or exit) : ";
        cin >> type; // type(buy or exit) 입력
        if (type == "buy"){ // buy 입력
            maincalcul.Calculate(); // 멤버 함수 실행
        }
        else { // exit(buy를 제외한 모든 값) 입력
        cout << "Exit calculate system." << endl;
        break; // 무한 loop를 빠져나감
        }
    }
}

결과 및 결과 분석


구매 현황을 저장 및 출력한다. 한 마리를 18,000원으로 잡았을 때 금액과 개수, 이게 몇 번째 주문인지 잘 출력되는 것을 확인할 수 있다. 또한 exit을 입력했을 때 시스템이 종료되는 것까지 확인할 수 있다.

구매할 치킨의 총 가격이 구매자의 잔액을 초과할 경우 모자란 가격과 함께 에러메세지를 출력하고 다시 구매 초기상태로 돌아는 모습을 볼 수 있다.

소감

처음에 sRevenue를 0으로 초기화하지 않은 상태로 프로그램을 실행했는데 정상적인 답보다 1이 더해진 값이 나오는 것을 확인했다. 문제를 찾지 못해서 sRevenue에 1을 뺄까 생각도 했지만 그럴 필요 없이 0으로 초기화하지 않아서 생기는 문제였다. 문제분석에서도 얘기했듯이 프로그램을 반복적으로 사용할 수 있도록 반복문과 조건문을 더 활용했다. 문제의 요구대로 하는 것도 매우 중요하지만, 원하는 목표대로 코드를 변경하고 추가하는 것 또한 실력 향상과 코드를 보는 안목에 굉장히 큰 도움이 될 것이라고 생각한다. 이번 문항처럼 계산기, 자판기와 같은 프로그램을 만드는 것은 다른 문제보다 더 흥미를 느끼는 것 같다. 앞으로 해야할 일이 있다면 효율적인 업무를 위해 문제를 해결할 코드를 직접 작성해서 해결해보는 것도 좋은 경험이 될 것이라고 생각한다.


Reference

profile
모든 글은 저의 눈물을 머금으며 작성한 글이니..재밌게 봐주세요 :) 깃헙 맞팔@

0개의 댓글