首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言入門

C語言可變參實現 scanf 封裝:myscanf(fmt, ...) 核心代碼解析

     編輯:C 語言入門

既然 printf 族函數可通過可變參實現,scanf 族同理。本文展示基於 vscanf 的 myscanf 封裝實現,揭示輸入函數可變參轉發的核心機制。

核心代碼

#include 
#include 

int myscanf(const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    
    // vscanf 是 scanf 的可變參版本,接收 va_list
    int ret = vscanf(fmt, ap);
    
    va_end(ap);
    return ret;
}

int main() {
    int num;
    printf("pls input num:\n");
    myscanf("%d", &num);  // 透傳格式字符串與地址參數
    printf("num: %d\n", num);
    return 0;
}

運行演示

pls input num:
100
num: 100

關鍵機制解析

轉發模式範式

// 通用封裝模板
int wrapper_scanf(const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    int ret = vscanf(fmt, ap);  // 或 vfscanf/vsscanf
    va_end(ap);
    return ret;
}

為什麼需要 v* 系列函數?

  1. 二次封裝:自定義格式檢查、日誌記錄、參數預處理後再調用標準掃描。
  2. 避免可變參傳遞開銷:內部實現直接操作 va_list,無需再次展開。
  3. 線程安全上下文:某些實現中 va_list 可跨函數傳遞而不複製棧幀。

注意事項

  • vscanf 等函數屬於 C99 標準,現代編譯器(GCC、Clang、MSVC)均支持。
  • 格式字符串 fmt 與後續參數必須嚴格匹配,否則未定義行為(如 %d 對應 float*)。
  • 返回值:成功賦值的項目數,EOF 表示輸入失敗/結束。

對比:printf 族與 scanf 族的可變參對應關係

printf   -> vprintf   (stdout)
fprintf  -> vfprintf  (FILE*)
sprintf  -> vsprintf  (char* buffer)
snprintf -> vsnprintf (char* buffer, size_t)

scanf    -> vscanf    (stdin)
fscanf   -> vfscanf   (FILE*)
sscanf   -> vsscanf   (const char* buffer)

理解 vscanf 等核心函數的存在意義,能讓你在需要自定義輸入解析邏輯(如協議解析、配置文件讀取、測試框架斷言)時,靈活構建類 scanf 的 DSL 接口。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
函數參數類型說明
scanf(const char*, ...)標準掃描,可變參
vscanf(const char*, va_list)接收預打包的 va_list,核心實現
fscanf(FILE*, const char*, ...)文件流掃描
vfscanf(FILE*, const char*, va_list)文件流可變參核心
sscanf(const char*, const char*, ...)字符串掃描
vsscanf(const char*, const char*, va_list)字符串可變參核心