C Academy · Lektion

Praktiske eksempler

En logging-funktion

Lektion 4 af 413 trin

Praktiske eksempler er en gratis C Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C Academy-kurset indeholder 4 lektioner i alt.

En logfunktion

En logger er den perfekte praktiske anvendelse af variadiske argumenter. Vi vil kunne kalde log_msg("user %s scored %d", name, score) ligesom printf.

Denne lektion bygger et lille, nyttigt logningsværktøj.

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

Tilføjelse af et alvorlighedsniveau

Rigtige loggere mærker meddelelser med et niveau som INFO eller ERROR. Tilføj en fast parameter før formatstrengen til niveauet.

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

Tilføjelse af tidsstempler til meddelelser

Du kan berige hver linje med ekstra kontekst, før formatet videresendes. Her sætter vi en opdigtet tæller foran som erstatning for et tidsstempel.

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

Logning til stderr

Fejl og diagnosticering sendes normalt til stderr. Brug vfprintf(stderr, fmt, args), så logoutputtet ikke blandes med programmets normale output.

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

Betinget logning

En grænse for detaljeringsgraden gør det muligt at undertrykke meddelelser med lav prioritet. Sammenlign meddelelsens niveau med et konfigureret minimum, før du udskriver den.

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

Opbygning af en meddelelsesstreng

Nogle gange vil du have den formaterede tekst i en buffer i stedet for at udskrive den. Brug vsnprintf til at gengive den, og beslut derefter, hvad der skal ske.

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

En variadisk max-funktion

Variadiske argumenter fungerer også til matematiske hjælpefunktioner. Her er en funktion, der returnerer det største af flere heltal ved hjælp af en tælleparameter.

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

Sammenkædning af strenge

Ved at bruge en NULL-sentinel kan vi samle et vilkårligt antal strenge i én buffer.

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

Optælling af variadiske heltal

En tæller baseret på en sentinel viser, hvor fleksibel metoden er. Vi tæller værdier, indtil vi rammer et afsluttende 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;
}

Indpakning som en makro

Et almindeligt trick er en makro, der automatisk udfylder niveauet, så kalderne skal skrive mindre. Makroen videresender til den rigtige variadiske funktion.

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

Brug af loggeren

Her er en komplet mini-logger, der kombinerer et niveau og en tidsstempeltæller, og som er klar til at blive føjet ind i et program.

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

Hurtigt tjek

Test din forståelse af design af variadisk logning.

Opsummering

Du har bygget praktiske variadiske værktøjer:

  • En logger, der videresender sit format til vprintf/vfprintf.
  • Du har tilføjet niveauer, tællere, stderr-output og betinget filtrering.
  • Du har brugt vsnprintf til at gemme meddelelser i buffere.
  • Du har set sentinelbaserede hjælpefunktioner og en praktisk makro-wrapper.
Gratis at komme i gang

Lær C med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
39
Lektioner
144

Ofte stillede spørgsmål

Er lektionen “Praktiske eksempler” gratis?

Ja — hele teksten til “Praktiske eksempler” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C Academy-kurset, skal du opgradere til CoddyKit PRO. C Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Praktiske eksempler”?

En logging-funktion Du øver dig i C Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C Academy?

Der kræves ingen tidligere erfaring. C Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.

Hvor lang tid tager lektionen “Praktiske eksempler”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C Academy-lektion?

Ja. Alle C Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. stdarg-makroerne
  2. Skriv printf-lignende funktioner
  3. Problemer med typesikkerhed
  4. Praktiske eksempler
← Tilbage til C Academy