[심화프로그래밍] Week5

Yoons·2022년 10월 10일
0
post-thumbnail

실습 보고서 작성 요령


문제분석

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

프로그램 설계 및 알고리즘

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

소스코드 및 주석

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

결과 및 결과 분석

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

소감

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

Prob 1

문제분석

원하는만큼의 숫자를 입력 받고 그 숫자들을 동적할당을 통해 배열에 저장하여 출력하는 프로그램이다. 따로 클래스를 만들 필요가 없어 main함수만 작성하면 된다. 몇 개의 숫자를 입력 받을지 cin을 통해 입력 받고, 그 크기만큼의 배열을 동적 할당한다. 그 후에는 반복문을 돌면서 정수를 입력 받고, 출력하면 된다. 처리조건에 조건문을 작성하라고 되어있는데, 어떻게 작성해야할지는 감이 잡히지 않는다.

프로그램 설계 및 알고리즘

  1. len 변수를 선언하고 cin을 사용하여 몇 개의 숫자를 입력할지 입력한다.
  2. 포인터형 변수 arr을 선언하고 사이즈가 len인 배열을 동적할당한다.
  3. len만큼 반복문을 돌면서 배열에 숫자를 입력한다.
  4. len만큼 반복문을 돌면서 배열에 저장된 숫자를 출력한다. 이때 숫자와 숫자 사이에 ', '를 출력하고 마지막 숫자일 경우 출력하지 않는 조건문을 작성한다.
  5. 동적할당을 해제한다.

소스코드 및 주석

#include <iostream>
using namespace std;

int main(){
    int len; // 입력 변수 선언

    cout << "정수를 얼마나 입력 받을까요? ";
    cin >> len; // 변수값 입력
    cout << endl;

    int* arr = new int[len]; // len만큼 동적 할당

    for (int i = 0; i < len; i++){ // len만큼 반복
        cout << "정수 입력 : "; 
        cin >> arr[i]; // 각 칸에 값 입력 후 저장
    }
    
    cout << endl << "정수 출력 : ";
    for (int i = 0; i < len; i++){ // len만큼 반복
        cout << arr[i]; // 각 칸에 저장된 값 출력
        if (i != len-1){ // 가장 마지막 숫자가 아니라면
            cout << ", "; // ', '를 입력함
        }
    }
    cout << endl;

    delete[] arr; // 해제
}

결과 및 결과 분석


입력할 정수의 개수를 입력했을 때 해당 숫자만큼 반복문이 잘 작동함을 확인할 수 있다. cin을 통해 값을 입력 받고 그 값들을 배열에 저장하여 반복문을 통해 출력한다. 출력 반복문 안에 작성한 조건문 또한 잘 작동함을 확인할 수 있다.

소감

main 함수만 작성하면 되는 과제였어서 크게 어렵게 느껴지지는 않았다. 하지만 동적할당이라는 것 자체가 익숙하지 않아서 결과가 제대로 나오는 것은 확인했지만 의미를 깊게 파악하지는 못한 것 같아 공부를 조금 해야할 것 같다. 조건문을 사용하라고 나와있지만 딱히 사용해야할 부분이 보이지 않아 최종적으로 숫자들을 출력할 때 마지막 숫자를 제외하고 숫자와 숫자 사이에 ', '를 출력하는 조건문을 작성했다.


Prob 2

문제분석

객체를 특정 이름, 학번, 출결 정보로 초기화하여 자동으로 출석 처리를 하는 프로그램이다. 초기화 정보를 저장할 객체 포인터를 동적할당을 통해 선언한다. 생성자를 사용하여 초기화 된 이름으로 "000 출석 체크를 시작합니다."라는 메세지를 출력한다. 다음으로 초기화 된 이름, 학번, 출결 정보를 순서대로 출력한다. 이때 객체 포인터를 이용하기 때문에 반복문이 아닌 각각의 객체에 대해 포인터 연산자(->)를 사용한다. 모두 출력이 됐다면 소멸자를 사용하여 "000 출석 체크가 완료되었습니다."라는 메세지를 출력하고 각각의 객체에 대해 동적할당을 해제한다.

프로그램 설계 및 알고리즘

  1. (Lecture class) Lecture 클래스를 선언하고 private, public 접근 지정자를 사용하여 멤버 변수 및 멤버 함수를 선언한다. 함수 내용은 외부에서 구현할 것이므로 클래스 내부에서는 선언만 한다. public으로는 생성자 2개(매개변수 유뮤)와 소멸자 1개, 출력함수 1개를 선언했다.
  2. (Lecture::Lecuture()) 매개변수가 없는 생성자이다. 이름, 학번, 출결정보를 모두 'none'으로 초기화한다.
  3. (Lecture::Lecture(string inName, string inNumber, string inCheck)) 매개변수가 있는 생성자이다. 이름, 학번, 출결정보를 main함수에서 지정한 값들로 초기화하고 초기화 시 입력된 이름으로 '000 출석 체크를 시작합니다.'라는 메세지를 출력한다.
  4. (void Lecture::printAll()) 초기화 된 이름, 학번, 출결 정보를 출력하는 함수이다.
  5. (main()) 3명의 학생 정보를 입출력 할 것이기 때문에 3개의 객체 포인터를 선언하고 각각 초기화하여 동적할당한다.
  6. (main()) 각 객체 포인터를 printAll()함수에 접근하여 정보를 출력한다.
  7. (main()) delete를 이용해 동적할당을 해제한다. 동적할당이 해제되면 소멸자가 작동하면서 '000 출석 체크가 완료되었습니다.'라는 메세지가 출력된다.

