프로그래밍기초 6주차
04.11 주제: 제어문
제어문
1. 분기문
- if ~ else if ~ else
- switch ~ case
2. 반복문
- for (횟수를 알고 있는 경우)
- while (조건만 아는 경우)
- do ~ while (조건만 아는 경우)
- 무한 반복문
3. 보조 제어문
- break
- continue
- return
- goto
goto
- 특정한 라인으로 이동하는 보조 제어문
- 코드흐름을 파악하기가 어려워 사용 지양
과제
1. InfiniteLoop.c
#include<stdio.h>
#include<stdbool.h>
#define TERMINATE_SIGNAL -1
#define IGNORE_EVENT 0
#define NORMAL_EVENT 1
// 2. 함수 선언(Prototype)
void service_loop();
int get_system_event();
void process_event(int event);
int main() {
service_loop();
return 0;
}
// 3. 메인 로직 (서비스 루프)
void service_loop() {
bool is_running = true;
while (is_running) {
int event = get_system_event();
if (event == TERMINATE_SIGNAL) {
is_running = false; // 루프 종료
printf("서비스가 종료됩니다.\n");
continue;
}
if (event == IGNORE_EVENT) {
printf("무시된 이벤트가 발생했습니다.\n");
continue; // 다음 이벤트로 넘어감
}
// IGNORE_EVENT는 무시
process_event(event); // 이벤트 처리
}
printf("서비스 루프가 종료되었습니다.\n");
}
// 4. 함수 구현 (이 부분이 업승면 LNK2019 발생)
int get_system_event() {
// 실제 시스템 이벤트를 가져오는 로직이 여기에 들어가야 합니다.
// 예시로, 무작위 이벤트를 반환하도록 하겠습니다.
static int count = 0;
count++;
if (count > 3) return TERMINATE_SIGNAL; // 4번째 이벤트부터 종료 신호 반환
return NORMAL_EVENT; // 정상 이벤트 반환
}
void process_event(int event) {
// 이벤트 처리 로직이 여기에 들어가야 합니다.
printf("이벤트 %d가 처리되었습니다.\n", event);
}
2. SwitchCase.c
#include<stdio.h>
#include<stdarg.h>
#include<time.h>
typedef enum {
STATE_IDLE,
STATE_CONNECTING,
STATE_CONNECTED,
STATE_ERROR
} SystemState;
void handle_state(SystemState current_state);
void log_error(const char* format, ...);
int main()
{
handle_state(STATE_ERROR);
return 0;
}
void handle_state(SystemState current_state) {
switch (current_state) {
case STATE_IDLE:
//대기 상태 로직
break;
case STATE_CONNECTING:
//연결 중 로직
break;
case STATE_CONNECTED:
//연결 완료 로직
break;
default:
//알 수 없는 상태 처리
log_error("Unknown State");
break;
}
}
void log_error(const char* format, ...) {
// 1. 현재 시간 정보 휙득
time_t now = time(NULL);
char time_str[32] = { 0 };
struct tm t_struct;
if (localtime_s(&t_struct, &now) == 0) {
if (strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &t_struct) == 0) {
snprintf(time_str, sizeof(time_str), "Failed to format time");
}
}
else {
// 시간 휙득 실패 시 별도의 에러 메시지나 대체 텍스트 처리
snprintf(time_str, sizeof(time_str), "Failed to get time");
}
//2. 로그 헤더 출력 (시간 및 레벨)
fprintf(stderr, "[%s] ERROR: ", time_str);
//3. 가변 인자 처리 및 로그 메시지 출력
va_list args;
va_start(args, format); // 가변 인자 리스트 초기화
vfprintf(stderr, format, args); // 가변 인자 리스트를 사용하여 포맷된 메시지 출력
va_end(args); // 가변 인자 리스트 정리
fprintf(stderr, "\n"); // 로그 메시지 끝에 줄바꿈 추가
}
3. GotoCleanupReturn.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//에러 코드 정의
#define SUCCESS 0
#define ERR_FILE_OPEN -1
#define ERR_INVALID_DATA -2
#define ERR_READ_FAILED -3
//함수 프로토타입 선언
int is_file_valid(FILE* fp);
int do_main_work(FILE* fp);
int process_file(const char* filename);
int main(int argc, char* argv[]) {
const char* target_file = "data.txt"; // 처리할 파일 이름
printf("파일 처리 시작: %s\n", target_file);
int status = process_file(target_file);
if(status == SUCCESS) {
printf("파일 처리가 성공적으로 완료되었습니다.\n");
} else {
printf("파일 처리 중 오류가 발생했습니다. 에러 코드: %d\n", status);
}
return 0;
}
int process_file(const char* filename) {
int result = SUCCESS;
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
perror("Error opening file");
return ERR_FILE_OPEN; // 파일 열기 실패
}
if (!is_file_valid(fp)) {
result = ERR_INVALID_DATA; // 파일 데이터가 유효하지 않음
goto cleanup; // 에러 발생 시 cleanup으로 이동
}
result = do_main_work(fp);
cleanup:
if (fp != NULL) {
printf("파일을 닫습니다.\n");
fclose(fp); // 파일 닫기
}
return result; // 최종 결과 반환
}
int is_file_valid(FILE* fp) {
rewind(fp);
int first_char = fgetc(fp);
if (first_char == EOF || !isdigit(first_char)) {
fprintf(stderr, "파일이 비어있거나 유효하지 않은 데이터가 포함되어 있습니다.\n");
return 0; // 파일이 유효하지 않음
}
return 1; // 파일이 유효함
}
int do_main_work(FILE* fp) {
char buffer[1024];
rewind(fp);
printf("파일에서 데이터를 읽고 처리합니다...\n");
while (fgets(buffer, sizeof(buffer), fp) != NULL)
{
// 각 줄의 데이터를 처리하는 로직 (예: 숫자 추출 및 계산)
printf("읽은 데이터: %s", buffer);
}
if (ferror(fp)) {
perror("Error reading file");
return ERR_READ_FAILED; // 파일 읽기 실패
}
return SUCCESS; // 성공적으로 처리됨
}