언어/C++

[C++] for each문 ->참조 변수 언제 사용? (feat.깊은 복사, 얕은복사) (+ cin.fail) 예제

study_memo 2023. 9. 30. 01:20

다음은 커피자판기로 작동하는 프로그램을 만들기 위해 필요한 두 클래스이다.

class CoffeeVendingMachine { // 커피 자판기를 표현하는 클래스

    Container tong[3]; // tong[0]는 커피, tong[1]은 물, tong[2]는 설탕통을 나타냄

    void fill(); // 3개의 통을 모두 10으로 채움

    void selectEspresso(); // 에스프레소를 선택한 경우, 커피 1, 1 소모

    void selectAmericano(); // 아메리카노를 선택한 경우, 커피 1, 2 소모

    void selectSugarCoffee(); // 설탕커피를 선택한 경우, 커피 1, 2 소모, 설탕 1 소모

    void show(); // 현재 커피, , 설탕의 잔량 출력

    bool checkInputError(); // 오류 처리를 위해 추가한 멤버 함수

public:

    void run(); // 커피 자판기 작동

};

 

class Container { // 통 하나를 나타내는 클래스

    int size; // 현재 저장 량, 최대 저장 가능량은 10

public:

    Container() { size = 10; }

    void fill(int n); // n 만큼 채우기

    bool consume(int n); // n 만큼 소모하기

    int getSize(); // 현재 크기 리턴

};

 

다음과 같이 실행되도록 main() 함수와 CoffeeVendingMachine, Container를 완성하라. 만일 커피, , 설탕 중 잔량이 하나라도 부족해 커피를 제공할 수 없는 경우 재료가 부족합니다.“ 를 출력하라 

 

#include <iostream>
using namespace std;

class Container { // 통 하나를 나타내는 클래스
    int size; // 현재 저장 량, 최대 저장 가능량은 10
public:
    Container() { size = 10; }
    void fill(int n); // n 만큼 채우기
    bool consume(int n); // n 만큼 소모하기
    int getSize(); // 현재 크기 리턴
};

void Container::fill(int n) {
    size = n; // n 만큼 채우기
}
bool Container::consume(int n) {
    size -= n; //n만큼 소모
    if (size < 0) { //size가 0보다 작으면
        size = 0; //0으로 초기화
        return false; //false반환
    }
    else return true; //tre반환
}

int Container::getSize() {
    return size;
}

class CoffeeVendingMachine { // 커피 자판기를 표현하는 클래스
    Container tong[3]; // tong[0]는 커피, tong[1]은 물, tong[2]는 설탕통을 나타냄
    void fill(); // 3개의 통을 모두 10으로 채움
    void selectEspresso(); // 에스프레소를 선택한 경우, 커피 1, 물 1 소모
    void selectAmericano(); // 아메리카노를 선택한 경우,  커피 1, 물 2 소모
    void selectSugarCoffee(); // 설탕커피를 선택한 경우, 커피 1, 물 2 소모, 설탕 1 소모
    void show(); // 현재 커피, 물, 설탕의 잔량 출력
    bool checkInputError(); // 오류 처리를 위해 추가한 멤버 함수
public:
    void run(); // 커피 자판기 작동
};

void CoffeeVendingMachine::fill() {
    for (Container& a : tong) {//for each문, &를 안쓰면 깊은복사인데, 값만 복사되므로 주소값이 달라서 안 채워짐.
        a.fill(10);
    }
    show();
}
void CoffeeVendingMachine::selectEspresso() {
    bool k = tong[0].consume(1) && tong[1].consume(1);;
    if (!k) cout << "원료가 부족합니다." << endl;
    else cout << "에스프레소 드세요" << endl;
}

void CoffeeVendingMachine::selectAmericano() {
    bool k = tong[0].consume(1) && tong[1].consume(2);;
    if (!k) cout << "원료가 부족합니다." << endl;
    else cout << "아메리카노 드세요" << endl;
}

void CoffeeVendingMachine::selectSugarCoffee() {
    bool k = tong[0].consume(1) && tong[1].consume(2) && tong[2].consume(1);
    if (!k) cout << "원료가 부족합니다." << endl;
    else cout << "설탕커피 드세요" << endl;
}

void CoffeeVendingMachine::show() {
    cout << "커피 " << tong[0].getSize() << ", 물 " << tong[1].getSize() << ", 설탕 " << tong[2].getSize() << endl;
}
bool CoffeeVendingMachine::checkInputError() {
    if (cin.fail()) { // 정수대신 문자열이 입력되어 오류가 발생하는 경우 대처. 
        cin.clear();  //내부 상태 플러그 초기화
        cin.ignore(100, '\n');  // 입력버퍼 비움
        cout << "메뉴에 있는 숫자만을 입력해주세요." << endl;
        return true; // 오류 있음
    }
    else
        return false; // 오류 없음
}

void CoffeeVendingMachine::run() {
    cout << "***** 커피자판기를 작동합니다. *****" << endl;

    while (true) {
        int num;
        cout << "메뉴를 눌러주세요(1:에스프레소, 2:아메리카노, 3:설탕커피, 4:잔량보기, 5:채우기)>>";
        cin >> num;
        if (checkInputError()) {
            continue;
        }
        switch (num) {
        case 1:
            selectEspresso();
            break;
        case 2:
            selectAmericano();
            break;
        case 3:
            selectSugarCoffee();
            break;
        case 4:
            show();
            break;
        case 5:
            fill();
            break;
        default:
            cout << "메뉴에 있는 숫자만을 입력해주세요." << endl;
            break;
        }
    }
}

int main() {
    CoffeeVendingMachine coffeeVendingMachine;
    coffeeVendingMachine.run();
    return 0;
}

for-each문이란? 

for-each 조건문을 사용하면 간단히 반복문을 작성할 수 있다. (auto 사용가능 - 자료형 자동으로 알아서 해준다.)

(arr를 만약에 동적할당하면 for-each 사용이 불가능하다.)

for(int num : arr){
	cout << num << endl;
}

 

여기서 잠깐!

for-each로 위의 arr의 내용을 바꾸고 싶다면,  &참조변수를 사용해야한다.

이유) &를 사용하지 않으면  깊은복사인데(깊은 복사: 값만 복사, 얕은 복사: 주소값을 복사) , 값만 복사되므로 주소값이 달라서 안 채워진다.

for(int &num : arr){
	num = 10;
}