소스코드 및 주석

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

class Lecture { // Lecture 클래스 생성
private: // private 접근지정자 지정
    string name; // 이름 변수
    string number; // 학번 변수
    string check; // 출결 변수
public: // public 접근지정자 지정
    Lecture(); // 매개변수가 없는 생성자
    Lecture(string inName, string inNumber, string inCheck); // 매개변수가 있는 생성자
    ~Lecture(); // 소멸자
    void printAll(); // 출결 사항 출력 함수
};

Lecture::Lecture(){ // 매개변수가 없는 생성자 내용
    name = "none";
    number = "none";
    check = "none";
}

Lecture::Lecture(string inName, string inNumber, string inCheck){ // 매개변수가 있는 생성자 내용
    name = inName; // 입력 이름 저장
    number = inNumber; // 입력 학번 저장
    check = inCheck; // 입력 출결 사항 저장
    cout << name << " 출석 체크를 시작합니다." << endl;
}

Lecture::~Lecture(){ // 소멸자 내용
    cout << name << " 출석 체크가 완료되었습니다." << endl;
}

void Lecture::printAll(){ // 출결 사항 출력 함수 내용
    cout << "이름 : " << name << endl; // 이름 출력
    cout << "학번 : " << number << endl; // 학번 출력
    cout << "출결(출석, 지각, 결석) : " << check << endl; // 출결 정보 출력
}

int main(){ 
    string inName; // 이름 입력 변수
    string inNumber; // 학번 입력 변수
    string inCheck; // 출결 정보 입력 변수
    
    Lecture *student1 = new Lecture("유재석", "2022765435", "출석"); // student1 동적할당 및 초기화
    Lecture *student2 = new Lecture("박명수", "2022786542", "무단결석"); // student2 동적할당 및 초기화
    Lecture *student3 = new Lecture("노홍철", "2022098165", "유고결석"); // student3 동적할당 및 초기화

    cout << endl;
    cout << "---------------------------------------"<< endl;
    student1 -> printAll(); // student1, printAll() 출력함수 접근
    student2 -> printAll();// student2, printAll() 출력함수 접근
    student3 -> printAll();// student3, printAll() 출력함수 접근
    cout << "---------------------------------------"<< endl;
    cout << endl;

    delete student1; // student1 동적할당 해제
    delete student2; // student2 동적할당 해제
    delete student3; // student3 동적할당 해제
}

결과 및 결과 분석


코드를 실행했을 때 생성자에 의해 초기화 된 이름으로 출석 체크 시작메세지가 출력되는 것을 확인할 수 있다. 이후 이름, 학번, 출결 정보가 출력되고 이후에 각 객체 포인터에 대한 동적할당 해제 및 소멸자가 작동하면서 출석 체크 완료 메세지가 출력된다.

소감

이 문제를 해결하는 데 많은 시간이 걸렸다. 처음에 이름, 학번, 출결에 대한 정보를 모두 cin을 통해 입력해야하는 줄 알았다. 실행결과를 보면 맨 처음 출력은 생성자에 의한 출력인데, 저렇게 되기 위해서는 초기화를 통해서 출력해야지만 된다는 것을 알았다. 처음에 이러한 착각을 하다보니 3명의 학생 정보에 대해 반복문을 사용해야하는 줄 알았지만, 각각을 객체로 선언하여 초기화하니 잘 출력되는 것을 확인할 수 있었다. 마지막으로 소멸자 내용에 대한 출력도 잘 확인되었다. 소멸자는 생성 순서에 역순으로 진행되는데, 정방향으로 출력되는 이유는 아마 반복문이 아닌 객체를 각각 생성했기 때문일 것이다. 또 소멸자 실행 시점이 main함수가 끝날 때인지, 아니면 delete로 동적할당이 해제될 때인지 잘 몰랐는데, 찾아본 결과 동적할당 했을 경우 동적할당이 해제되면서 소멸자가 작동한다는 것을 알았다. 아직 객체 포인터와 관련된 개념에 대해 익숙하지 않아서 어떻게 써야할지 잘 모르고 망설이는 것 같다. 조금 더 깊게 공부해서 자유자재로 사용할 수 있었으면 좋겠다.


Prob 3

문제분석

