自己動手用C語言實現迷你printf函式

2021-09-28 17:39:20 字數 4806 閱讀 6963

平時寫**接觸最多函式大概就是 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會對每乙個擴充套件模組呼叫此函式 ...