25.05.29 (3) - 추가학습

김영하·2025년 5월 29일

C++

목록 보기
13/32

클래스 개념 관련

1. 배터리 관리 클래스

세부적인 요구사항은 아래와 같다:

기능

  • 배터리 잔량(0~100)을 관리합니다.
  • 배터리 사용 및 충전을 할 수 있어야 합니다.
  • 초기 배터리는 0입니다.

구현할 메서드

  • 배터리 잔량을 반환하는 메서드
  • 배터리를 사용하는 메서드 (한번 호출될 때마다 배터리 잔량은 5씩 감소)
  • 배터리를 충전하는 메서드 (한번 호출될 때마다 배터리 잔량은 7씩 충전)

초기 상태

  • 배터리 잔량의 기본값은 100입니다.
    해당 값은 생성자에서 설정할 수 있어야 합니다.

2. 두 분수의 곱셈 클래스

세부 사항:

Fraction 클래스를 만들어 분수를 표현하세요.

  • 분자는 numerator, 분모는 denominator로 관리합니다.
  • 두 분수의 곱의 결과는 기약분수로 출력합니다.

구현할 메서드

  • 기본 생성자를 만드세요. (numerator = 0 / denominator = 1 )
  • 분자의 분모의 수를 입력받는 생성자를 구현하세요.
  • 현재 분수를 출력하는 함수 display를 구현하세요.
  • 기약분수 형태로 만드는 함수 simplify를 구현하세요.
    이때 최대공약수를 구하는 함수가 필요할 수 있는데 아래를 참조하세요.
// gcd 함수 구현 (유클리드 호제법)
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b; // b는 나머지 값으로 덮어씌워지고
        a = temp; // a 는 바로 전의 b 값으로
    }
    return a;
}


1번, 배터리

  • 헤더 파일 (battery.h)

기존에 배운대로 한번만 정의되도록 #ifndef 구문 활용
생성자 -> 배터리 잔량 기본값 100
사용할 함수들 : 잔량 확인, 잔량 감소, 잔량 증가 "선언만" 해주고
멤버 변수 charge 선언

  • 소스 파일 (battery.cpp)

잔량 확인 함수 Battery::getCharge()
= 잔량을 확인하고 표시도 해줘야해서, 리턴값이 있어야하고, int 형 함수로

잔량 감소/증가 함수는 증감만 해주면 그만이라 void

  • 메인 함수 (solution.cpp)


  • 정답 코드 확인
#include <iostream>

class Battery {
private:
    int charge; // 배터리 잔량

public:
    // 생성자: 기본값은 100으로 설정
    Battery(int initialCharge = 100) : charge(initialCharge) {
        if (charge < 0) {
            charge = 0;
        } else if (charge > 100) {
            charge = 100;
        }
    }

    // 배터리 잔량 반환
    int getCharge() const {
        return charge;
    }

    // 배터리를 사용하여 잔량 감소
    void useBattery() {
        if (charge >= 5) {
            charge -= 5;
        } else {
            charge = 0;
        }
        std::cout << "Battery used. Current charge: " << charge << "%\n";
    }

    // 배터리를 충전하여 잔량 증가
    void chargeBattery() {
        if (charge <= 93) {
            charge += 7;
        } else {
            charge = 100;
        }
        std::cout << "Battery charged. Current charge: " << charge << "%\n";
    }
};

int main() {
    // 배터리 객체 생성 (초기 잔량 100)
    Battery battery;

    std::cout << "Initial charge: " << battery.getCharge() << "%\n";

    // 배터리 사용 및 충전 테스트
    battery.useBattery(); // 잔량 95%
    battery.useBattery(); // 잔량 90%
    battery.chargeBattery(); // 잔량 97%
    battery.useBattery(); // 잔량 92%

    return 0;
}

일단 생성자와 함수들에 들어있는 조건 부분은
배터리는 0~100% 로 되어있고 그 조건도 붙어있었기 때문에
배터리 양에 관한 조건문들을 넣어주는 게 맞았다.

다만 생성자의
Battery(int initialCharge = 100) : charge(initialCharge)
이 부분은 어떤 의미일까?
일단 : 를 기준으로 앞부분이 기존에 알던 기본값 포함한 생성자 모습인데,

알아본 결과:
:멤버 이니셜라이저
= 멤버 변수의 초기화나 클래스 상속에 쓰인다

부모 클래스의 멤버 변수를 초기화 하기 위해서 생성자 함수를 호출한다던가, 클래스 내의 변수를 초기화한다던가, const 변수를 초기화 할때도 사용됩니다. 멤버 이니셜라이저는 생성자의 몸체 부분보다 먼저 실행된다는 특징을 가지고 있습니다.



2번, 두 분수의 곱셈

진도상 이 문제는 정답을 보며 학습하기로

  • 현재 헤더 파일

  • 현재 소스 파일

    클래스 변수끼리 곱해서
    분자, 분모의 최대공약수 구해서 그걸로 나눠주고 하는 과정을 구현하지 못했다.
    최대 우려점은 multiply() 하는 과정에서 멤버 변수가 변경될까봐.
    ex) f1 곱하기 f2 했는데 f1 원래 값이 안 남아있고 변질될까봐

  • 정답 코드

#include <iostream>
using namespace std;

// Fraction 클래스 정의
// 분수를 표현하고 곱셈 및 단순화 기능을 제공합니다.
class Fraction {
private:
    int numerator;   // 분자
    int denominator; // 분모

