C 語言日誌輸出與 log 函式完整指南:從基礎到進階應用

1. 前言

C 語言是一種廣泛應用於系統開發與嵌入式系統等多個領域的程式語言。特別是日誌輸出功能,可將程式行為可視化,是除錯與發現錯誤不可或缺的要素。本文將從 C 語言日誌的基礎開始,全面介紹高效日誌管理的方法。透過理解日誌輸出的基礎知識與應用技術,能夠有效運用於實際開發中。

2. 關於 C 語言的數學函式「log」

C 語言內建了數學計算的標準函式「log」。本節將說明 log 函式的概要與基本用法。

「log」函式的概要與用途

「log」函式定義於 C 語言的數學函式庫(math.h)中,用於計算自然對數(以 e 為底的對數)。它是統計分析與科學計算中常用的函式之一。

#include <math.h>
double result = log(10.0);  // 計算 10 的自然對數

自然對數與常用對數的差異

自然對數的底數是 e,而常用對數(底數為 10)則使用 log10 函式計算。

double result = log10(100.0);  // 計算 100 的常用對數

錯誤處理

如果向「log」函式傳入負數或 0,會發生錯誤,因此需要進行輸入檢查。

if (number > 0) {
    result = log(number);
} else {
    printf("請輸入正數\n");
}

3. C 語言日誌輸出的基礎

日誌輸出有助於檢視程式行為,並協助發現與解決問題。這裡將介紹使用標準輸出與檔案輸出的基本方法。

使用標準輸出的基本日誌輸出

使用標準輸出顯示日誌可透過 printf 完成。

#include <stdio.h>
int main() {
    printf("程式開始\n");
    int x = 5;
    printf("變數 x 的值: %d\n", x);
    return 0;
}

將日誌輸出到檔案

要將日誌記錄到檔案,可使用 fopen 開啟檔案,並用 fprintf 寫入。

#include <stdio.h>
int main() {
    FILE *logfile = fopen("log.txt", "w");
    if (logfile != NULL) {
        fprintf(logfile, "程式開始\n");
        fclose(logfile);
    } else {
        printf("建立日誌檔案失敗\n");
    }
    return 0;
}

4. 日誌等級的設定與管理

透過設定日誌等級,可依訊息的重要性控制輸出。以下為各等級的作用與實作範例。

日誌等級概要

  • DEBUG:詳細的除錯資訊
  • INFO:一般操作資訊
  • WARN:警告訊息
  • ERROR:錯誤訊息
  • FATAL:嚴重錯誤

依日誌等級控制輸出

#define LOG_LEVEL_DEBUG 0
#define LOG_LEVEL_INFO 1
#define LOG_LEVEL_WARN 2
int current_log_level = LOG_LEVEL_WARN;

void log_message(int level, const char *message) {
    if (level >= current_log_level) {
        printf("[%d] %s\n", level, message);
    }
}

5. 使用巨集提升日誌輸出效率

可透過巨集自動附加檔名與行號等資訊到日誌中。

#include <stdio.h>
#define LOG(level, message) printf("[%s] %s:%d - %s\n", level, __FILE__, __LINE__, message)

int main() {
    LOG("INFO", "程式開始");
    return 0;
}

6. 多執行緒環境下的日誌輸出

在多執行緒環境中,需要進行互斥控制以避免多執行緒同時輸出日誌造成競爭。可使用 pthread_mutex 實現互斥控制。

#include <stdio.h>
#include <pthread.h>

pthread_mutex_t log_mutex;

void log_message(const char *message) {
    pthread_mutex_lock(&log_mutex);
    FILE *logfile = fopen("log.txt", "a");
    if (logfile != NULL) {
        fprintf(logfile, "%s\n", message);
        fclose(logfile);
    }
    pthread_mutex_unlock(&log_mutex);
}

int main() {
    pthread_mutex_init(&log_mutex, NULL);
    log_message("來自執行緒的訊息");
    pthread_mutex_destroy(&log_mutex);
    return 0;
}

7. 使用外部函式庫進行日誌管理

透過 log4c 函式庫可更高階地管理日誌輸出。

log4c 的安裝與基本設定

log4c.rootCategory=INFO, R
log4c.appender.R=RollingFileAppender
log4c.appender.R.fileName=mylogfile.log
log4c.appender.R.layout=PatternLayout
log4c.appender.R.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

log4c 程式碼範例

#include <log4c.h>
int main() {
    log4c_init();
    log4c_category_t* mycat = log4c_category_get("mycategory");
    log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "程式開始");
    log4c_fini();
    return 0;
}

8. 總結

本文介紹了 C 語言日誌從基礎到進階的內容,包含基本輸出方式、日誌等級設定,以及外部函式庫的應用。透過適當的日誌管理,能提升程式的可靠性與維護性。希望讀者能將日誌功能應用於實際開發中,提升除錯效率並協助問題解決。

侍エンジニア塾