문과 코린이의, [C. C++] 기록/C++ 이론

[문과 코린이의 IT 기록장] C++ - 예외상황과 예외처리의 이해 및 예외처리 매커니즘 (예외상황을 처리하지 않았을 때의 결과, if문을 이용한 예외처리, C++의 예외처리 매커니즘의 이해 : try와 cat..

벼리네 2021. 7. 1. 10:15
반응형

[문과 코린이의 IT 기록장] C++ - 예외상황과 예외처리의 이해 및 예외처리 매커니즘 (예외상황을 처리하지 않았을 때의 결과, if문을 이용한 예외처리, C++의 예외처리 매커니즘의 이해 : try와 catch, 그리고 throw의 이해, try블록을 묶는 기준)

[문과 코린이의 IT 기록장] C++ - 예외상황과 예외처리의 이해 및 예외처리 매커니즘 (예외상황을 처리하지 않았을 때의 결과, if문을 이용한 예외처리, C++의 예외처리 매커니즘의 이해 : try와 catch, 그리고 throw의 이해, try블록을 묶는 기준)

 


1. 예외상황을 처리하지 않았을 때의 결과

- C++의 예외 : 프로그램의 실행 도중에 발생하는 문제상황 (즉, 프로그램의 논리에 맞지 않는 상황)

- 따라서, 컴파일시 발생하는 문법적인 에러는 예외의 범주에 포함되지 않는다.

 

ex ) 예외의 예시

- 나이를 입력하라고 했는데, 0보다 작은 값이 입력된 경우

- 나눗셈을 위한 두 개의 정수를 입력받는데, 제수(나누는 수)로 0이 입력된 경우

- 주민등록번호 13자리만 입력하라고 했더니, 중간에 -를 포함하여 14자리를 입력한 경우

 


Case 1 ) 예외가 발생하지 않은 경우

#include<iostream>
using namespace std;

int main() {
	int num1, num2;
	cout << "두 개의 숫자 입력 : ";
	cin >> num1 >> num2;

	cout << "나눗셈의 몫 : " << num1 / num2 << endl;
	cout << "나눗셈의 나머지 : " << num1 % num2 << endl;
	return 0;
}

Case 2 ) 예외가 발생한 경우

예외가 발생하면, 그에 따른 처리가 이루어져야지, 그냥 프로그램이 종료되는 상황을 만들면 안된다.

 


2. if문을 이용한 예외처리

예외처리 방법은 대표적으로 if문을 활용하는 것이다.

즉, if문을 통해 예외상황의 발생유무를 확인한 후, 그에 따른 처리를 진행하는 것이다.

 

Case 3 ) if 문을 통한 예외처리

#include<iostream>
using namespace std;

int main() {
	int num1, num2;
	cout << "두 개의 숫자 입력 : ";
	cin >> num1 >> num2; // 예외의 발생위치

	if (num2==0) // 예외의 발견위치
	{
		cout << "제수는 0이 될 수 없습니다." << endl; // 예외의 처리위치
		cout << "프로그램을 다시 실행하세요." << endl; // 예외의 처리위치
	}
	else
	{
		cout << "나눗셈의 몫 : " << num1 / num2 << endl;
		cout << "나눗셈의 나머지 : " << num1 % num2 << endl;
	}

	return 0;
}

이 코드를 보면, 예외가 발견되는 위치는 예외가 발생하는 위치와 다를 수 있다.

 

그런데 이와 같은 예외처리방식은, 예외처리를 위한 코드와 프로그램의 흐름을 구성하는 코드를 쉽게 구분하지 못한다는 단점을 지닌다. 따라서, C++의 예외처리 매커니즘을 사용하는 것이 필요하다.

 


3. C++의 예외처리 매커니즘의 이해 : try와 catch, 그리고 throw의 이해

- C++은 구조적으로 예외를 처리할 수 있는 매커니즘을 제공한다. 이 메커니즘을 이용하면 코드의 가독성과 유지보수성을 높일 수 있다.

 

