0Pricing
C Academy · Lekcja

Praktyczne przykłady

Funkcja logująca

Praktyczne przykłady to bezpłatna lekcja C Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C Academy zawiera 4 lekcji w sumie.

Funkcja logująca

Logger to doskonałe praktyczne zastosowanie argumentów wariadycznych. Chcemy wywoływać log_msg("user %s scored %d", name, score) tak jak printf.

W tej lekcji zbudujesz małe, przydatne narzędzie do logowania.

#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;
}

Dodawanie poziomu ważności

Rzeczywiste loggery oznaczają komunikaty poziomem, takim jak INFO lub ERROR. Dodaj stały parametr przed napisem formatującym, który określa poziom.

#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;
}

Dodawanie znaczników czasu do komunikatów

Każdy wiersz można wzbogacić o dodatkowy kontekst przed przekazaniem formatu dalej. W tym przykładzie jako zamiennika znacznika czasu użyjemy fikcyjnego licznika umieszczanego na początku.

#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;
}

Logowanie do stderr

Błędy i informacje diagnostyczne zwykle trafiają do stderr. Użyj vfprintf(stderr, fmt, args), aby dane dziennika nie mieszały się ze standardowym wyjściem programu.

#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;
}

Warunkowe logowanie

Próg szczegółowości pozwala wyciszyć komunikaty o niskim priorytecie. Przed wypisaniem porównaj poziom komunikatu ze skonfigurowanym minimum.

#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;
}

Budowanie napisu komunikatu

Czasami sformatowany tekst powinien trafić do bufora, a nie na wyjście. Użyj vsnprintf, aby go utworzyć, a następnie zdecyduj, co z nim zrobić.

#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;
}

Wariadyczna funkcja max

Argumenty wariadyczne sprawdzają się również w pomocniczych funkcjach matematycznych. Oto funkcja, która zwraca największą spośród kilku liczb całkowitych, korzystając z parametru z liczbą argumentów.

#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;
}

Łączenie napisów

Korzystając z wartownika NULL, można połączyć dowolną liczbę napisów w jeden bufor.

#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;
}

Zliczanie liczb całkowitych wariadycznych

Licznik oparty na wartowniku pokazuje elastyczność tego schematu. Zliczamy wartości aż do napotkania kończącego 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;
}

Opakowywanie w makro

Popularnym sposobem jest makro, które automatycznie uzupełnia poziom, dzięki czemu wywołujący musi pisać mniej. Makro przekazuje argumenty do właściwej funkcji wariadycznej.

#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;
}

Korzystanie z loggera

Oto kompletny mini-logger łączący poziom i licznik znaczników czasu, gotowy do dodania do programu.

#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;
}

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat projektowania logowania wariadycznego.

Podsumowanie

Zbudowałeś praktyczne narzędzia wariadyczne:

  • Logger, który przekazuje swój format do vprintf/vfprintf.
  • Dodawanie poziomów, liczników, wyjścia stderr i filtrowania warunkowego.
  • Używanie vsnprintf do zapisywania komunikatów w buforach.
  • Pomocnicze funkcje oparte na wartownikach oraz wygodne opakowanie w postaci makra.

Często zadawane pytania

Czy lekcja „Praktyczne przykłady” jest bezpłatna?

Tak — pełny tekst „Praktyczne przykłady” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C Academy, przejdź na CoddyKit PRO. Kurs C Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Praktyczne przykłady”?

Funkcja logująca Ćwiczysz C Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C Academy?

Nie wymagamy żadnego doświadczenia. C Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Praktyczne przykłady”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C Academy?

Tak. Każda lekcja C Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Makra stdarg
  2. Pisanie funkcji podobnych do printf
  3. Problemy z bezpieczeństwem typów
  4. Praktyczne przykłady
← Powrót do C Academy