0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

標(biāo)準(zhǔn)C函數(shù)庫(kù)的用法

PoisonApple ? 來(lái)源:網(wǎng)絡(luò)整理 ? 2018-03-02 11:27 ? 次閱讀

C標(biāo)準(zhǔn)函數(shù)庫(kù)

C標(biāo)準(zhǔn)函數(shù)庫(kù)是所有符合標(biāo)準(zhǔn)的頭文件的集合,以及常用的函數(shù)庫(kù)實(shí)現(xiàn)程序,例如I/O 輸入輸出和字符串控制。不像 COBOL、Fortran 和 PL/I等編程語(yǔ)言,在 C 語(yǔ)言的工作任務(wù)里不會(huì)包含嵌入的關(guān)鍵字,所以幾乎所有的 C 語(yǔ)言程序都是由標(biāo)準(zhǔn)函數(shù)庫(kù)的函數(shù)來(lái)創(chuàng)建的。

每一個(gè)函數(shù)的名稱與特性會(huì)被寫成一個(gè)電腦文件,這個(gè)文件就稱為頭文件,但是實(shí)際的函數(shù)實(shí)現(xiàn)是被分存到函數(shù)庫(kù)文件里。頭文件的命名和領(lǐng)域是很常見(jiàn)的,但是函數(shù)庫(kù)的組織架構(gòu)也會(huì)因?yàn)椴煌木幾g器而有所不同。標(biāo)準(zhǔn)函數(shù)庫(kù)通常會(huì)隨附在編譯器上。因?yàn)?C 編譯器常會(huì)提供一些額外的非 ANSI C 函數(shù)功能,所以某個(gè)隨附在特定編譯器上的標(biāo)準(zhǔn)函數(shù)庫(kù),對(duì)其他不同的編譯器來(lái)說(shuō),是不兼容的。

標(biāo)準(zhǔn)C函數(shù)庫(kù)的用法

本篇介紹若干常用的標(biāo)準(zhǔn)C函數(shù)的用法,主要介紹stdio(標(biāo)準(zhǔn)輸入輸出)、math(數(shù)字函數(shù)庫(kù))、time(時(shí)間函數(shù)庫(kù))、stdlib(標(biāo)準(zhǔn)函數(shù)庫(kù))string(標(biāo)準(zhǔn)字符串函數(shù))等。

1.1 stdio.h

標(biāo)準(zhǔn)輸入/輸出函數(shù),stdio即standard input/output。其中文件操作相關(guān)API在單獨(dú)一章中介紹。

#include 《stdio.h》

char getchar(void); // 控制臺(tái)輸入一個(gè)字符

int putchar(int c); // 控制臺(tái)輸出一個(gè)字符

char *gets(char *s); // 控制臺(tái)輸入一個(gè)字符串

int puts(const char *s); // 控制臺(tái)輸出一個(gè)字符串

int printf(const char *format, 。。。); // 控制臺(tái)格式化輸出

int scanf(const char *format, 。。。); // 控制臺(tái)格式化輸入

int sprintf(char *s, const char *format, 。。。); // 字符串格式化輸出

int sscanf(const char *s, const char *format, 。。。); // 字符串格式化輸入

1.1.4 sprintf與sscanf

適用于string版本的格式化輸入/輸出,其目標(biāo)不是控制臺(tái),而是一個(gè)字符串。這兩個(gè)函數(shù)非常有用。

用sprintf格式化一個(gè)字符串,例如,

[cpp] view plain copychar buf [256];

sprintf (buf, “Name: %s, Age: %d, Height: %.2f \n”, “LiMing“, 30, 1.68 );

此代碼將目標(biāo)buf格式化為: Name: LiMing, Age 30, Height: 1.68

用sscanf從一個(gè)具有格式的字符串中提取固定字段,和scanf的用法類似,要求在格式上要嚴(yán)格匹配。以下代碼從字符中提供取年月日的值。

[cpp] view plain copychar* src = ”2014-12-11“;

int year, month, day;

int n = sscanf ( src,

”%d-%d-%d“,

&year, &month, &day);

if( n == 3)

{

// 成功提取了所有字段

}

1.2 math.h

提供了一系列數(shù)學(xué)相關(guān)的函數(shù),如三角函數(shù)、指數(shù)/對(duì)數(shù)、冪/根號(hào)等。

