C Academy · 강의

실전 예제

로깅 함수를 작성합니다

레슨 4/413개 단계

실전 예제은(는) CoddyKit의 무료 C Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

로깅 함수

로거는 가변 인수를 실제로 활용하기에 가장 좋은 예입니다. printf처럼 log_msg("user %s scored %d", name, score)를 호출하고 싶다고 해 보겠습니다.

이 레슨에서는 작지만 유용한 로깅 도구를 만듭니다.

#include <stdio.h>
#include <stdarg.h>

void log_msg(const char *fmt, ...) {
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
    printf("\n");
}

int main(void) {
    log_msg("user %s scored %d", "Ann", 90);
    return 0;
}

심각도 수준 추가하기

실제 로거는 INFO나 ERROR 같은 수준으로 메시지에 레이블을 붙입니다. 형식 문자열 앞에 수준을 위한 고정 매개변수를 추가하세요.

#include <stdio.h>
#include <stdarg.h>

void logf(const char *level, const char *fmt, ...) {
    printf("[%s] ", level);
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
    printf("\n");
}

int main(void) {
    logf("INFO", "started with %d workers", 4);
    return 0;
}

메시지에 타임스탬프 추가하기

형식을 전달하기 전에 각 줄에 추가 정보를 넣어 내용을 보강할 수 있습니다. 여기서는 타임스탬프를 대신해 가상의 카운터를 앞에 붙입니다.

#include <stdio.h>
#include <stdarg.h>

static int line_no = 0;

void logf(const char *fmt, ...) {
    printf("#%d ", ++line_no);
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
    printf("\n");
}

int main(void) {
    logf("first %s", "event");
    logf("value %d", 7);
    return 0;
}

stderr에 로깅하기

오류와 진단 메시지는 보통 stderr로 보냅니다. vfprintf(stderr, fmt, args)를 사용하면 로그 출력이 일반 프로그램 출력과 섞이지 않습니다.

#include <stdio.h>
#include <stdarg.h>

void err(const char *fmt, ...) {
    fprintf(stderr, "ERROR: ");
    va_list a; va_start(a, fmt);
    vfprintf(stderr, fmt, a);
    va_end(a);
    fprintf(stderr, "\n");
}

int main(void) {
    err("failed to open %s", "data.txt");
    return 0;
}

조건부 로깅

출력 수준의 임계값을 사용하면 우선순위가 낮은 메시지를 표시하지 않을 수 있습니다. 출력하기 전에 메시지 수준을 설정된 최솟값과 비교하세요.

#include <stdio.h>
#include <stdarg.h>

static int min_level = 2;

void logf(int level, const char *fmt, ...) {
    if (level < min_level) return;
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
    printf("\n");
}

int main(void) {
    logf(1, "debug hidden");
    logf(3, "important %d", 42);
    return 0;
}

메시지 문자열 만들기

때로는 형식이 지정된 텍스트를 출력하지 않고 버퍼에 저장하고 싶을 수 있습니다. vsnprintf로 렌더링한 다음 처리 방법을 결정하세요.

#include <stdio.h>
#include <stdarg.h>

void capture(const char *fmt, ...) {
    char buf[128];
    va_list a; va_start(a, fmt);
    vsnprintf(buf, sizeof(buf), fmt, a);
    va_end(a);
    printf("captured: %s\n", buf);
}

int main(void) {
    capture("id=%d name=%s", 5, "box");
    return 0;
}

가변 인수 최댓값 함수

가변 인수는 수학 도우미 함수에도 사용할 수 있습니다. 여기서는 개수 매개변수를 사용해 여러 정수 중 가장 큰 값을 반환하는 함수를 만듭니다.

#include <stdio.h>
#include <stdarg.h>

int max_of(int count, ...) {
    va_list a; va_start(a, count);
    int best = va_arg(a, int);
    for (int i = 1; i < count; i++) {
        int v = va_arg(a, int);
        if (v > best) best = v;
    }
    va_end(a);
    return best;
}

int main(void) {
    printf("%d\n", max_of(4, 3, 9, 2, 7));
    return 0;
}

문자열 연결하기

NULL 센티널을 사용하면 임의의 개수의 문자열을 하나의 버퍼로 연결할 수 있습니다.

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

void join(char *out, const char *first, ...) {
    out[0] = '\0';
    va_list a; va_start(a, first);
    const char *s = first;
    while (s) { strcat(out, s); s = va_arg(a, const char *); }
    va_end(a);
}

int main(void) {
    char buf[64];
    join(buf, "a", "b", "c", (char *)NULL);
    printf("%s\n", buf);
    return 0;
}

가변 인수 정수 세기

센티널 기반 카운터는 이 패턴이 얼마나 유연한지 보여 줍니다. 종료 0을 만날 때까지 값을 셉니다.

#include <stdio.h>
#include <stdarg.h>

int count_until_zero(int first, ...) {
    va_list a; va_start(a, first);
    int n = 0, v = first;
    while (v != 0) { n++; v = va_arg(a, int); }
    va_end(a);
    return n;
}

int main(void) {
    printf("%d\n", count_until_zero(5, 6, 7, 0));
    return 0;
}

매크로로 감싸기

호출자가 더 적게 작성하도록 수준을 자동으로 채우는 매크로를 사용하는 방법이 흔합니다. 이 매크로는 실제 가변 인수 함수로 전달합니다.

#include <stdio.h>
#include <stdarg.h>

void real_log(const char *lvl, const char *fmt, ...) {
    printf("[%s] ", lvl);
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
    printf("\n");
}

#define LOG_INFO(...) real_log("INFO", __VA_ARGS__)

int main(void) {
    LOG_INFO("ready in %d ms", 50);
    return 0;
}

로거 사용하기

수준과 타임스탬프 카운터를 결합한 완전한 미니 로거입니다. 프로그램에 바로 추가해 사용할 수 있습니다.

#include <stdio.h>
#include <stdarg.h>

static int seq = 0;

void mylog(const char *lvl, const char *fmt, ...) {
    printf("%04d [%s] ", ++seq, lvl);
    va_list a; va_start(a, fmt);
    vprintf(fmt, a);
    va_end(a);
    printf("\n");
}

int main(void) {
    mylog("INFO", "boot ok");
    mylog("WARN", "low memory: %d MB", 64);
    return 0;
}

빠른 확인

가변 인수 로깅 설계에 대한 이해도를 확인해 보세요.

복습

실용적인 가변 인수 도구를 만들었습니다.

  • 형식을 vprintf/vfprintf로 전달하는 로거
  • 추가한 수준, 카운터, stderr 출력, 조건부 필터링
  • vsnprintf를 사용해 메시지를 버퍼에 저장하기
  • 센티널 기반 도우미와 편의성을 위한 매크로 래퍼
무료로 시작

AI 튜터와 함께 C을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
39
레슨
144

자주 묻는 질문

“실전 예제” 강의는 무료인가요?

네 — “실전 예제” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C Academy 강의 전체를 잠금 해제할 수 있습니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“실전 예제”에서 뭘 배우나요?

로깅 함수를 작성합니다 브라우저에서 직접 실행하는 실습 코드로 C Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“실전 예제” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. stdarg 매크로
  2. printf 같은 함수 작성
  3. 타입 안전성 문제
  4. 실전 예제
← C Academy(으)로 돌아가기