    // 최대공약수를 계산하는 유클리드 호제법 구현
    // gcd 함수는 Fraction 클래스 내부에서만 사용되므로 private으로 설정
    int gcd(int a, int b) const { 
    // 여기 const는 클래스 안에 있는 멤버 함수에만 쓸 수 있는 용법인데,
    // 이 함수가 멤버로서 속한, 객체의 변수를 수정할 수 없게 만들어준다.
        while (b != 0) {
            int temp = b; // 현재 b 값을 저장
            b = a % b;    // a를 b로 나눈 나머지를 새로운 b로 설정
            a = temp;     // 이전 b 값을 새로운 a로 설정
        }
        return a; // b가 0이 되었을 때 a가 최대공약수
    }

public:
    // 기본 생성자를 쓸 경우=
    // 분자를 0, 분모를 1로 초기화합니다. (0/1은 0을 나타냄)
    Fraction() : numerator(0), denominator(1) {}
    // `:` 로 멤버변수 초기화

    // 매개변수가 있는 생성자를 경우=
    // 사용자로부터 분자와 분모를 입력받아 초기화합니다.
    // 분모가 0일 경우 자동으로 1로 설정합니다. (분모가 0이면 정의되지 않음)
    Fraction(int num, int denom) {
        numerator = num;
        denominator = (denom != 0) ? denom : 1; // 분모가 0이면 1로 설정
        // denom != 0 이라는 조건에 맞냐`?` 하고 물어봤을 때
        // true 면 denom 그대로, 아니면 1로
    }

    // 분수를 간단한 형태로 변환하는 함수
    // 최대공약수(gcd)를 이용해 분자와 분모를 나눕니다.
    void simplify() {
        int gcdValue = gcd(numerator, denominator); // 분자와 분모의 최대공약수 계산
        numerator /= gcdValue;   // 분자를 최대공약수로 나누기
        denominator /= gcdValue; // 분모를 최대공약수로 나누기
    }

    // 두 분수를 곱하는 함수
    // 두 분수를 곱한 새로운 분수를 반환합니다.
    Fraction multiply(const Fraction& other) const {
    // Fraction 뒤에 `&` 붙여서 정보 참조해오는 듯
    // 클래스 이름 뒤에 `&` 를 붙임으로서 참조변수 생성,
    // 여기서는 Fraction 클래스 객체를 참조하는 참조변수 `other`
        // 새로운 분자 = 현재 분수의 분자 * 다른 분수의 분자
        int newNumerator = numerator * other.numerator;

        // 새로운 분모 = 현재 분수의 분모 * 다른 분수의 분모
        int newDenominator = denominator * other.denominator;

        // 새로운 Fraction 객체 생성
        Fraction result(newNumerator, newDenominator);

        // 결과를 간단히 만들기
        result.simplify();

        return result;
    }

    // 분수를 출력하는 함수
    // 분자를 '/' 기호와 함께 출력합니다.
    void display() const {
        cout << numerator << "/" << denominator;
    }
};

int main() {
    // 두 분수 생성
    Fraction f1(1, 2); // 첫 번째 분수: 1/2
    Fraction f2(3, 4); // 두 번째 분수: 3/4

    // 두 분수를 곱하기
    Fraction product = f1.multiply(f2); // f1 * f2

    // 결과 출력
    cout << "곱한 결과: ";
    product.display(); // 결과 분수 출력
    cout << endl;

    return 0;
}

일단 정답 코드는 한 곳에 쓰느라 헤더/소스 나눠지지 않은 상태

주요점은
0) 생성자는 여러개 작성 가능!

1) 최대공약수 구하는 gcd 함수는 클래스 안에서만 쓰니까 private
ㄴ 기약분수 만들때 계산만 해주면 되니까 세부사항은 숨기기
2) 함수 뒤에 const 붙여주는 활용법
ㄴ 함수가 포함된 클래스의 변수를 수정할 수 없게 됨
3) gcd 함수에 파라미터 넣어놔야 클래스 안에서 활용가능
ㄴ 어쨌든 수 2개를 받아야 최대공약수를 구할 수 있으니까

잘 설정하는 법이 있을 수도 있지만 원본 값이 변경되선 안되기도 하고

4) simplify 과정은 최대공약수로 각각 나눠주는 것,
미리 gcdValue 만들어서 최대공약수 저장해주고
그걸로 분자-분모 나눠서 기약분수 만들어주기

5) multiply 과정인데,
다른 인스턴스의 값을 참조해와야하고 + 원본값도 바뀌면 안되니까
const Fraction& other 로 파라미터 지정
ㄴ 클래스이름 뒤에 & 붙여서 other 라는 이름으로 참조변수 생성
Fraction multiply(const Fraction& other) const {
const 적극 활용
6) 분수끼리 곱했으니 결과를 분수로 보여줘야 하니까
분자분모들의 형태로만 남기지 말고
함수 내부에서 Fraction result(newNumerator, newDenominator) 로
새 객체 생성하고,
simplify() 까지 적용
7) multiply 함수를 선언할 때, void 나 기타 데이터형 대신
Fraction이 붙어있는데 어떻게 된 구조일까?
==>
함수 앞에 붙는 데이터형은 리턴값의 형태를 나타낸다고 했으니,
multiply 의 리턴값은 클래스 객체 이기 때문에 Fraction 이 붙은 것으로 보인다!!

8) 삼항연산자
(조건식) ? a : b = 조건식을 만족하냐 하고 ? 로 물어보면
true면 a 고 아니면(false면) b

profile
내일배움캠프 Unreal 3기

0개의 댓글