#include 《math.h》

double abs(double x); // 取絕對(duì)值

double cos(double x); // 余弦cos, 參數(shù)是弧度值

double sin(double x); // 正弦sin, 參數(shù)是弧度值

double tan(double x); // 正切 tan, 參數(shù)是弧度值

double ceil(double x); // 向上取整, 即不小于x的最小整數(shù)

double floor(double x); // 向下取整, 即不大于x的最大整數(shù)

double exp(double x); // 求ex

double log(double x); // ln(x), 以e為底的對(duì)數(shù)

double log10(double x); // lg(x), 以10為底的對(duì)數(shù)

double pow(double x, double y); // 求冪xy

double sqrt(double x); // 求平方根 x1/2

需要補(bǔ)充說(shuō)明的是,這里所列的幾乎所有函數(shù)都至少有2個(gè)版本,分別是double型和float型參數(shù)。例如,

[cpp] view plain copydouble sqrt(double x);

float sqrt(float x);

以下代碼編譯錯(cuò)誤,

[cpp] view plain copydouble result = sqrt (16); // 編譯錯(cuò)誤

為什么會(huì)有編譯錯(cuò)誤呢?因?yàn)樽置娉A?6是int型,在匹配函數(shù)時(shí),sqrt(float)與sqrt(double)均被匹配,int可以隱式轉(zhuǎn)換成float和double。必須要顯示把參數(shù)強(qiáng)轉(zhuǎn)為double或float。

如果要對(duì)一個(gè)整數(shù)調(diào)用sqrt函數(shù),那么就必須顯式的強(qiáng)轉(zhuǎn)成double或float,例如,

[cpp] view plain copydouble result = sqrt ((double)16); // OK

float result = sqrt ((float)16); // OK

1.2.1 abs求絕對(duì)值

例如 ,

[cpp] view plain copydouble a = abs ( -12.34);

1.2.2 cos/sin/tan三角函數(shù)

其單位都是弧度值。例如,

[cpp] view plain copy#define PI 3.1415926535898

double ret = sin ( PI / 2); // sin (pi/2)結(jié)果應(yīng)為1

1.2.3 ceil /floor取整

用于向上/向下取整。例如,

[cpp] view plain copydouble ci = ceil ( 12.87 ); // +13

double fi = floor(12.87); // +12

ci = ceil ( -12.87 ); // -12

fi = floor( -12.87); // -13

1.2.4 exp / log / log10 / pow / sqrt指數(shù)/對(duì)數(shù)/冪/平方根

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

1.3 time.h

time.h中提供了時(shí)間/日期相關(guān)的函數(shù)。這里僅列出常用的幾個(gè)函數(shù)。

#include 《time.h》

struct tm *localtime(const time_t *tod); // 當(dāng)“秒值”轉(zhuǎn)成“年月日時(shí)分秒”

time_t mktime(struct tm *tptr); // 將“年月日時(shí)分秒”轉(zhuǎn)成“秒值”

time_t time(time_t *tod); // 取得當(dāng)前時(shí)間

其中,需要介紹time_t和struct tm這兩個(gè)類型。

1.3.1 time_t

time_t是一個(gè)typedef的類型,目前在各種操作系統(tǒng)上time_t類型都是一個(gè)整數(shù)類型,差不多就是

typedef long time_t;

這種類似的定義,在各種場(chǎng)合都可以認(rèn)為它是int型。當(dāng)然,保險(xiǎn)起見(jiàn)也可以顯式的強(qiáng)轉(zhuǎn)一下。它的單位是秒。

[cpp] view plain copytime_t start = 1000;

time_t end = 1020;

printf(”time eclipse: %d seconds !\n“, (int)(end - start));

1.3.2 struct tm

tm是一個(gè)結(jié)構(gòu),它的定義是,

struct tm

{

int tm_sec; /* seconds after the minute - [0,59] */

int tm_min; /* minutes after the hour - [0,59] */

int tm_hour; /* hours since midnight - [0,23] */

int tm_mday; /* day of the month - [1,31] */

int tm_mon; /* months since January - [0,11] */

int tm_year; /* years since 1900 */

int tm_wday; /* days since Sunday - [0,6] */

int tm_yday; /* days since January 1 - [0,365] */

};

