출처 => C++ How to Program (Detitel / Prenticehall) / 현재 그리고 미래지향적인 C++ 프로그래밍(장석우, 임정목 / 비앤씨에듀케이션)
예외란 무엇인가?
▶ 프로그램을 실행 중, 오작동이나 결과에 영향을 미치는 예상치 못한 상황이 발생한다. 이런 사오항을 예외 발생이라고 하는데 이를 처리하는 코드를 예외 처리기라고 한다.
▶ 예를 들면 다음과 같은 상황이다.
#include<iostream>
using namespace std;
int getExp(int base, int exp) {
int value = 1;
for (int n = 0; n < exp; n++) {
value = value * base;
//거듭제곱. base를 exp번 곱한 값이 value
}
return value;
}
void main() {
int v = getExp(2, 3);
cout << "2의 3승은" << v << "입니다" << endl;
int e = getExp(2, -3);
cout << "2의 -3승은 " << e << "입니다" << endl;//오류 발생!
}
▶ 오류가 발생한다!!!! 2의 -3은 1/8인데 이런 기초적인 실수를 컴퓨터가 하다니....! 이렇게 예상치도 못한 오류가 발생하는 경우를 대비하기 위해 예외 처리기를 사용한다.
▶ 지금까지 공부했던 걸로 이런 상황을 해결할 수 있는데 방법은 2가지 정도이다. if문을 사용하는 방법과 참조 매개변수를 사용하는 방법이다.
1. if문과 리턴값을 이용한 오류처리 예제
#include<iostream>
using namespace std;
int getExp(int base, int exp) {
//base의 exp지수승 계산
if (base <= 0 || exp <= 0) {
//음수의 계승이거나 양수의 음수 승
return -1;//오류 리턴
}
int value = 1;
for (int i = 0; i < exp; i++) {
value = value * base;
}
return value;
}
void main() {
int v = getExp(2, 3);
cout << "2의 3승은" << v << endl;
int e = getExp(2, -3);
if (e != -1) {
cout << "2의 3승은" << e << endl;
}
else cout << "오류입니다. " << endl;
}
2. 리턴 값과 참조 매개 변수를 이용한 오류 처리
#include<iostream>
using namespace std;
bool getExp(int base, int exp, int& ret) {
//참조 매개변수인net
if (base <= 0 || exp <= 0)
return false;
int value = 1;
for (int i = 0; i < exp; i++) {
value = value * base;
}
ret = value;
return true;
}
void main() {
int v = 0;
if (getExp(2, 3, v))//만약 true라면
cout << "2의 3승은" << v << endl;
else cout << "오류입니다." << endl;
int e = 0;
if (getExp(2, -3, e))
cout << "2의 -3승은" << e << endl;
else cout << "오류입니다" << endl;
}
2. 예외 기본 처리 형식(feat. try, throw, catch)
▶ 예외 처리를 할 때는 세 가지의 문법 용어가 필요한데 그것이 바로 try, throw, 그리고 catch 문이다.
▶ try { }블록 => 예외가 발생할 가능성이 있는 코드를 묶음
▶ throw { }블록 => 예외가 발견되었을 때 예외 발생을 알리는 문장
▶ catch { }블록 => throw에 의해 발생할 예외를 처리하는 코드를 묶음
▶ 예제를 통해서 예외 처리문이 어떻게 쓰이는지 알아보자
#include<iostream>
using namespace std;
void main() {
int n, sum, average;
while (true) {
cout << "합을 압력하세요>";
cin >> sum;
cout << "인원수를 입력하세요>";
cin >> n;
try {
if (n <= 0)
throw n;
else average = sum / n;
}
catch (int x) {
cout << "예외 발생!"
<< x << "으로 나눌 수 없음" << endl;
average = 0;
cout << endl;
continue;
}
cout << "평균=" << average << endl << endl;
}
}
▶ 위의 소스에서 try문에 대해서 자세히 알아보도록 하자
try{
if(n<=0)
throw n;
else average=sum/n;
}
▶ 예외가 발생할 수도 있는 코드를 나타낸 try문이다. 인원수가 0이거나 음수이면 나누는 것이 불가능하므로 이에 대한 예외를 고려하여 작성하였다.
catch (int x) {
cout << "예외 발생!" << x << "으로 나눌 수 없음" << endl;
average = 0;
cout << endl;
continue;
}
▶ 만약 사용자가 n에 음수나 0을 입력했다면 아래의 문장이 실행된다.
▶ 이처럼 예외 처리문을 이용하여 코드를 작성하면 코드가 보다 더 직관적으로 보이게 된다.
▶ 아까 위에서 언급한 예제를 try-catch문을 이용하여 다시 작성해보도록 하겠다.
#include<iostream>
using namespace std;
int getExp(int base, int exp) {
if (base <= 0 || exp <= 0) {
throw"음수 사용 불가";
}
int value = 1;
for (int i = 0; i < exp; i++) {
value = value * base;
}
return value;
}
void main() {
int v = 0;
try {
v = getExp(2, 3);
cout << "2의 3승은" << v << "입니다" << endl;
v = getExp(2, -3);
cout << "2의 -3승은" << v << "입니다" << endl;
}
catch (char* s) {
cout << s << endl;
}
}
예외 클래스 만들기
▶ 예외 클래스는 예외 정보를 포함한다. throw로 객체를 던지는데 객체가 복사되어 예외 파라미터에 전달을 한다.
#include<iostream>
#include<cstring>
using namespace std;
class MyException {
int lineNo;
string func, msg;
public:
MyException(int n, string f, string m) {
this->lineNo = n;
this->func = f;
this->msg = m;
}
void print() {
cout << func << ":" << lineNo << "," << msg << endl;
//예외를 설명해주는 메소드
//
}
};
class DivideByZeroException :public MyException {
//0으로 나누는 예외 클래스 선언
public:
DivideByZeroException(int lineNo, string func, string msg)
: MyException(lineNo, func, msg) {}
};
class InvalidInputException :public MyException {
//잘못된 입력 예외 클래스 선언
public:
InvalidInputException(int lineNo, string func, string msg)
: MyException(lineNo, func, msg) {}
};
void main() {
int x, y;
try {
cout << "나눗셈을 합니다. 두 개의 양의 정수를 입력하세요>>";
cin >> x >> y;
if (x < 0 || y < 0)
throw InvalidInputException(32, "main()", "음수 입력 예외 발생");
//InvalidInputException 메소드를 던짐.
if (y == 0)
throw DivideByZeroException(34, "main()", "0으로 나누는 예외 발생");
//DivideByZeroException 메소드 던짐
cout << (double)x / (double)y;
//만약 아무런 예외(if 문)에도 포함이 되지 않는다면 나눈 결과를 출력
}
catch (DivideByZeroException& e) {
//DivideByZeroException의 객체인 e를 생성하고 print()메소드 던짐
e.print();
}
catch (InvalidInputException& e) {
//InvalidInputException의 객체인 e를 생성하고 print()메소드 던짐
e.print();
}
}
예외처리를 이용한 추가 Example
1. 예외 처리를 이용한 퀴즈 Example
#include<iostream>
using namespace std;
void main() {
while (1) {
int a = (int)(rand() % 100);
//0에서 100까지의 수 중 임의로 하나 선택(랜덤함수)
int b = (int)(rand() % 100);
//0에서 100까지의 수 중 임의로 하나 선택(랜덤함수)
int result = a + b;
int answer;//사용자가 입력하는 값
cout << "문제를 내겠습니다" << endl;
cout << a << "+" << b << "= ?" << endl;
cin >> answer;
try {
if (result != answer)//만약에 정답이 아니라면
throw answer;//answer를 int n에 대입하여 throw하여라
else cout << "정답입니다!" << endl;
//만약 정답이면 정답이라는 것을 출력!
}
catch (int n) {//answer로 throw한 것을 받아서
cout << n << "은 오답입니다." << endl;
//오답이라는 것을 출력!
}
}
}
'💻 개인공부 💻 > C | C++' 카테고리의 다른 글
[C++] 함수와 참조 (feat. &, 별명) (0) | 2020.06.24 |
---|---|
[C++] string 클래스 (feat. copy, getline, substr, find, replace) (0) | 2020.06.24 |
[C++] 조작자를 이용한 구조체 객체들의 정보 출력 프로그램(feat. struct, setw(), switch) (0) | 2020.06.21 |
[C++] 제네릭 함수 (feat. template) (0) | 2020.06.21 |
[C++] 상속(Inheritance) - 2 (feat. 가상 함수와 추상클래스) (0) | 2020.06.20 |