iT邦幫忙

2021 iThome 鐵人賽

DAY 7
1

昨天做輸出系統的時候,發現輸出Vector2這樣常見的結構,沒有一個通用的函式直接轉成字串。再往回看,好像沒有做過Log功能欸,雖然直接使用printf也可以,但既然都要重頭開始了,那就做出一個簡單的log功能吧~!

今日目標

  • Log功能

先來看看printf

int printf( const char* format, ... )

最開始學的時候就很好奇,為什麼C語言的功能很簡單(相對其他語言),但printf可以帶這麼多參數進去,之前沒想那麼多,想說能用就好了,今天就趁這個機會來解析一下到底是做了甚麼,而這個秘密就在那個...裡面。

那個叫做Variadic functions(我不知道中文怎麼翻),它可以讓我們N個參數,那要怎麼讓函式變成可以有N個參數呢?答案就在stdarg.h的腳本裡面。

其中:

  • va_list: 是儲存任意複數結構的一個list
  • va_start: 第一個參數表示cursor從哪個參數開始,他會往下讀
  • va_end: 最後用完va_list要自己回收

之後就可以用這三個,寫出一個極簡單的Log功能

void LogMessage(LogT log_type, const char* file_name, int line, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);

    fprintf(stdout, "%s %s:%d ", LOG_LABELS[log_type], file_name, line);
    vfprintf(stdout, fmt, args);
    fprintf(stdout, "\n");

    va_end(args);
}

上面的va_start就等於是,從參數列fmt開始,讀後面開始的任意得參數。

可以看到著函式還要印出「哪個文件」和「第幾行開始」,這就可以簡單的用上C語言內建的marco:

 __FILE__、__LINE__

直接把相對的把這個功能做出來。

然後再依靠LogMessage,改成macro function,最後就可以做出不同階級的log囉

#define LogInfo(...) LogMessage(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__);
#define LogWarning(...) LogMessage(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__);
#define LogError(...) LogMessage(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__);

至於macro function中的...跟__VA_ARGS__(注意: 是兩條底線喔),是甚麼呢?
__VA_ARGS__是個macro,等於這個函式任意任數量的參數,簡單來說,上面的code就表示

... == (const char* fmt, ...)

參考

最後這是今天的成果


上一篇
[Day6] 初見輸入系統
下一篇
[Day 8] 2D世界中的數學 (一)
系列文
翻車機率極高的2D平台遊戲(2D Platformer)製作33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言