它用于表示日期/時(shí)間,有幾個(gè)字段組成:年,月,日,時(shí),分,秒,weekday和yearday。其中,

年:從1900開(kāi)始算,tm_year = 114表示年份 1900 + 114 = 2014

月:范圍是[0,11], tm_mon = 11表示月份 12

日:范圍是[1,31], tm_mday = 24表示該月的第24天

時(shí): 范圍是[0,23],tm_hour = 13表示下午13時(shí)

分: 范圍是[0,59], tm_min = 40表示第40分鐘

秒:范圍是[0,59], tm_sec = 40表示第40秒鐘

tm_wday: 范圍是[0,6],星期日是0,星期一是1,。。。 ,星期六是6

tm_yday: 范圍是[0,365],tm_yday=299,表示當(dāng)年的第300天

當(dāng)tm_min和tm_sec都為0時(shí),表示整點(diǎn)時(shí)間。如12:00:00。

例如,2014-12-11 11:47:12這個(gè)時(shí)間可以用下面的代碼賦值:

[cpp] view plain copytm info;

info.tm_year = 2014 - 1900; // 2014年

info.tm_mon = 12 - 1; // 12月

info.tm_mday = 11; // 11日

info.tm_hour = 11; // 11時(shí)

info.tm_min = 47; // 47分

info.tm_sec = 12; // 12分

1.3.3 time取得系統(tǒng)當(dāng)前時(shí)間

time函數(shù)可以取得系統(tǒng)當(dāng)前時(shí)間,返回值是一個(gè)秒值。例如,

[cpp] view plain copytime_t now = time (NULL);

為什么一個(gè)整數(shù)秒值可以表示當(dāng)前的時(shí)間呢?是這么規(guī)定的,time函數(shù)返回的是自1970-1-1 00:00:00這個(gè)時(shí)間點(diǎn)開(kāi)始至當(dāng)前時(shí)刻的時(shí)間差。它是一個(gè)比較大的整數(shù),例如1418270153表示的是2014-12-11 11:55:53這個(gè)時(shí)刻。

利用time函數(shù)時(shí)可以計(jì)算程序運(yùn)行了多少時(shí)間,如下面的代碼:

[cpp] view plain copytime_t start = time (NULL);

。。。 DoSomething 。。。

time_t end = time (NULL);

printf(”Time cost : %d seconds“, end - start );

當(dāng)然這個(gè)DoSomething要運(yùn)行相當(dāng)時(shí)間才行,因?yàn)閠ime的粒度較大,返回是秒值。如果你的DoSomething只耗費(fèi)了幾毫秒的話,那么用time根本無(wú)法衡量。不過(guò),可以成倍的量化一下,比較,將DoSomething連續(xù)運(yùn)動(dòng)10000次,看需要的總時(shí)間,然后再平均一下得出單次需要的時(shí)間。

[cpp] view plain copytime_t start = time (NULL);

for( int i=0; i《 10000; i++)

{

。。。 DoSomething 。。。

}

time_t end = time (NULL);

int avg = (end - start ) / 10000;

1.3.4 localtime()得到年月日時(shí)分秒

雖然用一個(gè)time_t整數(shù)來(lái)表示當(dāng)前系統(tǒng)時(shí)間是比較方便的,但有時(shí)候還是希望能轉(zhuǎn)化成年月日時(shí)分秒的形式來(lái)顯示,畢竟肉眼無(wú)法直接看一個(gè)time_t值到底是哪一個(gè)日期。

localtime函數(shù)可以將time_t所表示的時(shí)間轉(zhuǎn)化成年月日時(shí)分秒,例如,

[cpp] view plain copytime_t t = time(NULL);

tm info = *localtime(&t);

printf(”%04d-%2d-%02d %02d:%02d:%02d \n“,

info.tm_year + 1900,

info.tm_mon + 1,

info.tm_mday,

info.tm_hour,

info.tm_min,

info.tm_sec);

localtime的返回值是tm*類型,應(yīng)該用一個(gè)tm變量將內(nèi)容保存起來(lái)。

事實(shí)上,用time_t來(lái)記錄時(shí)間更方便,只用一個(gè)整數(shù)(占4個(gè)字節(jié))就表達(dá)了日期和時(shí)間信息。在保存和傳輸?shù)臅r(shí)候,應(yīng)該盡量用time_t類型。只是在最終顯示的時(shí)候,用localtime轉(zhuǎn)成人類易讀的yyyy-mm-dd HH:MM:SS格式。

