平時寫**接觸最多函式大概就是 printf 函式了,printf 函式就是乙個可變引數函式,第2個引數就是可變引數,第乙個引數是格式化字串。格式化字串中的轉換修飾符決定了可變引數的數量和型別。
int printf (
const
char
*format,..
.)
可變引數函式(variadic function):函式引數變數可變的函式。可變參函式包括至少乙個強制引數(mandatory argument)+數量可變的可選引數(optional argument),強制性引數在前,可變引數用省略號(…)表示。
實現可變引數函式需要包含****標頭檔案,他提供需要用到的下列巨集定義:
typedef
char
* va_list;
void
va_start
(va_list argptr, lastparam)
; type va_arg
(va_list argptr, type)
;void
va_end
(va_list argptr)
;void
va_copy
(va_list dest, va_list src)
;
第一步:定義函式,並用這個型別定義乙個變數:
int
m_printf
(const
char
*f_str,..
.)
第2步:用va_start初始化 p_list變數。format為printf函式的第乙個引數。
int
m_printf
(const
char
*f_str,..
.)
第3步:用va_arg獲取可變參引數的值。根據引數型別,type需要設定為不同的型別。
int
m_printf
(const
char
*f_str,..
.)
最後一步呼叫va_end完成清理工作。
int
m_printf
(const
char
*f_str,..
.)
/* num:表示可變引數的數量 */
intadd
(int num,..
.)va_end
(p_list)
;return sum;
}void
add_t
(void
)
printf函式的格式化輸出是使用百分號%
控制輸出的格式。printf第乙個引數是格式化字串,所以需要解析這個字串,然後根據不同的輸出格式輸出對應字元。最終呼叫putc()
等類似函式輸出乙個個字元。
控制符說明%d
十進位制整型資料
%mdm 為指定的輸出欄位的寬度。如果資料的位數小於 m,則左端補以空格,若大於 m,則按實際位數輸出。
%0md
m 為指定的輸出欄位的寬度。如果資料的位數小於 m,則左端補以0,若大於 m,則按實際位數輸出。
%x十六進製制整形資料
%c輸出乙個字元
%s輸出字串
乙個整形數值可以按照下面的**轉換為十進位制字串:
int value=
1234
;char buff[32]
;char ch;
buff[31]
=0;int index =30;
while
(value!=0)
上面**的ch = value % 10 + '0';
還可以簡單的改為下面的**:
static
const
char hex=
"0123456789abcdef";.
....
. ch = hex[value %10]
;
int value=
1234
;char buff[32]
;char ch;
buff[31]
=0;int index =30;
while
(value!=0)
上面**的ch = value % 10 + '0';
還可以簡單的改為下面的**:
static
const
char hex=
"0123456789abcdef";.
....
. ch = hex[value %16]
;
轉16進製制字串的**實現和10進製類似,不同的只是求餘和除法的10和16;
int value=
1234
;char buff[32]
;char ch;
buff[31]
=0;int index =30;
static
const
char hex=
"0123456789abcdef"
;while
(value!=0)
#define ary 10
/* 不同數值表示不同的進製 */
int value=
1234
;char buff[32]
;char ch;
buff[31]
=0;int index =30;
static
const
char hex=
"0123456789abcdef"
;while
(value!=0)
輸出指定寬度的數值時需要將字串轉為10進製數值,%md
其中的m,可以是字串123或者10等,實現**如下所示:
int width =0;
char fmt=
"123"
;char
*p = fmt;
while((
*p>=
'1')&&(
*p<=
'9')
)printf
("width=%d"
,width)
;
輸出乙個字元的**實現就很簡單了,printf最終也是也是呼叫字元輸出函式將字串輸出。
/* 實現迷你printf函式 */
void
put_str
(char
* str)
}#define buff_size 32
intm_printf
(const
char
*fmt,..
.);/* 緩衝區 */
static
const
char hex=
"0123456789abcdef"
; va_list p_args;
va_start
(p_args,fmt)
;while
(*fmt !=
'\0'
)else
while((
*fmt >=
'1')&&(
*fmt <=
'9')
)switch
(*fmt)
/* int 型數字轉為十進位制字串 */
while
(value !=0)
/* 負數新增負號 */
if(temp <0)
fmt++
;break
;case
'x':
case
'x':
value_x =
va_arg
(p_args,
unsigned
int)
;/* 數值轉16進製制字串 */
while
(value_x !=0)
buff[index--]=
'x';
/* 新增 0x 字首 */
buff[index--]=
'0';
width -=2
; fmt++
;break
;default
:break;}
/* 按照指定寬度填充字元0或者空格,width可能為負數 */
if(width >0)
}if(index !=30)
/* 輸出格式化字串 */
}else
/* 直接輸出字元 */
}va_end
(p_args)
;return length;
}/* 函式功能測試 */
void
test_m
(void
)
自己動手用c 寫控制項(下)
自己動手用c 寫控制項 下 因為我們這個控制項是實現背景漸變及文字填充,所以override paint事件以完成自畫。為了完成override,現在以下的準備工作 寫幾個在paint事件用的著的事件 使用角度的方法漸近重畫button private void drawbuttonwithangl...
自己動手用C擴充套件PHP(二)
在上一章裡我們介紹了如何編寫自己的函式,接下來,我們開始編寫乙個有引數有返回值的擴充套件函式。因為zend沒有正式的函式呼叫語法檢查支援,所以我們在編寫擴充套件函式的時候必須得 小心 也就是我們必須得嚴格地進行呼叫合法性檢查。首先,我們寫乙個函式 include string.h php funct...
自己動手用C擴充套件PHP(三)
在上兩章裡講述了擴充套件模組的基本用法,相信讀者已經能夠構建自己的擴充套件模組了,接下來,我們來看看幾個重要的函式 1 php minit function mymodule 當模組被zend engine ze 載入後,例如apache啟動,載入了php模組,ze會對每乙個擴充套件模組呼叫此函式 ...