오늘 학습 진행 내용
라이브 세션
CH2 과제 발제
1번 과제 상태창 구현
프로그래밍 기본 요소에 대해서 학습
변수, 배열, 함수, 조건문, 반복문
학습과제 목표
C++ 기본 문법 이해
배열과 함수 사용하여 데이터 처리
사용자 입력 받아 출력하는 간단한 프로그램 설계 및 구현
개발 프로세스 가이드
1단계. 요구사항 분석 및 설계
문제를 읽고 구현해야 할 프로그램의 입력과 출력 흐름을 그림이나 글로 정리
2단계. 코드 작성 및 구현
1단계에서 설계한 내용을 바탕으로 기능을 구현, 필요 시 기능 별로 나눠서 함수 제작
3단계. 테스트 및 디버깅
예외 케이스를 방어할 수 있도록 코드 작성
필수 기능 가이드
해당 기능은 반드시 구현
HP,MP,공격력,방어력을 int형 배열로 선언, 전체 값들은 0으로 초기화
배열 이름이 status라면 status[0]은 HP, status[3]은 방어력
HP와 MP를 입력받고, HP/MP 중 하나라도 50이하의 숫자를 입력받을 경우 다시 입력 받음
HP와 MP에 값을 입력 받은 후 공격력과 방어력을 입력 받음
공격력이나 방어력 하나라도 0 이하의 숫자를 입력 받은 경우 다시 입력 받음
스탯 관리 시스템을 시작
1. HP UP 2.MP UP 3. 공격력 UP 4. 방어력 UP 5. 현재 능력치 6. Level UP 0.나가기
선택지 출력한 후, Int형 정수 하나를 입력 받아서 해당 선택지를 실행
포션 지급 함수를 작성, HP,MP 강화 포션은 5개씩 지급, HP,MP 포션 개수로 5를 저장.
함수는 다음과 같이 정의
void setPotion(int count, int p_HPPotion,int p_MPPotion)
1,2번을 선택 시 각각 HP,MP는 20 증가, 포션 개수 1개 차감, 포션이 0일 경우 사용 불가
3,4번을 선택 시 각각 공격력/방어력 2배 증가, 이 연산은 두가지 방법이 있으니 잘 생각
5번은 현재 HP, MP, 공격력, 방어력 출력
6번은 레벨업, HP/MP 포션을 하나씩 충전
0번을 선택하면 프로그램 종료
도전 기능 가이드
레벨 변수를 만들어서 6번 레벨업을 실행하면 나의 레벨도 1씩 올려줌
레벨 업 할 때 포션 충전을 함수로 변경
5번 현재 능력치 출력 시 나의 레벨도 같이 보여줌
5번 현재 능력치 출력 시 남은 포션 수도 같이 보여줌
공격력,방어력 이외에 힘,민첩,지능 같은 추가 스탯도 만들어봄
아스키 아트 적용
2번 과제. 전직 시스템과 전투 시스템
다형성을 활용한 객체지향 프로그래밍
객체 지향적 프로그래밍 하기위한 다향성과 상속에 대해서 배워서 쓸 수 있어야함
생성자를 이용하여 객체의 속성 값을 지정하고, 부모 클래스의 생성자를 자식 클래스의 생성자에서 호출
상속을 활용하여 부모 클래스의 기능을 자식 클래스에서 확장하거나 재정의
다형성을 활용해 동일한 인터페이스를 통해 다양한 객체의 동작을 실행
객체 지향 프로그래밍의 유연성과 코드 재사용성을 직접 경험
개발 프로세스 가이드
1단계. 공통 속성 찾아내기
다형성을 구현하려면 가장 중요한 것은 공통적인 부분 뽑아내는 것, 이 작업을 일반화
2단계. 기본 클래스 정의
1단계 결과 토대도 기본 클래스 정의, 필요한 부분 가상 함수로 지정, 순수 가상 함수를 이용해 추상 클래스 구성
자식 클래스들에서 반드시 재정의 강제할 수 있음
3단계. 서브 클래스 정의
기본 클래스를 상속받은 클래스들을 정의하고, 가상 함수 재정하여 다양한 행동을 구현
필수 기능 가이드
Player 기본 클래스 정의
도전 기능 가이드
참조 코드 스니펫을 보고 Monster 클래스를 작성
class Monster {
public:
// Monster 생성자
// - 몬스터의 이름을 매개변수로 입력 받습니다.
// - 모든 몬스터는 HP 10, 공격력 30, 방어력 10, 스피드 10의 능력치를 가집니다.
Monster(string name);
// 몬스터의 공격 함수
// - 플레이어 객체의 포인터를 매개변수로 입력 받습니다.
// - 몬스터의 공격력-플레이어의 방어력을 데미지로 정의합니다.
// - 만약 위에서 계산한 데미지가 0 이하라면, 데미지를 1로 정의합니다.
// - 플레이어에게 얼마나 데미지를 입혔는지 출력합니다.
// - setHP 함수를 실행하여 HP-데미지 계산 결과를 매개변수로 전달합니다.
// - setHP에서 리턴 받은 생존 여부를 기준으로 분기문이 실행됩니다.
// - 생존했을 경우, 플레이어의 남은 HP만 출력합니다.
// - 생존하지 못했을 경우, 플레이어의 남은 HP와 몬스터의 승리 문구를 출력합니다.
void attack(Player* player);
// 몬스터의 속성값을 리턴하는 get 함수
string getName();
int getHP();
int getPower();
int getDefence();
int getSpeed();
// 몬스터의 속성값을 정의하는 set 함수
// setHP의 경우 배틀 시스템에 직결되는 함수이므로, 생존 여부를 리턴합니다.
// HP가 1 이상일 때 true, HP가 0 이하가 되었을 때 false를 리턴합니다.
// HP가 1 이상일 때만 새로운 HP값 정의를 진행합니다.
// 0 이하일 경우 HP를 0으로 정의합니다.
void setName(string name);
bool setHP(int HP);
void setPower(int power);
void setDefence(int defence);
void setSpeed(int speed);
protected:
string name; // 몬스터의 이름
int HP; // 몬스터의 HP
int power; // 몬스터의 공격력
int defence; // 몬스터의 방어력
int speed; // 몬스터의 스피드
};
Player의 attack() 함수를 오버로딩하여 attack(Monster *monster) 함수를 구현
코드 스니펫 함수 요구 사항 보고 구현
github 링크로 제출(12/16 화요일 14:00까지)
1번과제와 2번 과제 모두 제출 각각 다른 레포지토리로 제출
Git 특강
Git 이란?
버전 관리 시스템 중 하나인 Git
Git의 핵심 역할
작업 기록-> 저장, 과거로 되돌리고, 언제 무엇을 왜 바꿨는지 알 수 있음
작업물 공유 -> 팀원들과 안전하게 공유 수정
버그가 발생했는데 언제부터 망가졌는지 모를 때 -> 특정 시점으로 바로 되돌림
지웠던 코드가 다시 필요할 때 -> 과거 코드로 그대로 복구 가능
팀원별로 기능 나눠서 작업할 때 -> 각각 코드 작업 후 합침
Github는 git 서버의 한 종류
Git 도구 소개
Github Desktop : 깃허브 저장소에 최적화된 도구
Fork : 여러 저장소를 같이 사용할 수 있고 깔끔함이 특징
SourceTree : 2000년대 주름잡던 Git 도구
Git의 주요 기능
clone : Git의 저장된 내용을 가져오는 것
push : 로컬 변경 사항을 Git에 업로드
Pull : Git의 변경사항 다운로드
branch : Git 정리를 위한 코드를 분기로 나누어서 관리
checkout : 해당 원하는 부분으로 이동
merge : 코드 결합
언리얼 엔진에서의 버전관리
5-1. Git + Git LFS
큰파일 다룰 수 있는 기능 지원
5-2. Perforce(P4V)
가격이 너무 비쌈
5-3. Git + SVN
아티스트나 디자이너분들이 SVN 연동해서 사용
게임 개발자를 위한 C++ 문법
챕터1-3 : 프로그래밍 기초 (3)
판단을 해주는 조건문
날씨와 온도에 따른 외출 여부 조건문 예시 코드
#include <iostream>
using namespace std;
int main() {
string weather;
int temperature;
cout << "Enter weather (sunny/rainy): ";
cin >> weather;
cout << "Enter temperature: ";
cin >> temperature;
// if/else if/else 문: 여러 조건을 순차적으로 검사합니다
// 조건: 맑은 날씨(sunny)이고 온도가 20도 이상일 때 외출
if (weather == "sunny" && temperature >= 20) {
cout << "It's a nice day to go out!\n";
}
// 조건: 비가 오거나 너무 추운 날씨
else if (weather == "rainy" || temperature < 10) {
cout << "Better stay indoors.\n";
}
// 나머지 경우
else {
cout << "You can go out, but dress appropriately.\n";
}
return 0;
}
조건문 문법
조건문은 크게 3가지 방식
if/ if - else/ if - else if - else
if(조건식){코드;}
if(조건식){코드;}
else{코드;}
if(조건식){코드;}
else if(조건식){코드;}
else{코드;} 복합 조건(&&,||)동일한 작업을 해주는 반복문
**for문 사용해서 삼각별 출력 반복문 예시 코드**
#include <iostream>
using namespace std;
int main() {
int n = 5; // 삼각형의 높이
for (int i = 1; i <= n; i++) { // 초기화: i = 1
// 종료 조건: i <= n
// 사후 조건: i++
for (int j = 1; j <= n - i; j++) { // 초기화: j = 1
// 종료 조건: j <= n - i
// 사후 동작: j++
cout << " "; // 실제 동작: 공백 출력
}
for (int j = 1; j <= i; j++) { // 초기화: j = 1
// 종료 조건: j <= i
// 사후 조건: j++
cout << "*"; // 실제 동작: 별 출력
}
cout << endl; // 줄 바꿈
}
// 출력값:
// *
// **
// ***
// ****
// *****
return 0;
}
**1과 100 사이 숫자 맞추기 게임 반복문 예시코드**
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(0)); // 랜덤 시드 초기화
int secretNumber = rand() % 100 + 1; // 1부터 100 사이의 랜덤 숫자
int guess;
cout << "Guess the number (1 to 100): ";
cin >> guess; // 초기 동작: 첫 번째 추측 입력 받기
while (guess != secretNumber) { // 종료 조건: 추측이 정답과 다를 경우 반복
if (guess < secretNumber) {
cout << "Too low! Try again: ";
} else {
cout << "Too high! Try again: ";
}
cin >> guess; // 사후 동작: 새로운 추측 입력 받기
}
cout << "Congratulations! You guessed the number!" << endl;
// 출력 예시:
// Guess the number (1 to 100): 50
// Too low! Try again: 75
// Too high! Try again: 60
// Congratulations! You guessed the number!
return 0;
}
실습
다이아몬드 모양 별 찍기
사용자로부터 정수를 입력받아,
해당 크기에 맞는 다이아몬드 모양을 *로 출력하는 프로그램을 작성하시오.
# 예시 1
입력:
4
출력:
*
***
*****
*******
*****
***
*
# 예시 2
입력:
2
출력:
*
***
*
# 예시 3
입력:
5
출력:
*
***
*****
*******
*********
*******
*****
***
*
답안
#include <iostream>
using namespace std;
int main() {
int n;
// 사용자로부터 입력 받기
cout << "다이아몬드의 크기를 입력하세요 (양의 정수): ";
cin >> n;
// 입력값 검증
if (n <= 0) {
cout << "잘못된 입력입니다. 양의 정수를 입력하세요." << endl;
return 1;
}
// 다이아몬드 상단 출력
for (int i = 1; i <= n; ++i) {
// 공백 출력
for (int j = 1; j <= n - i; ++j) {
cout << " ";
}
// 별 출력
for (int k = 1; k <= 2 * i - 1; ++k) {
cout << "*";
}
cout << endl; // 줄 바꿈
}
// 다이아몬드 하단 출력
for (int i = n - 1; i >= 1; --i) {
// 공백 출력
for (int j = 1; j <= n - i; ++j) {
cout << " ";
}
// 별 출력
for (int k = 1; k <= 2 * i - 1; ++k) {
cout << "*";
}
cout << endl; // 줄 바꿈
}
return 0;
}
CH2 학습 가이드 실습 과제
실습 과제
강의에서 나온 계산기 코드가 꼭 완성되지 않아도 괜찮아요.
대신, 지금까지 작성한 코드 한 줄마다 주석을 한 줄씩 달아봅시다.
코드에 등장하는 단어 하나하나가 주석에서 설명될 수 있도록,
가능한 한 자세하고 친절하게 적어보는 것이 목표입니다.
덧셈을 실행하는 계산기
구현 코드
#include <iostream> //입출력 라이브러리 포함(cin, cout 등)
using namespace std; //표준 네임스페이스 사용, 이름 중복 오류 방지 std 생략 처리
int main() {
int firstNum = 0; //첫번째 숫자 변수 선언 및 초기화
int secondNum = 0; //두번째 숫자 변수 선언 및 초기화
//첫번째 숫자 입력 메세지 출력과 firsNum 입력 받기
cout << "첫번째 숫자를 입력하시오 : ";
cin >> firstNum;
//두번째 숫자 입력 메세지 출력과 secondNum 입력 받기
cout << "두번째 숫자를 입력하시오 : ";
cin >> secondNum;
int result = firstNum + secondNum; //연산 결과 저장
//연산 결과 메세지 메세지 출력
cout << "결과: ";
cout << firstNum << " " << "+" << " " << secondNum << " = ";
cout << result << endl;
return 0;
}
도전 실습 과제
“- * /”- 뺄셈, 곱셈, 나눗셈에 해당하는 사칙연산을 구현해주세요.
함수를 이용하셔도 좋습니다.
프로그램 시작시 첫 입력을 통해, 어떤 연산을 할지 선택 가능해야 합니다.
예시 출력)
사칙 연산 모드를 설정해주세요.
1) 덧셈
2) 뺄셈
3) 곱셈
4) 나눗셈
> 1
//... 이후는 계산기 코드와 동일합니다.
구현 코드
#include <iostream> //입출력 라이브러리 포함(cin, cout 등)
using namespace std; //표준 네임스페이스 사용, 이름 중복 오류 방지 std 생략 처리
int main() {
int firstNum = 0; //첫번째 숫자 변수 선언 및 초기화
int secondNum = 0; //두번째 숫자 변수 선언 및 초기화
int op_mod = 0; //연산자 선택 변수 선언 및 초기화
char op; // 연산자 변수 선언
//연산 모드 입력 메세지와 함께 연산 모드 입력받기
cout << "사칙 연산 모드를 설정 해주세요." << endl;
cout << "1. 덧셈" << endl;
cout << "2. 뺄셈" << endl;
cout << "3. 곱셈" << endl;
cout << "4. 나눗셈" << endl;
cin >> op_mod;
cout << op_mod << endl;
while (op_mod != 1 && op_mod != 2 && op_mod != 3 && op_mod != 4) { //잘못된 연산자 받은 경우 다시 연산자 받게 while문으로 반복 처리 실행
cout << "잘못된 입력입니다. 다시 입력해주세요." << endl;
cout << "사칙 연산 모드를 설정 해주세요." << endl;
cout << "1. 덧셈" << endl;
cout << "2. 뺄셈" << endl;
cout << "3. 곱셈" << endl;
cout << "4. 나눗셈" << endl;
cin >> op_mod;
}
//첫번째 숫자 입력 메세지 출력과 firsNum 입력 받기
cout << "첫번째 숫자를 입력하시오 : ";
cin >> firstNum;
//두번째 숫자 입력 메세지 출력과 secondNum 입력 받기
cout << "두번째 숫자를 입력하시오 : ";
cin >> secondNum;
// 연산자에 따른 계산 수행
int result = firstNum + secondNum; //연산 결과 초기값 설정(덧셈이 초기값)
if (op_mod == 1) { // 덧셈일 경우 result에 덧셈 결과 저장, 출력용 연산자 문자 저장
op = '+';
result = firstNum + secondNum;
}
else if (op_mod == 2) { //뺄셈일 경우 result에 뺄셈 결과 저장, 출력용 연산자 문자 저장
op = '-';
result = firstNum - secondNum;
}
else if (op_mod == 3) { //곱셈일 경우 result에 곱셈 결과 저장, 출력용 연산자 문자 저장
op = '*';
result = firstNum * secondNum;
}
else if (op_mod == 4) { //나눗셈일 경우 result에 나눗셈 결과 저장, 출력용 연산자 문자 저장
op = '/';
if (secondNum != 0) {//0으로 나눌 경우 에러가 발생하는 것 방지 처리
result = firstNum / secondNum;
}
else { //0으로 나눌 경우 에러 메세지 출력 후 비정상 종료됨을 코드로 반환
cout << "0으로 나눌 수 없습니다. 종료됩니다." << endl;
return 1; //비정상 코드 종료 반환
}
}
//연산 결과 메세지 메세지 출력
cout << "결과: ";
cout << firstNum << " " << op << " " << secondNum << " = ";
cout << result << endl;
return 0;
}
도전 실습X실습
1) 1 + 1
2) 2 * 6 =
3) 3.33 / 5.2 = ?
...
```굳이 힌트를 드리자면, 토큰과 파서, 스택이에요.
기존에 공부했던 기능으로는 하기 힘들거에요.
최대한 라이브러리를 이용하는 쪽으로 개발하길 추천해요.
구현 코드
#include <iostream> //입출력 라이브러리 포함(cin, cout 등)
#include <stack> //스택 라이브러리 포함
#include <cctype> //문자 관련 함수 라이브러리 포함 isdigit 등
#include <string> //문자열 라이브러리 포함
using namespace std; //표준 네임스페이스 사용, 이름 중복 오류 방지용 std 생략 처리
int precedence(char op) { //연산자 우선순위 반환 함수
if (op == '+' || op == '-') {
return 1; //덧셈, 뺄셈 우선순위 1 반환
}
if (op == '*' || op == '/') {
return 2; //곱셈, 나눗셈 우선순위 2 반환
}
return 0; //그 외 연산자 우선순위 0 반환
}
bool popTwo(stack<double>& values, double& first_num, double& second_num) {
//스택에서 계산에 사용할 피연산자 2개를 꺼내는 함수
if (values.size() < 2) { //피연산자 개수가 2개 미만인 경우 false 반환
return false;
}
second_num = values.top(); //두 번째 피연산자(스택 맨 위) 가져오기
values.pop(); //꺼낸 두 번째 피연산자 스택에서 제거
first_num = values.top(); //첫 번째 피연산자 가져오기
values.pop(); //꺼낸 첫 번째 피연산자 스택에서 제거
return true; //정상적으로 2개를 꺼낸 경우 true 반환
}
double apply(double first_num, double second_num, char op, bool& error) {
//피연산자 두 개와 연산자를 받아 실제 연산을 수행하는 함수
error = false; //에러 플래그 초기화
//0으로 나누기 예외 처리
if (op == '/' && second_num == 0) { //연산자가 나눗셈이고, 두 번째 피연산자가 0인 경우
cout << "❌ 오류: 0으로 나눌 수 없습니다." << endl;
error = true;
return 0;
}
//연산자 종류에 따라 사칙연산 수행
switch (op) {
case '+': return first_num + second_num; //덧셈
case '-': return first_num - second_num; //뺄셈
case '*': return first_num * second_num; //곱셈
case '/': return first_num / second_num; //나눗셈
}
//사칙연산 이외의 알 수 없는 연산자가 들어온 경우
cout << "❌ 오류: 알 수 없는 연산자입니다." << endl;
error = true;
return 0;
}
double parseNumber(const string& expr, int& i) {
//수식 문자열 expr에서 현재 인덱스 i 위치부터 시작하는 하나의 숫자(정수/실수)를 파싱하는 함수
double number_value = 0; //파싱 중인 숫자 값 저장 변수
double decimal_place = 0.1; //소수점 자리수 (첫 번째 소수 자리는 0.1부터 시작)
//정수 부분 처리
while (i < static_cast<int>(expr.length()) && isdigit(expr[i])) {
//문자열에서 숫자가 연속되는 동안(정수 부분) 반복
number_value = number_value * 10 + (expr[i] - '0');
//기존 값에 10을 곱한 뒤 현재 자리 숫자를 더해서 자릿수 반영
i++; //다음 문자 위치로 이동
}
//소수점 부분 처리
if (i < static_cast<int>(expr.length()) && expr[i] == '.') {
//현재 문자가 소수점(.)인 경우 소수 부분 처리 시작
i++; //소수점 문자를 건너뛰고 다음 문자로 이동
//소수점 이하 자리 처리
while (i < static_cast<int>(expr.length()) && isdigit(expr[i])) {
//소수점 아래에 숫자가 연속되는 동안 반복
number_value += decimal_place * (expr[i] - '0');
//현재 소수 자리값(decimal_place)에 현재 숫자를 곱해서 number_value에 더함
decimal_place *= 0.1; //다음 소수 자리를 위해 자리수(0.1 → 0.01 → 0.001 ...)를 10분의 1로 감소
i++; //다음 문자 위치로 이동
}
}
//for문에서 i가 마지막 숫자 위치를 지나 한 번 더 증가하므로, 한 칸 되돌려서 조정
i--;
return number_value; //파싱된 숫자 값 반환
}
double evaluate(string expr, bool& error) { //수식 전체를 평가하는 함수
stack<double> values; //피연산자(숫자)를 저장하는 스택
stack<char> ops; //연산자와 괄호를 저장하는 스택
//수식이 '=' 문자로 끝나는 경우, 계산에 필요 없으므로 제거
if (!expr.empty() && expr.back() == '=')
expr.pop_back();
//수식 문자열의 각 문자 순회
for (int i = 0; i < static_cast<int>(expr.length()); i++) {
char c = expr[i]; //현재 문자
if (c == ' ') continue; //공백 문자는 무시
//숫자 또는 ".5" 같은 형태로 시작하는 경우 숫자 파싱
if (isdigit(c) || c == '.') {
values.push(parseNumber(expr, i)); //숫자를 파싱해서 피연산자 스택에 푸시
continue;
}
if (c == '(') {
//여는 괄호는 연산자 스택에 그대로 푸시
ops.push(c);
}
else if (c == ')') {
//닫는 괄호가 나오면, 대응되는 여는 괄호를 만날 때까지 연산 수행
bool found_paren = false; //대응되는 여는 괄호를 찾았는지 여부
while (!ops.empty()) {
char op = ops.top();
ops.pop(); //연산자 스택에서 하나 꺼냄
if (op == '(') {
//여는 괄호를 만나면 괄호 구간 정리 완료
found_paren = true;
break;
}
double first_num, second_num; //계산에 사용할 피연산자 두 개
if (!popTwo(values, first_num, second_num)) { //피연산자가 부족한 경우
cout << "❌ 오류: 피연산자가 부족합니다." << endl;
error = true;
return 0;
}
values.push(apply(first_num, second_num, op, error)); //연산 결과를 다시 피연산자 스택에 푸시
if (error) return 0; //연산 중 오류 발생 시 즉시 종료
}
if (!found_paren) { //여는 괄호를 못 찾은 경우 (괄호 짝이 맞지 않음)
cout << "❌ 오류: 괄호가 잘못되었습니다." << endl;
error = true;
return 0;
}
}
else if (precedence(c) > 0) {
//사칙연산(+, -, *, /)인 경우
//현재 연산자보다 우선순위가 높거나 같은 연산자를 먼저 처리
while (!ops.empty() && precedence(ops.top()) >= precedence(c)) {
char op = ops.top();
ops.pop(); //연산자 스택에서 하나 꺼냄
double first_num, second_num; //계산에 사용할 피연산자 두 개
if (!popTwo(values, first_num, second_num)) {
cout << "❌ 오류: 피연산자가 부족합니다." << endl;
error = true;
return 0;
}
values.push(apply(first_num, second_num, op, error)); //연산 결과를 피연산자 스택에 푸시
if (error) return 0; //연산 중 오류 발생 시 즉시 종료
}
ops.push(c); //현재 연산자를 연산자 스택에 푸시
}
else {
//숫자, 괄호, 연산자 모두 아닌 잘못된 문자
cout << "❌ 오류: 잘못된 문자 '" << c << "' 입니다." << endl;
error = true;
return 0;
}
}
//수식 순회를 마친 후, 남아 있는 연산자들을 모두 처리
while (!ops.empty()) {
char op = ops.top();
ops.pop();
if (op == '(') { //여는 괄호가 남아있는 경우도 괄호 오류
cout << "❌ 오류: 괄호가 잘못되었습니다." << endl;
error = true;
return 0;
}
double first_num, second_num;
if (!popTwo(values, first_num, second_num)) {
cout << "❌ 오류: 피연산자가 부족합니다." << endl;
error = true;
return 0;
}
values.push(apply(first_num, second_num, op, error)); //연산 결과를 피연산자 스택에 푸시
if (error) return 0; //연산 중 오류 발생 시 즉시 종료
}
if (values.empty()) { //피연산자 스택이 비어 있는 경우 (아무 계산 결과도 없는 경우)
cout << "❌ 오류: 수식이 비어있습니다." << endl;
error = true;
return 0;
}
return values.top(); //최종 계산 결과 반환
}
int main() {
string expr; //사용자로부터 입력받을 수식 문자열
cout << "수식을 입력하세요: ";
getline(cin, expr); //한 줄 전체를 입력받아 expr에 저장
bool error = false; //계산 과정에서 에러 발생 여부
double result = evaluate(expr, error); //수식을 평가해 결과값과 에러 여부를 받음
if (!error) { //에러가 나지 않은 경우에만 결과 출력
cout << "결과: " << result << endl;
}
}