1.3.5 mktime構(gòu)造時(shí)間

當(dāng)已知了年月日時(shí)分秒信息,可以用mktime換算成time_t值。例如,把2014-12-11 11:47:12轉(zhuǎn)成time_t值,

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

1.4 stdlib.h

這一節(jié)將介紹stdlib.h里提供的API,下面列表其中主要的幾個(gè)函數(shù):

#include 《stdlib.h》

double atof(const char *s);

int atoi(const char *s);

int rand(void);

void srand(unsigned int seed);

int system(const char *s);

1.4.1 atoi / atof 字符串轉(zhuǎn)成數(shù)字

例如,

[cpp] view plain copyint n = atoi(”1280“);

double f = atof(”12.80“);

其實(shí)完全可以用sscanf來(lái)完成相同的事情,例如,

[cpp] view plain copyint n;

double f;

sscanf(”1280“, ”%d“, &n);

sscanf(”12.80“, ”%f“, &f);

相比之下,使用atoi和atof更簡(jiǎn)潔一些。

1.4.2 rand / srand 隨機(jī)數(shù)生成

在抽簽、抽獎(jiǎng)等涉及“隨機(jī)事件”的應(yīng)用場(chǎng)景中,需要隨機(jī)數(shù)生成函數(shù)。由于計(jì)算機(jī)中并沒(méi)有隨機(jī)性和偶然性,想制造一個(gè)隨機(jī)數(shù)實(shí)際上是一件比較困難的事情。要真正隨機(jī)的數(shù)字,需要購(gòu)置在非常昂貴的硬件,這些硬件利用某些自然科學(xué)的規(guī)則來(lái)生成隨機(jī)數(shù),因?yàn)閮r(jià)格昂貴,所以專業(yè)的隨機(jī)數(shù)生成器只用于專業(yè)用途。我們這里介紹的適用普通PC機(jī)能夠勝任的“偽隨機(jī)數(shù)”生成函數(shù),能夠生成近似隨機(jī)的數(shù)據(jù)就可以了。

rand函數(shù)用于生成隨機(jī)數(shù),該函數(shù)返回一個(gè)整數(shù)。調(diào)用以下代碼測(cè)試一下:

[cpp] view plain copyfor(int i=0; i《10; i++)

{

printf(”%d \n“, rand());

}

控制臺(tái)輸出了10個(gè)完全沒(méi)有規(guī)律的數(shù)字,因?yàn)橥耆珶o(wú)規(guī)律可循,所以稱它為隨機(jī)數(shù)。這里為了顯示方便,只生成了10個(gè)隨機(jī)數(shù),實(shí)際上可以改成1000次、10000次試試,會(huì)發(fā)現(xiàn)它確實(shí)是雜亂無(wú)章、完全沒(méi)有規(guī)律的出現(xiàn)的。

那么為什么說(shuō)它是“偽隨機(jī)數(shù)”呢?說(shuō)明它沒(méi)有真正的實(shí)現(xiàn)“隨機(jī)”??梢赃@么驗(yàn)證一下,把相同的程序反復(fù)運(yùn)行數(shù)次,會(huì)發(fā)現(xiàn)每次程序運(yùn)行輸出的結(jié)果都是相同的一個(gè)序列的數(shù)字。例如,第一次運(yùn)行程序的時(shí)候輸出13435 31833 5075 19863 30565 11677 1339 4096 31105 9088等10個(gè)隨機(jī)數(shù),當(dāng)關(guān)閉程序再次運(yùn)行時(shí),輸出的10個(gè)隨機(jī)數(shù)還是這10個(gè)數(shù)。

為了解決這個(gè)問(wèn)題,stdlib.h里提供了srand函數(shù)。srand函數(shù)用于為程序設(shè)置一個(gè)種子(seed),當(dāng)種子不同時(shí),程序產(chǎn)生的隨機(jī)數(shù)序列也不同。srand只需要在程序開(kāi)始時(shí)設(shè)置一次,例如,可以在main()函數(shù)開(kāi)始時(shí)運(yùn)行一次。種子怎么定呢?要保證程序每次運(yùn)行時(shí),這個(gè)種子的值不同,一般來(lái)說(shuō)是取系統(tǒng)時(shí)間來(lái)作為種子的。