[ try 블록과 catch 블록 ]

/* try : 예외를 발견하다 */
try{ 
	// 예외 발생 예상지역
}

/* catch : 예외를 잡는다. */
catch(처리할 예외의 종류 명시)
{
	// 예외처리 코드의 삽입
}

- try 블록은 예외발생에 대한 검사의 범위를 지정할 때 사용된다.
- try 블록 내에서 예외가 발생하면, 이는 C++의 예외처리 매커니즘에 의해 처리가 된다.

- 즉, try블록에서 발생한 예외는 catch 블록에서 처리가 된다.

 * try와 catch는 하나의 문장이기 때문에 항상 이어서 등장해야 하며, 사이에 다른 문장에 오면 안된다.

 

 

[ throw 블록 ]

키워드 throw는 예외가 발생했음을 알리는 문장의 구성에 사용된다.

throw expn;

expn(예외 데이터, 예외 객체) : 변수, 상수, 객체 등 표현 가능한 모든 데이터들이 될 수 있음.

 ※ 그러나 예외상황에 대한 정보를 담은 의미있는 데이터야 함.

 

 

[ try, catch + throw 블록 ]

try
{
	...
    if(예외가 발생한다면)
    throw expn; // 예외의 발생
    ...
}

catch(type exn) // exn = 예외 expn의 전달
{
	// 예외의 처리
}

즉, throw에 의해 던져진 '예외 데이터'는, '예외 데이터'를 감싸는 try의 블록에 의해 감지가 되어, 이어 등장하는 catch 블록에 의해 처리된다.

 


Case 4 ) 예외처리 발생 X

#include<iostream>
using namespace std;

int main() {
	int num1, num2;
	cout << "두 개의 숫자 입력 : ";
	cin >> num1 >> num2; // 예외의 발생위치

	try
	{
		if (num2 == 0) {
			throw num2; // 바로 catch블록으로 넘어감
		}

		cout << "나눗셈의 몫 : " << num1 / num2 << endl;
		cout << "나눗셈의 나머지 : " << num1 % num2 << endl;
		// throw를 만나지 않았다면, catch 블록은 실행되지 않음
	}
	catch (int expn) // throw절에 의해 던져진 데이터의 자료형과 catch블록의 매개변수 자료형은 일치해야 한다.
	{
		cout << "제수는 " << expn << "이 될 수 없습니다." << endl;
		cout << "프로그램을 다시 실행하세요." << endl;
	}

	cout << "end of main" << endl;

	return 0;
}

Case 5 ) 예외처리 발생 O

 

※ 정리
- try 블록을 만나면 그 안에 삽입된 문장이 순서대로 실행된다.
- try 블록 내에서 예외가 발생하지 않으면, catch 블록 이후를 실행한다.
- try 블록 내에서 예외가 발생하면, 예외가 발생한 지점 이후의 나머지 try영역은 건너뛴다.

 


4. try블록을 묶는 기준

- try블록은 예외가 발생할만한 영역만 묶는 것이 아니라, 그와 관련된 모든 문장을 함께 묶어 하나의 일(work)단위로 구성한다.

 

[ 만약 아래의 문장과 같이 코드가 묶였다면? ]

try
{
	if(num2==0)
    	throw num2;
}

catch(int expn) { ... }

cout << "나눗셈의 몫 : " << num1 / num2 << endl;
cout << "나눗셈의 나머지 : " << num1 % num2 << endl;

 

이와 같은 경우 예외가 발생했음을 인지했음에도 불구하고, 더불어 catch문에 의해 예외가 처리되었음에도 불구하고, 실행해서는 안되는 문장을 실행하게 된다.

 

따라서 try 블록 밖으로 나온 두 문장을 내부로 넣어서, 예외발생시 실행되지 않도록 해야 한다.

  

 


* 유의사항
- 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다.
- 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다.
- 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :)
반응형