通過《C程序設計語言》第二版第7章的介紹,我們知道標題準確翻譯或許是“變長變元表”,這個無可厚非,我們只要知道我們要編寫一個函數參數個數不確定的函數,如何編寫?
形式:
int printf(char *fmt, ...);
從形式上出發,我們需要處理的部分是”…”。
這部分的處理,我們可以這樣設計:
首先“…”表示的是一個變元表,這個表我們可以理解成是一個鏈表,對於鏈表的處理,我們往往需要一個指針指向當前元素。變元表的遍歷可以採用鏈表的遍歷思路。
1.獲得變元表的開始位置
2.獲得當前位置的元素值,並且位置+1處理
3.循環執行步驟2,直到變元表結束
這裏有個問題,我們並不知道,變元表的結束位置。也就是說,我們必須知道我們的變元表的元素個數,這樣上面的設計思路才能實施,假設我們知道變元表中的元素個數,這也是編寫變長變元表的前提。
我們現在使用文件 stdarg.h 文件中函數,實現變元表的處理:
va_list: 用於定義變元變量指針
va_start:初始化變元變量指針
va_end:釋放處理過程中的資源
va_arg:獲得當前變元變量指針對應的值(依賴數據類型),並且+1變元變量的指針值
從這個設計我們可以看出,對於表的處理,基本上就是“定界遍歷”這樣的方式。這些都是基本的遍歷思想。我們從這裏也明白,對於計算機的理解要建立在最基礎的理解方式上面,因爲,這樣的理解是深刻的,沒有特殊的元素在這裏面,都是些基本的設計理念。
一個簡單的例子:
/*************************************************************************
> File Name: main.c
> Author: mhsheng
> Mail:[email protected]
> Created Time: Mon 14 Nov 2016 03:14:04 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void
minprintf(char *fmt, ...)
{
va_list ap;
char *p;
int iVal;
double dVal;
va_start(ap, fmt);
for (p=fmt; *p!='\0'; ++p) {
if (*p != '%') {
putchar(*p);
continue;
}
++p;
switch (*p) {
case 'd':
iVal = va_arg(ap, int);
printf("%d", iVal);
break;
case 'f':
dVal = va_arg(ap, double);
printf("%f", dVal);
break;
default:
break;
}
}
va_end(ap);
}
int
main(int argc, char **argv)
{
minprintf("%d, %f\n", 13, 0.12);
exit(0);
}