[cpp] view plain copyvoid main()

{

srand (time (NULL));

。。。 do something else 。。。

}

每次程序運(yùn)行時(shí),time(NULL)返回的時(shí)間是不同的,于是srand每次都是使用了不同的種子。在程序中再調(diào)用rand()來(lái)生成隨機(jī)數(shù)時(shí),會(huì)發(fā)現(xiàn)每次程序運(yùn)行生成的隨機(jī)數(shù)序列是不同的。

在實(shí)際應(yīng)用中如何使用rand函數(shù)呢?例如,有一種彩票叫“七星彩”,每次生成的中獎(jiǎng)號(hào)碼是7個(gè)屆于0~9之間的隨機(jī)數(shù)字??梢杂胷and來(lái)隨機(jī)生成一注號(hào)碼。

[cpp] view plain copyvoid main()

{

srand (time (NULL));

int code[7]; // 一注號(hào)碼為7個(gè)數(shù)字

for(int i=0; i《7; i++)

{

int r = rand () % 10; // 取模使每個(gè)數(shù)字界于0~9之間

code[i] = r;

}

}

注意,一般都要為rand()生的隨機(jī)數(shù)指定一個(gè)區(qū)間。

生成[100,120]之間的隨機(jī)數(shù),

[cpp] view plain copyint r = 100 + rand () % 20;

生成[0,1]區(qū)間的隨機(jī)小數(shù),

double r = rand()/ (double)RAND_MAX;

其中, RAND_MAX在VC下的定義是32767,在其他操作系統(tǒng)下可能是其他值。

例題:給定10個(gè)數(shù),要求從中每次隨機(jī)選出5個(gè)數(shù)。

思路:首先,從10個(gè)數(shù)里面隨機(jī)挑選出1個(gè)數(shù),然后再?gòu)氖O碌?個(gè)數(shù)里挑選1個(gè),然后再?gòu)氖O碌?個(gè)數(shù)里挑選1個(gè)。。。。。。

設(shè)計(jì):用一個(gè)flags數(shù)組來(lái)表示哪個(gè)數(shù)已經(jīng)被選中了,例如 flags[3] = 1表示第第4個(gè)數(shù)已經(jīng)被選中,flags[9]=0表示第10個(gè)數(shù)未被選中。

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

1.4.3 system 調(diào)用系統(tǒng)命令行

用system函數(shù)可以調(diào)用系統(tǒng)命令行,在windows下可以執(zhí)行DOS命令行, 在linux下SHELL命令行。比如,刪除d:\aaa.pdf這個(gè)文件,

system (”del /F /Q d:\\aaa.pdf“);

其實(shí)原則上并不限于DOS命令,所以的命令行都可以運(yùn)行的。例如,調(diào)用瀏覽器打開(kāi)一個(gè)網(wǎng)站,

