C에서 오류 처리: 초보자 가이드
안녕하세요, 젊은 프로그래머 여러분! C 프로그래밍의 fascinatng 세상에 환영합니다. 오늘 우리는 더 robust하고 reliable한 코드를 작성하는 데 도움이 되는 중요한 주제를 탐구할 것입니다: 오류 처리. 코드를 한 줄도 작성해본 적이 없다면 걱정하지 마세요 - 저는 여러분을 단계별로 안내해 드릴 것입니다. 수년 동안 수많은 학생들을 가르쳐온 경험을 바탕으로 말입니다. 그럼 좋아하는 음료를 한 잔 챙겨서 함께 빠져들어 보겠습니다!
오류 처리란?
구체적인 내용에 들어가기 전에, 오류 처리가 무엇인지 이해해 보겠습니다. 생각해 보세요. 여러분이 케이크를 만들고 있을 때, 실수로 소금 대신 설탕을 사용하게 되면 어떤 일이 일어날까요? 결과는 매우 불쾌할 것입니다, 아닌가요? 프로그래밍에서 오류는 잘못된 재료를 사용하는 것과 같습니다 - 프로그램이 예상치 못한 방식으로 동작하거나 심지어崩溃할 수 있습니다. 오류 처리는 이러한 "잘못된 재료"를 감지하고 그것을 부드럽게 처리하는 우리의 방법입니다.
이제 C가 제공하는 다양한 오류 처리 도구를 탐구해 보겠습니다.
errno 변수
errno
변수는 C 프로그램에서 작은 전령사 같은 역할을 합니다. 무언가 잘못되었을 때, 그 오류 코드를 전달하여 무엇이 일어났는지 알려줍니다. <errno.h>
헤더 파일에서 정의되어 있으며, 사용하려면 이 헤더 파일을 프로그램에 포함시켜야 합니다.
다음은 간단한 예제입니다:
#include <stdio.h>
#include <errno.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (file == NULL) {
printf("Error opening file: %d\n", errno);
}
return 0;
}
이 코드에서 우리는 존재하지 않는 파일을 열려고 시도하고 있습니다. fopen
이 실패하면 errno
에 특정 값을 설정합니다. 그런 다음 우리는 이 값을 출력합니다.
이 프로그램을 실행하면 다음과 같은 출력을 볼 수 있습니다:
Error opening file: 2
숫자 2는 "No such file or directory"라는 오류 코드입니다. 다른 오류는 다른 코드를 가지고 있습니다. 이제 다음 도구로 넘어가겠습니다...
perror() 함수
오류 코드는 유용하지만, 사람에게 친절하지는 않습니다. 여기서 perror()
가 등장합니다. 오류 코드를 읽기 쉬운 메시지로 변환하는 역할을 합니다.
이전 예제를 수정해 보겠습니다:
#include <stdio.h>
#include <errno.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (file == NULL) {
perror("Error opening file");
}
return 0;
}
이제 실행하면 다음과 같은 출력을 볼 수 있습니다:
Error opening file: No such file or directory
이렇게 하면 훨씬 더 좋습니다, 아닌가요? perror()
는 자동으로 errno
의 값을 사용하여 적절한 오류 메시지를 생성합니다.
strerror() 함수
때로는 오류 메시지를 문자열로 가져와서 자신의 커스텀 오류 처리에서 사용하고 싶을 수 있습니다. 그때는 strerror()
함수가 유용합니다. 이 함수는 <string.h>
에서 정의됩니다.
다음은 그 사용법입니다:
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (file == NULL) {
printf("Custom error message: %s\n", strerror(errno));
}
return 0;
}
이/output:
Custom error message: No such file or directory
ferror() 함수
이제 파일 연산에 대해 이야기해 보겠습니다. 파일을 읽거나 쓰는 중에 오류가 발생할 수 있습니다. ferror()
함수는 이러한 오류를 감지하는 데 도움이 됩니다.
다음은 예제입니다:
#include <stdio.h>
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
char c;
while ((c = fgetc(file)) != EOF) {
putchar(c);
}
if (ferror(file)) {
printf("An error occurred while reading the file.\n");
}
fclose(file);
return 0;
}
이 예제에서 우리는 파일을 문자 단위로 읽고 있습니다. 읽기를 마친 후, ferror()
를 사용하여 읽는 중에 오류가 발생했는지 확인합니다.
clearerr() 함수
때로는 파일 스트림의 오류 인디케이터를 지우고 싶을 수 있습니다. 그때는 clearerr()
함수가 도움이 됩니다. 파일 스트림에게 새로운 시작을 주는 것 같은 느낌입니다.
다음은 그 사용법입니다:
#include <stdio.h>
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
// 파일의 끝을 넘어 읽는 것을 시뮬레이션하여 오류를 발생시킵니다.
fseek(file, 0, SEEK_END);
fgetc(file);
if (ferror(file)) {
printf("An error occurred.\n");
clearerr(file);
printf("Error indicator cleared.\n");
}
if (!ferror(file)) {
printf("No error indicator set.\n");
}
fclose(file);
return 0;
}
이 예제에서 우리는 파일의 끝을 넘어 읽는 것을 시도하여 인위적으로 오류를 발생시킵니다. 그런 다음 clearerr()
를 사용하여 오류 인디케이터를 지웁니다.
제로로 나누기 오류
마지막으로, 수학과 프로그래밍에서 흔히 발생하는 오류에 대해 이야기해 보겠습니다: 제로로 나누기. C에서 제로로 나누기는 기본적으로 오류를 던지지 않지만, 정의되지 않은 동작을 유발할 수 있습니다.
다음은 그 처리 방법입니다:
#include <stdio.h>
int safe_divide(int a, int b, int *result) {
if (b == 0) {
return -1; // 제로로 나누기 오류 코드
}
*result = a / b;
return 0; // 성공
}
int main() {
int a = 10, b = 0, result;
int status = safe_divide(a, b, &result);
if (status == -1) {
printf("Error: Division by zero!\n");
} else {
printf("%d / %d = %d\n", a, b, result);
}
return 0;
}
이 예제에서 우리는 safe_divide
함수를 만들어 제로로 나누기 전에 체크합니다. 만약 b가 zero라면, 오류 코드를 반환합니다.
요약
오류 처리 방법을 요약해 보겠습니다:
방법 | 설명 |
---|---|
errno | 오류 코드를 저장하는 변수 |
perror() | 설명적인 오류 메시지를 출력합니다 |
strerror() | 오류 코드를 설명하는 문자열을 반환합니다 |
ferror() | 스트림에서 오류가 발생했는지 확인합니다 |
clearerr() | 스트림의 오류 인디케이터를 지웁니다 |
커스텀 함수 | 특정 경우에 맞는 오류 처리를 작성합니다 |
좋은 오류 처리는 운전 중 안전벨트를 착용하는 것과 같습니다 - 대부분의 시간에는 불필요할 수 있지만, 문제가 발생했을 때는 기쁜 마음으로 감사하게 됩니다. C 프로그래밍의 여정을 계속하면서, 항상 오류 처리를 염두에 두십시오. 이는 프로그램을 더 robust하고 사용자 친화적으로 만듭니다.
미래의 프로그래머 여러분, 행복하게 코딩하세요! 그리고 프로그래밍에서도 실생활에서도, 오류는 실패가 아니라 배울 수 있는 기회입니다. 오류를 받아들이고 처리하고 계속 코딩하십시오!
Credits: Image by storyset