객체 포인터, 객체 배열을 사용하여 책에 대한 정보(이름, 가격)을 입출력하는 예제이다. 책 번호에 대한 정보도 출력하기 때문에 책 정보를 입력하기 전 사용자에게 몇 권을 입력할 것인지 물어보고 cin을 통해 책 권수를 입력 받은 후 그 만큼 반복문을 통해 입력 받으려고 한다. 포인터형 객체 배열을 선언하고 책 번호, 이름, 가격에 대한 정보를 담은 정보와 함께 동적할당한다. 그 후 포인터 연산자를 통해 printAll()에 접근하여 책 정보를 순서대로 출력하면 된다.

프로그램 설계 및 알고리즘

  1. (Books class) Books 클래스를 선언하고 private, public 접근 지정자를 이용하여 멤버 변수, 멤버 함수를 선언한다. public으로는 생성자 2개 (매개변수 유무), 출력함수 1개를 선언했다. 클래스 외부에서 구현할 것이므로 선언만 진행한다.
  2. (Books::Books()) 매개변수가 없는 생성자이다. 책 번호, 가격을 0으로 설정하고 책 이름도 'none'으로 초기화한다.
  3. (Books::Books(int i, string inputName, int inputPrice)) 매개변수가 있는 생성자이다. 생성자를 호출한 main함수로부터 i, inputName, inputPrice에 대한 정보를 private 멤버 변수인 tag, name, price에 저장한다.
  4. (void Books::printAll()) 책 정보를 출력하는 출력함수이다.
  5. (main()) 책 개수를 물어보고 cin을 통해 입력 받은 후 그 값만큼 반복문을 돌면서 책 정보(이름, 가격)에 대한 정보를 입력 받는다. 책 번호, 이름, 가격에 대한 정보를 포인터형 배열에 동적할당한다.
  6. (main()) 동적할당 받은 배열을 포인터 연사자를 이용해 printAll()함수로 접근하여 책 정보를 출력한다.

소스코드 및 주석

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

class Books {
private: // private 접근지정자
    int tag; // 책 번호
    string name; // 책 이름
    int price; // 책 가격
public: // public 접근 지정자
    Books(); // 매개변수가 없는 생성자
    Books(int i, string inputName, int inputPrice); // 매개변수가 있는 생성자
    void printAll(); // 출력 함수
};

Books::Books(){ // 매개변수가 없는 생성자 내용
    tag = 0;
    name = "none";
    price = 0;
}

Books::Books(int i, string inputName, int inputPrice){ // 매개변수가 있는 생성자 내용
    name = inputName;
    price = inputPrice;
    tag = i;
}

void Books::printAll(){
    cout << "[책 " << tag << "]" << endl; // 책 번호 출력
    cout << "제목 : " << name << endl; // 책 제목 출력
    cout << "가격 : " << price << endl << endl; // 책 가격 출력
}

int main(){
    int num;
    string inputName;
    int inputPrice;

    cout << "책 개수를 입력해주세요 : ";
    cin >> num; // 책 개수(입력할 개수)

    Books *data[num]; // 포인터형 객체 배열 생성

    for (int i = 1; i <= num; i++){
        cout << "[책 " << i << "번 제목 및 가격 입력]" << endl; // 책 번호 출력
        cout << "제목 : ";
        cin >> inputName; // 책 제목 입력
        cout << "가격 : ";
        cin >> inputPrice; // 책 가격 입력
        cout << endl;
        data[i] = new Books(i, inputName, inputPrice); // 동적 할당
    }
    
    cout << "[책 제목 및 가격 출력]" << endl;
    for (int i = 1; i <= num; i++){
        data[i] -> printAll(); // printAll 접근
    }
}

결과 및 결과 분석


책 권수를 입력했을 때 그 값만큼 반복문이 잘 작동되는 것을 확인할 수 있다. 책 번호에 맞게 책 제목, 가격을 입력하고 출력도 올바르게 작동하는 것을 확인할 수 있다.

소감

포인터형 객체 배열을 선언하고 책 번호, 제목, 가격 정보가 입력될 때마다 각 배열에 동적할당을 이용해 저장하는 프로그램을 작성했다. 작년 기초프로그래밍을 배우면서 포인터를 배열로 생각하되 차이를 알아야한다고 들었다. 그때는 그게 무슨의미인지 몰랐지만 포인터형 객체 배열을 써보면서 그 의미를 점차 알아간 것 같다. i번째 포인터형 객체 배열에 책 번호, 제목, 가격을 동적할당하고 그것을 포인터연산자를 이용해 접근했다. 아직 포인터와 배열을 '객체'에 사용하는 것이 어색하기는 하지만, 다른 절차 지향 언어와는 달리 객체를 각각 생성하고 부를수 있다는 점에서 객체 지향 언어가 많이 쓰이는 이유를 알아가고 있다고 생각한다. 앞으로 객체에 대해 더 공부하고 사용해 볼 필요가 있을 것이다.


Reference

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

0개의 댓글