[cpp] view plain copysystem (”explorer http://www.afanihao.cn“);

1.5 string.h

string.h中提供了一系統(tǒng)內(nèi)存操作函數(shù)及字符串操作函數(shù)。在學(xué)習(xí)本節(jié)之前,一定要先學(xué)習(xí)第15章中,掌握字符串的意義。

#include 《string.h》

char *strcat(char *s1, const char *s2); // 拼接字符串

char *strchr(char *s, int c); // 查找字符

int strcmp(const char *s1, const char *s2); // 字符串比較

char *strcpy(char *s1, const char *s2); // 拷貝字符串

char *strstr(char *s1, const char *s2); // 查找子串

size_t strlen(const char *s); // 計(jì)算長(zhǎng)度

int memcmp(const void *s1, const void *s2, size_t n); //按內(nèi)存比較

void *memcpy(void *s1, const void *s2, size_t n); // 按內(nèi)存拷貝

void *memmove(void *s1, const void *s2, size_t n); // 移動(dòng)數(shù)據(jù)

void *memset(void *s, int c, size_t n); // 按字節(jié)填充內(nèi)存

1.5.1 strcpy拷貝字符串

strcpy(a,b)用于將字符串b拷貝到目標(biāo)緩沖區(qū),

如,

[cpp] view plain copychar buf[128];

strcpy(buf, ”LiMing“); // 目標(biāo)緩沖區(qū)內(nèi)容拷貝為”LiMing“

1.5.2 strcat拼接字符串

strcat(a,b)用于將字符串b拼接于字符串a(chǎn),也就是說(shuō)把字符串拷貝到目標(biāo)字符串的末尾。此函數(shù)要求目標(biāo)緩沖區(qū)足夠大,

[cpp] view plain copy#include 《string.h》

void main()

{

char a [128] = ”hello“;

char b [] = ”world“;

strcat(a, b); // 目標(biāo)a結(jié)果為”helloworld“

}

1.5.3 strcmp比較字符串

關(guān)于字符串比較的意義在第15章已經(jīng)講述。strcmp(a,b)用于比較字符串,當(dāng)返回為0時(shí)表示完全相等,小于0時(shí)表示a《b,大于0時(shí)表示a》b。

[cpp] view plain copyint ret = strcmp(”Jack“, ”Jacky“); // 返回值 ret=-1,表示”Jack“《”Jacky“

1.5.4 strlen求字符串長(zhǎng)度

字符串求長(zhǎng)度時(shí),結(jié)束符‘\0’不計(jì)算在內(nèi)。例如,

[cpp] view plain copyint n = strlen(”LiMing“); // 返回長(zhǎng)度n為6

1.5.5 strchr查找字符

strchr(s, c)用于在字符串s中查找字符c,并返回第一處匹配的位置。其返回值是char*類型,表示匹配的位置,

[cpp] view plain copychar* s = ”LiMing“;

char* p = strchr(s, ‘M’); // 返回值p指向字符‘M’的地址

if(p!= NULL)

{

printf(”find: %s \n“, p);

}

1.5.6 strstr查找子串

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

1.5.7 memset內(nèi)存填充

[cpp] view plain copymemset(s, c, n)用于向目標(biāo)緩沖區(qū)s中添加n個(gè)相同的字符c,例如,

unsigned char buf[128];

memset(buf, 0, sizeof(buf)); // 全部填充為0

memset(buf, 0xFF, 128); // 全部填充為0xFF

memset(buf, 0x55, 100); // 前100個(gè)字節(jié)填充為0x55

memset(buf+100, 0x77, 10); // 100..109填充為0x77

1.5.8 memcpy內(nèi)存拷貝

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

1.5.9 memcmp內(nèi)存比較

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

其中,a和b的比較是容易得出結(jié)果的 ,但a與c的比較呢?由于要轉(zhuǎn)成unsigned char再比較,所以c》a。

1.5.10 memmove移動(dòng)數(shù)據(jù)

memmove(dst, src, n)用于在內(nèi)存中移動(dòng)數(shù)據(jù),將開(kāi)始于src的n個(gè)字節(jié)移動(dòng)到dst位置,這個(gè)函數(shù)的強(qiáng)大之處在于它允許src和dst有交迭。

例如,利用這個(gè)函數(shù)我們可以實(shí)現(xiàn)在字符串中插入字符,當(dāng)插入字符串如果將插入點(diǎn)之后的所有字符后移,

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

點(diǎn)擊查看此節(jié)內(nèi)容,第16章

1.6 stdarg.h

stdarg.h中的接口用于實(shí)現(xiàn)省略號(hào)參數(shù)。在函數(shù)中曾經(jīng)指出,函數(shù)參數(shù)有一個(gè)特殊形式,就是不指定個(gè)數(shù)和類型,直接用省略號(hào)表示。

void test (。。。)

當(dāng)參數(shù)為省略號(hào)時(shí),可以輸入任意個(gè)數(shù)的參數(shù),而且參數(shù)的類型不受限制。我們觀察printf函數(shù)的原型,發(fā)現(xiàn)它就是使用了省略號(hào)參數(shù),

int printf(const char *format, 。。。);

printf的第一個(gè)參數(shù)為字符串類型,用于傳遞格式參數(shù), 而后面的省略號(hào)處可以傳遞0..N個(gè)參數(shù)。這種靈活的傳參方式在某此特殊場(chǎng)合會(huì)用到。下面就指出一種應(yīng)用需求并給出其實(shí)現(xiàn)方法。

需求:自定義一個(gè)函數(shù)用于日志輸出,在輸出的時(shí)候自動(dòng)添加日期時(shí)期信息、日志等級(jí),其原型要求是這種形式,

void log(int level, const char* fmt, 。。。);

其中, level為日志級(jí)別:level=0時(shí),顯示ERR, level=1時(shí)顯示:WRN, level=2時(shí)顯示INF, level=3時(shí)顯示DBG。

在調(diào)用的時(shí)候要求跟printf類似地使用格式化控制符來(lái)控制輸出,并前綴以日期顯示:

log(0, “My name is %s, I‘m %d years old.\n”, “Jennifer”, 30);

此需求實(shí)際上就是要實(shí)現(xiàn)一個(gè)自定義的打印函數(shù),

[cpp] view plain copy#include 《stdio.h》

#include 《string.h》

#include 《stdarg.h》

void log(int level, const char* fmt, 。。。)

{

// 打印日志等級(jí)

const char* token = ”DBG“;

switch(level)

{

case 0: token = ”ERR“; break;

case 1: token = ”WRN“; break;

case 2: token = ”INF“; break;

case 3: token = ”DBG“; break;

}

printf(”[ %s ] “, token);

// 將省略號(hào)參數(shù)格式化成字符串

char buf[512];

va_list args;

va_start(args, fmt);

vsprintf(buf, fmt, args);

va_end(args);

printf(buf);

}

int main()

{

log(2, ”Name: %s, Age: %d.\n“, ”LiMing“, 30);

return 0;

}

對(duì)省略號(hào)參數(shù)的核心處理是這幾行代碼:

[cpp] view plain copyva_list args;

va_start(args, fmt);

。。。 此處已經(jīng)將參數(shù)取得在args里。。。

va_end(args);

能夠以va_list作為參數(shù)的函數(shù)有vsprintf, vprintf, vfprintf,其原型是:

int vprintf(const char *format, va_list ap); // 輸出到控制臺(tái)

int vsprintf(char *s, const char *format, va_list ap); // 輸出到字符串緩沖區(qū)

int vfprintf(FILE *stream, const char *format, va_list ap); // 輸出到文件流

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    STM32固件函數(shù)庫(kù)資料分享!

    應(yīng)用每一個(gè)外設(shè)。因此,使用本固態(tài)函數(shù)庫(kù)可以大大減少用戶的程序編寫時(shí)間,進(jìn)而降低開(kāi)發(fā)成本。 所有的驅(qū)動(dòng)源代碼都符合“Strict ANSI-C標(biāo)準(zhǔn)(項(xiàng)目于范例文件符合擴(kuò)充 ANSI-C
    發(fā)表于 08-31 17:26

    PS 2接口C 語(yǔ)言通信函數(shù)庫(kù)設(shè)計(jì)

    深入分析PS/2 接口通信協(xié)議,實(shí)現(xiàn)了C 語(yǔ)言通信函數(shù)庫(kù),可以方便地應(yīng)用于PS/2 設(shè)備的使用和開(kāi)發(fā)。程序在AVR 單片機(jī)上實(shí)現(xiàn)并通過(guò)檢驗(yàn), 最后給出一個(gè)使用該函數(shù)庫(kù)的程序。
    發(fā)表于 05-14 14:37 ?43次下載

    Linux C 函數(shù)庫(kù)中文教程

    Linux C 函數(shù)庫(kù)中文手冊(cè) cosh       原型:extern float cosh(float x);    用法:#include  
    發(fā)表于 03-10 14:09 ?36次下載

    ZLGCAN接口函數(shù)庫(kù)

    ZLGCAN接口函數(shù)庫(kù) 數(shù)據(jù)結(jié)構(gòu)VCI 函數(shù)庫(kù)中定義了一些數(shù)據(jù)結(jié)構(gòu)用于數(shù)據(jù)交換,在使用VCI 函數(shù)前應(yīng)該先創(chuàng)建這些數(shù)據(jù)結(jié)構(gòu)。在LabVIEW 中創(chuàng)建這些結(jié)構(gòu)時(shí)應(yīng)該使用
    發(fā)表于 03-29 14:01 ?56次下載

    C語(yǔ)言入門教程-函數(shù)庫(kù)

    函數(shù)庫(kù) C語(yǔ)言本身具備最基本功能,所以C函數(shù)庫(kù)就顯得十分重要了。C語(yǔ)言本身甚至不提供從鍵盤讀入和向屏幕輸出的I/O
    發(fā)表于 07-29 10:40 ?1175次閱讀

    C語(yǔ)言入門教程-創(chuàng)建一個(gè)函數(shù)庫(kù)

    創(chuàng)建一個(gè)函數(shù)庫(kù) 上述程序中的rand和bubble_sort函數(shù)很實(shí)用,很可能在您寫其他程序時(shí)也能派上用場(chǎng)。為了能更方便地重復(fù)使用,您可以為它們創(chuàng)建一個(gè)實(shí)用工具函數(shù)庫(kù)。
    發(fā)表于 07-29 11:18 ?3183次閱讀

    PIC單片機(jī)的C語(yǔ)言應(yīng)用下的函數(shù)庫(kù)

    PICC編譯器下的函數(shù)庫(kù),調(diào)用函數(shù)庫(kù)開(kāi)發(fā),更快更方便,更少的bug
    發(fā)表于 12-09 15:29 ?10次下載

    PID模塊相關(guān)函數(shù)庫(kù)

    PID模塊相關(guān)函數(shù)庫(kù)
    發(fā)表于 11-17 18:35 ?7次下載

    linux_C函數(shù)庫(kù)中文手冊(cè)

    linux_C函數(shù)庫(kù)中文手冊(cè)linux_C函數(shù)庫(kù)中文手冊(cè)
    發(fā)表于 03-20 10:42 ?14次下載

    基于GE運(yùn)動(dòng)控制器型號(hào)及在函數(shù)庫(kù)中應(yīng)用

    GE 系列運(yùn)動(dòng)控制器提供DOS 下的C 語(yǔ)言函數(shù)庫(kù)和Windows 下的動(dòng)態(tài)鏈接庫(kù),若為GUC 運(yùn)動(dòng)控制器且內(nèi)嵌系統(tǒng)為WinCE 系統(tǒng),運(yùn)動(dòng)控制器還會(huì)提供對(duì)應(yīng)WinCE 下的動(dòng)態(tài)鏈接庫(kù)
    發(fā)表于 10-11 17:44 ?33次下載

    Linux C函數(shù)庫(kù)參考手冊(cè)真的是免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是Linux C函數(shù)庫(kù)參考手冊(cè)真的是免費(fèi)下載
    發(fā)表于 04-15 08:00 ?18次下載
    Linux <b class='flag-5'>C</b><b class='flag-5'>函數(shù)庫(kù)</b>參考手冊(cè)真的是免費(fèi)下載

    Linux的常用C函數(shù)庫(kù)中文手冊(cè)免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是Linux的常用C函數(shù)庫(kù)中文手冊(cè)免費(fèi)下載,包含幾乎所有Linux下C語(yǔ)言接口,對(duì)初學(xué)者有很大幫助。
    發(fā)表于 10-28 08:00 ?9次下載
    Linux的常用<b class='flag-5'>C</b><b class='flag-5'>函數(shù)庫(kù)</b>中文手冊(cè)免費(fèi)下載

    C語(yǔ)言編程函數(shù)庫(kù)分類匯總資源下載

    C語(yǔ)言編程函數(shù)庫(kù)分類匯總資源下載
    發(fā)表于 04-15 16:40 ?17次下載
    <b class='flag-5'>C</b>語(yǔ)言編程<b class='flag-5'>函數(shù)庫(kù)</b>分類匯總資源下載

    C語(yǔ)言編程文件操作函數(shù)庫(kù)匯總資源下載

    C語(yǔ)言編程文件操作函數(shù)庫(kù)匯總資源下載
    發(fā)表于 04-15 16:42 ?13次下載
    <b class='flag-5'>C</b>語(yǔ)言編程文件操作<b class='flag-5'>函數(shù)庫(kù)</b>匯總資源下載

    LiquidCrystal_I2C函數(shù)庫(kù)

    LiquidCrystal_I2C函數(shù)庫(kù)(實(shí)用電源技術(shù)講義)-【資源描述】: LiquidCrystal_I2C函數(shù)庫(kù)?
    發(fā)表于 09-16 16:05 ?102次下載
    LiquidCrystal_I2<b class='flag-5'>C</b><b class='flag-5'>函數(shù)庫(kù)</b>

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品