C語言最全面的函數(shù)知識(shí)講解寓涨!上萬字純干貨盯串!

涉及到的知識(shí)點(diǎn)有:

1、C語言庫函數(shù)戒良、字符輸入函數(shù):gets和fgets体捏、字符輸出函數(shù):puts和fputs、

? ? 求字符串長度函數(shù)strlen糯崎、字符串追加函數(shù)strcat几缭、字符串有限追加函數(shù)strncat、字符串比較函數(shù)strcmp沃呢、

? ? ? ? 字符串有限比較函數(shù)strcmp年栓、字符串拷貝函數(shù)strcpy、字符串有限拷貝函數(shù)strncpy薄霜、

? ? ? ? 格式化字符串函數(shù)sprintf(輸出)某抓、格式化字符串函數(shù)sscanf(讀取輸入)、解析一個(gè)字符串惰瓜、

? ? ? ?字符串查找字符函數(shù)strchr否副、字符串查找子串函數(shù)strstr、字符串分割函數(shù)strtok崎坊、

? ? ? ?atoi函數(shù)备禀、atof函數(shù)、atol函數(shù)、解析一個(gè)字符串的高級應(yīng)用曲尸。

2赋续、函數(shù)的定義和聲明、函數(shù)的形式參數(shù)(形參)與實(shí)際參數(shù)(實(shí)參)另患、函數(shù)的返回值類型和返回值纽乱、

? ? ?return函數(shù)與exit函數(shù)(exit更猛,不受位置限制)柴淘、自定義一個(gè)函數(shù)迫淹,實(shí)現(xiàn)大小寫字母的互相轉(zhuǎn)換功能秘通、

? ? ?自定義一個(gè)函數(shù)为严,實(shí)現(xiàn)atoi的功能。

3肺稀、函數(shù)的遞歸第股、遞歸例子:有n個(gè)人排成一隊(duì)、遞歸例子:將10進(jìn)制數(shù)轉(zhuǎn)化為二進(jìn)制數(shù)话原、

? ? ?遞歸例子:將10進(jìn)制數(shù)轉(zhuǎn)化為16進(jìn)制夕吻、遞歸例子:菲波那切數(shù)列、遞歸的優(yōu)點(diǎn)與缺點(diǎn)繁仁。

4涉馅、多個(gè)源代碼文件程序如何編譯、頭文件的使用黄虱、解決預(yù)編譯時(shí)會(huì)出現(xiàn)多次函數(shù)聲明問題稚矿。

“我是一名從事了10年開發(fā)的老程序員,最近我花了一些時(shí)間整理關(guān)于C語言捻浦、C++晤揣,自己有做的材料的整合,一個(gè)完整的學(xué)習(xí)C語言朱灿、C++的路線昧识,學(xué)習(xí)材料和工具。C/C++盗扒、編程愛好者的聚集地就在我這里 <進(jìn)入我的專欄就能看到>跪楞!歡迎初學(xué)和進(jìn)階中的小伙伴。希望你也能憑自己的努力侣灶,成為下一個(gè)優(yōu)秀的程序員甸祭。工作需要、感興趣炫隶、為了入行淋叶、轉(zhuǎn)行需要學(xué)習(xí)C/C++的伙伴可以跟我一起學(xué)習(xí)!”

C語言/C++進(jìn)階之路 - 專題 - 簡書

===========================================================

C語言庫函數(shù)

1、字符串處理函數(shù):字符輸入函數(shù)和字符輸出函數(shù)

字符輸入函數(shù):gets和fgets

通過scanf輸入的時(shí)候煞檩,最后按的是一個(gè)什么鍵处嫌?答:回車鍵,scanf會(huì)把回車鍵認(rèn)為是輸入完成斟湃,而不是字符串的內(nèi)容熏迹。

而且scanf認(rèn)為回車和空格都代表輸入完成哦。

當(dāng)字符數(shù)組的成員數(shù)量小于用戶在鍵盤輸入字符的數(shù)量之后凝赛,scanf并不會(huì)自動(dòng)處理注暗,而是把用戶輸入的所有字符都放入了數(shù)組,導(dǎo)致了數(shù)組溢出了墓猎,內(nèi)存出錯(cuò)捆昏,程序崩潰。

-----------------------------------------------------------------------------

gets認(rèn)為只有回車代表輸入完成毙沾,空格只是字符串中的一部分而已骗卜。

gets和scanf一樣有緩沖區(qū)溢出的危險(xiǎn)。

-----------------------------------------------------------------------------

字符數(shù)組 的英文名字是 char []

gets()函數(shù)的基本用法為:

char *gets(char *s);?

該函數(shù)的參數(shù)是一個(gè)字符數(shù)組左胞,該函數(shù)的返回值也是一個(gè)字符數(shù)組寇仓。

linux下示例代碼如下:

1 #include

2?

3 int main()

4 {

5    char a[100] = { 0 };

6    gets(a);

7  ? printf("%s\n", a);

8    return 0;

9 }

-----------------------------------------------------------------------------

編譯時(shí)會(huì)出現(xiàn)一個(gè)warning,建議我們不要使用gets函數(shù)了烤宙。我們暫時(shí)不管他遍烦,先直接運(yùn)行看結(jié)果。

--------------------------------------

警告如下:

a2.c:6:5: warning: implicit declaration of function ‘gets’ [-Wimplicit-function-declaration]

gets(a);

^

/tmp/cceyMQ7u.o: In function `main':

a2.c:(.text+0x41): warning: the `gets' function is dangerous and should not be used.

--------------------------------------

原因:

問題出在程序中使用了 gets是非常不安全的躺枕。這是對程序產(chǎn)生BUG服猪,出現(xiàn)不可靠性的一個(gè)描述,

有些函數(shù)在某些意外情況會(huì)導(dǎo)致程序陷入不可控狀態(tài)屯远,僅僅是PC上運(yùn)行最多也就是退出而已蔓姚,

但是如果是運(yùn)行在飛機(jī)等系統(tǒng)里的話,就會(huì)有大麻煩慨丐,說危險(xiǎn)也不為過坡脐。因?yàn)橛⑽奈墨I(xiàn)里描述為dangerous,所以也就翻譯為危險(xiǎn)房揭。

函數(shù)執(zhí)行需要一個(gè)棻赶校空間,但這個(gè)椡北空間容量是有限的恬砂,而且棧里存放了函數(shù)返回的地址。

gets()函數(shù)在獲取輸入時(shí)蓬痒,如果無限輸入會(huì)造成椥褐瑁空間溢出,在程序返回時(shí),不能正常的找到返回地址狱掂,程序?qū)l(fā)生不可預(yù)測行為演痒。

--------------------------------------

解決:

解決辦法是使用 fgets,但由于fgets函數(shù)是為讀取文件設(shè)計(jì)的趋惨,所以讀取鍵盤是沒有g(shù)ets那么方便鸟顺。

fgets(char *s, int size, FILE *stream);

第一個(gè)參數(shù)是:字符類型的數(shù)組,第二個(gè)參數(shù)是:標(biāo)明這個(gè)數(shù)組的大小器虾,第三個(gè)參數(shù)是:如果總是通過鍵盤輸入的話讯嫂,可以固定寫為stdin。

fgets()函數(shù)的基本用法為:

-------------------------------------

示例程序:

/*代碼實(shí)現(xiàn)01_使用fputs函數(shù)打印輸出*/

#include <stdio.h>

int main ( )?

{

char name[20] = { 0 };

fgets(name, sizeof(name), stdin);//stdin 意思是鍵盤輸入

fputs(name, stdout); //stdout 意思是通過打印設(shè)備輸出

return 0;

}

--------------------------------------

/*代碼實(shí)現(xiàn)02_使用printf函數(shù)打印輸出*/

#include

int main ( )?

{

char name[20] = { 0 };

fgets(name, sizeof(name), stdin);//stdin 意思是鍵盤輸入

printf("%s", name);//這邊輸出不需要 \n 了兆沙,實(shí)際操作時(shí)欧芽,fgets會(huì)認(rèn)為用戶輸入的回車也是字符串的一部分內(nèi)容。即輸出的內(nèi)容中間接地帶了 \n 了挤悉。

return 0;

}

-----------------------------------------------------------------------------

fgets會(huì)認(rèn)為用戶輸入的回車也是字符串的一部分內(nèi)容渐裸。

fgets是安全的巫湘,不會(huì)因?yàn)橛脩魫阂獾妮斎脒^長的字符串導(dǎo)致溢出装悲。因?yàn)樗唤邮芩艽娴淖畲蟮淖址麛?shù),其余的舍掉尚氛!

=============================================================================

字符輸出函數(shù):puts和fputs

puts函數(shù)打印字符串時(shí)诀诊,與printf不同,puts會(huì)在最后自動(dòng)增加一個(gè)換行字符 '\n'阅嘶。

puts不支持各種轉(zhuǎn)義字符属瓣,如%d,%s都不支持讯柔,puts只能簡單直接地輸出一個(gè)字符串抡蛙,而不能輸出char類型(字符類型)、int類型(整型)魂迄、double類型(雙精度浮點(diǎn)類型)等其他類型粗截。

linux下示例代碼如下:

1 #include

2?

3 int main()

4 {

5   char a[] = "hello world";

6   puts(a);

7   return 0;

8 }

--------------------------------------

puts函數(shù)內(nèi)部可能是如下這樣實(shí)現(xiàn)的:

int puts(const char *s)

{

int index = 0;

while(s[index])

{

putchar(s[index]);

index++;

}

putchar('\n');

return index;

}

putchar函數(shù)的作用:向終端輸出一個(gè)字符。

(1)putchar函數(shù)只能用于單個(gè)字符的輸出捣炬,且一次只能輸出一個(gè)字符熊昌。

(2)在程序中使用putchar函數(shù),務(wù)必牢記:在程序(或文件)的開頭加上編譯預(yù)處理命令(也稱包含命令)湿酸,即:#include "stdio.h"婿屹。

//思考

用putchar就可以實(shí)現(xiàn)puts,printf等輸出函數(shù)推溃。

用getchar就可以實(shí)現(xiàn)scanf昂利,gets等輸入函數(shù)。

-----------------------------------------------------------------------------

fputs函數(shù)是puts函數(shù)的文件操作版本。

int fputs(const char *s, FILE *stream);  //注意:const用來修飾char *s, *s的內(nèi)容不可變蜂奸。

第一個(gè)參數(shù)是一個(gè)char的數(shù)組梯捕;第二個(gè)參數(shù)是:如果總是通過屏幕進(jìn)行輸出的話,可以固定寫為stdout窝撵。

fputs并不會(huì)像puts那樣輸出的時(shí)候自動(dòng)結(jié)尾加 \n 傀顾。

linux下示例代碼如下:

1 #include

2?

3 int main()

4 {

5    char a[] = "hello world";?

6    //puts(a);     ? //hello world

//root@iZ2zeeailqvwws5dcuivdbZ:~/1/01#

7    //printf(a);   ? ? ? //hello worldroot@iZ2zeeailqvwws5dcuivdbZ:~/1/01# 編譯有警告哦

8   ?fputs(a, stdout);  //hello worldroot@iZ2zeeailqvwws5dcuivdbZ:~/1/01#

9    return 0;

10 }

--------------------------------------

1 #include

2?

3 int main()

4 {

5    char a[] = "hello world\n";?

6    //puts(a);?

7    //printf(a);

8  ? fputs(a, stdout);  //hello world

9  ? return 0;     ? ?//root@iZ2zeeailqvwws5dcuivdbZ:~/1/01#

10 }

=============================================================================

求字符串長度函數(shù)strlen

使用這個(gè)庫函數(shù)時(shí)需要包含頭文件<string.h>

"abc",注意:用strlen時(shí)返回的結(jié)果是3,而不是4碌奉。

strlen函數(shù)的基本用法為:

size_t strlen(const char *s);?

參數(shù)是:一個(gè)字符數(shù)組短曾。

返回值是:不包含字符串結(jié)尾'\0'的字符串的長度(注意:是字符串字節(jié)的總數(shù)哦!不同的系統(tǒng)下是不同的)赐劣。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6    char a[] = "hello";//char a[] = "hello傳智";

7    unsigned int index = 0;

8    /*

9    while (a[index])

10   {

11     index++;

12   }

13   */

14   index = strlen(a);

15   ? ?printf("%u\n",index);//5 //11

16   return 0;

17 }

=============================================================================

字符串追加函數(shù)strcat

strcat函數(shù)的基本用法為:

char *strcat(char *dest, const char *src);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)字符數(shù)組嫉拐,第二個(gè)參數(shù)是靜態(tài)的字符數(shù)組。

返回值是:一個(gè)字符數(shù)組魁兼。

用strcat的時(shí)候要注意婉徘,第一個(gè)字符串一定要有足夠的空間容納第二個(gè)字符串。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6    char a[100] = "abc"; ? //a不是空串時(shí)

7    char b[100] = "hello";

8  ? strcat(a,b);       //將a和b合并為一個(gè)字符串咐汞,合并的結(jié)果放入a盖呼。

9  ? printf("%s\n", a);  //abchello

10   ?return 0;

11 }

--------------------------------------

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = { 0 };//a為空串時(shí) 或者 char a[100] = "";

7   char b[100] = "hello";

8   strcat(a, b);

9   printf("%s\n", a);//hello

10 ? return 0;

11 }

-----------------------------------------------------------------------------

字符串有限追加函數(shù)strncat

strncat函數(shù)的基本用法為:

char *strncat(char *dest, const char *src, size_t n);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)字符數(shù)組,第二個(gè)參數(shù)是靜態(tài)的字符數(shù)組化撕,第三個(gè)參數(shù)代表最多追加幾個(gè)字符几晤。

返回值是:一個(gè)字符數(shù)組。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6    char a[100] = "abc";

7    char b[100] = "hello123456789";

8    strncat(a, b, 5);?

9    printf("%s\n", a);  //abchello

10  ? return 0;

11 }

=============================================================================

字符串比較函數(shù)strcmp

strcmp函數(shù)的基本用法為:

int strcmp(const char *s1, const char *s2);//比較兩個(gè)字符串是否相等

參數(shù)是:第一個(gè)參數(shù)是一個(gè)靜態(tài)的字符數(shù)組植阴,第二個(gè)參數(shù)是靜態(tài)的字符數(shù)組蟹瘾。

返回值是:int。相等返回0掠手;不相等返回非0.

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6    char a[100] = "abc";

7    char b[100] = "hel";

8  ? if (strcmp(a, b) == 0)

9  ? {

10     printf("相同\n");

11   }

12  else

13   ? {

14     printf("不相同\n");

15   }

16   ?return 0;

17 }

--------------------------------------

strcmp函數(shù)內(nèi)部可能是如下這樣實(shí)現(xiàn)的:

char a[100] = "abc";

char b[100] = "abc123";

int status = 0;//0代表這兩個(gè)字符串相等憾朴;

//代碼先加一個(gè)判斷,兩個(gè)字符串如果長度不一樣喷鸽,直接設(shè)置status等于1众雷。

int index = 0;

while(a[index])

{

if (a[index] != b[index])

{

status = 1;

break;

}

index++;

}

//這樣就可以通過status的值來判斷兩個(gè)字符串是否相等了。

-----------------------------------------------------------------------------

字符串有限比較函數(shù)strcmp

strncmp函數(shù)的基本用法為:

int strncmp(const char *s1, const char *s2, size_t n);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)靜態(tài)的字符數(shù)組魁衙,第二個(gè)參數(shù)是靜態(tài)的字符數(shù)組报腔,第三個(gè)參數(shù)代表比較幾個(gè)字符。

返回值是:int剖淀。相等返回0纯蛾;不相等返回非0.

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "abc";

7   char b[100] = "hel";

8   if (strncmp(a, b, 2) == 0)

9   {

10     printf("相同\n");

11   ?}

12   ?else

13   ?{

14   ?  ?printf("不相同\n");

15  }

16   ?return 0;

17 }

=============================================================================

字符串拷貝函數(shù)strcpy

strcpy函數(shù)的基本用法為:

char *strcpy(char *dest, const char *src);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)字符數(shù)組,第二個(gè)參數(shù)是靜態(tài)的字符數(shù)組纵隔。

返回值是:一個(gè)字符數(shù)組翻诉。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "abc";

7   char b[100] = "1234";

8    /*

9    //把b的內(nèi)容拷貝到a里面,不使用庫函數(shù)

10  int index = 0;

11   ? while (b[index])

12  {?

13     a[index] = b[index];

14     index++;

15   }

16   */

17  //把b的內(nèi)容拷貝到a里面,使用庫函數(shù)

18  strcpy(a, b);

19  printf("%s\n", a);//1234

20   ?return 0;

21 }

-----------------------------------------------------------------------------

字符串有限拷貝函數(shù)strncpy

strncpy函數(shù)的基本用法為:

char *strncpy(char *dest, const char *src, size_t n);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)靜態(tài)的字符數(shù)組炮姨,第二個(gè)參數(shù)是靜態(tài)的字符數(shù)組,第三個(gè)參數(shù)代表比較幾個(gè)字符碰煌。

返回值是:一個(gè)字符數(shù)組舒岸。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "abc";

7   char b[100] = "1234";

8   //把b的有限內(nèi)容拷貝到a里面,使用庫函數(shù)

9   strncpy(a, b, 2);//strncpy(a, b, sizeof(a) - 1);

10   ?printf("%s\n", a);//12c//123

11   ?return 0;

12 }

=============================================================================

格式化字符串函數(shù)sprintf(輸出)

printf是向標(biāo)準(zhǔn)輸出設(shè)備輸出一個(gè)字符串。

sprintf向一個(gè)char的數(shù)組輸出一個(gè)字符串芦圾。

超級特別注意:可以使用sprintf將一個(gè)int或者其他類型轉(zhuǎn)化為一個(gè)字符串蛾派。

和printf函數(shù)功能類似,printf函數(shù)格式化結(jié)果輸出到屏幕(或標(biāo)準(zhǔn)輸出設(shè)備)个少,

sprintf將格式化結(jié)果輸出到字符串洪乍,并不會(huì)將結(jié)果打印到標(biāo)準(zhǔn)輸出設(shè)備上去。

sprintf使用方法與printf類似夜焦,唯一的區(qū)別是多了第一個(gè)參數(shù)壳澳,第一個(gè)參數(shù)是一個(gè)char的數(shù)組。

sprintf的使用方法和printf基本一致茫经,

特別注意:所有printf的轉(zhuǎn)義符對于sprintf是一樣的巷波。

linux下示例代碼如下:

1 #include

2?

3 int main()

4 {

5   char a[100] = { 0 };

6  ? ?sprintf(a, "%s\n", "hello");    //不加下一句printf,屏幕上什么也不會(huì)輸出卸伞。

7   printf("%s", a);//hello

8   return 0;

9 }?

-----------------------------------------------------------------------------

格式化字符串函數(shù)sscanf(讀取輸入)

scanf從鍵盤讀取用戶輸入數(shù)據(jù)抹镊,sscanf從指定格式化字符串讀取輸入。

即sscanf從某一個(gè)格式化字符串中讀取到我們想要的東西瞪慧,找到后通過轉(zhuǎn)義的方式取出來髓考,取出來后我們就可以繼續(xù)進(jìn)行想要的處理了。

sscanf函數(shù)類似于scanf函數(shù)弃酌,唯一的區(qū)別是多了第一個(gè)參數(shù),第一個(gè)參數(shù)是一個(gè)char的數(shù)組儡炼。

linux下示例代碼如下:

1 #include

2?

3 int main()

4 {

5   char a[100] = "56+72";

6   int i;

7   int j;

8   sscanf(a, "%d+%d", &i, &j);    //sscanf從某一個(gè)格式化字符串中讀取到我們想要的東西妓湘,找到后通過轉(zhuǎn)義的方式取出來。

9   printf("%d+%d=%d\n", i, j, i + j); ?//取出來后我們就可以繼續(xù)進(jìn)行想要的處理了乌询。

10   return 0;

11 }

=============================================================================

課堂小練習(xí):解析一個(gè)字符串

例如:

有一個(gè)字符數(shù)組榜贴,char a[100] = "43+56="; 整數(shù)是任意的,中間可能是 + - * / 任意一個(gè)妹田。

現(xiàn)在寫一個(gè)程序唬党,將計(jì)算的結(jié)果追加到字符串a(chǎn)的后面。也即:程序執(zhí)行完成后a的值是"43+56=99"鬼佣。

linux下示例代碼如下:

1 #include

2?

3 int main()

4 {

5   char a[100] = "56+72=";

6   int i;

7   int j;

8   char c;

9   //printf("%d, %c, %d\n",i, c, j);//打印看看結(jié)果

10  ? sscanf(a, "%d%c%d", &i, &c, &j);//從字符串里面把想要的字符提取出來驶拱。

11?

12   ? int res = 0;

13   switch(c)

14   {

15     case '+':

16       res = i + j;

17       break;

18     case '-':

19       res = i - j;

20       break;

21     case '*':

22       res = i * j;

23       break;

24     case '/':

25       res = i / j;

26       ? ?break;

27     default:

28       res = 0;

29   }

30   sprintf(a, "%d%c%d=%d", i, c, j, res);

31   printf("%s\n", a);

32   return 0;

33 }

=============================================================================

字符串查找字符函數(shù)strchr

strchr函數(shù)的基本用法為:

char *strchr(const char *s, int c); //功能:在指定的字符串里面找指定的相關(guān)字符的子串。

參數(shù)是:第一個(gè)參數(shù)是一個(gè)靜態(tài)的字符數(shù)組晶衷,第二個(gè)參數(shù)是int(其實(shí)是一個(gè)字符的ASCII)蓝纲。

返回值是:一個(gè)字符數(shù)組阴孟。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "hello world";

7   char *s;//定義了一個(gè)char類型的指針變量

8   s = strchr(a, 'l');//注意是一個(gè)字符

9?

10   ?if (s != NULL)

11   ? {

12     printf("%s\n", s); //llo world

13   }?

14   return 0;

15 }

-----------------------------------------------------------------------------

字符串查找子串函數(shù)strstr

strstr函數(shù)的基本用法為:

char *strstr(const char *haystack, const char *needle);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)靜態(tài)的字符數(shù)組,第二個(gè)參數(shù)也是靜態(tài)的字符數(shù)組(其實(shí)是一個(gè)字符串)税迷。

返回值是:一個(gè)字符數(shù)組永丝。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "hello world";

7   char *s;//定義了一個(gè)char類型的指針變量

8   s = strstr(a, "wo");//注意是一個(gè)字符串

9?

10  if (s != NULL)

11   {

12      printf("%s\n", s);//world

13   }

14   return 0;

15 }

strchr與strstr如果找不到,返回NULL(空指針)箭养。

=============================================================================

字符串分割函數(shù)strtok

strtok函數(shù)的基本用法為:

char *strtok(char *str, const char *delim);

參數(shù)是:第一個(gè)參數(shù)是一個(gè)字符數(shù)組慕嚷;第二個(gè)參數(shù)也是一個(gè)靜態(tài)的字符數(shù)組(其實(shí)是一個(gè)字符串)。

返回值是:一個(gè)字符數(shù)組毕泌。

注意:

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "abc_565656_asadsd";

7   char *s;  //定義一個(gè)char的指針變量

8   s = strtok(a, "_");

9   printf("%s\n", s);//abc

10?

11   ?s = strtok(NULL, "_");  //注意:在第二次至以后調(diào)用strtok函數(shù)時(shí)闯冷,第一個(gè)參數(shù)寫NULL。

12   ?printf("%s\n", s);//565656

13?

14   ?s = strtok(NULL, "_");

15   ?printf("%s\n", s);//asadsd

16?

17   ?s = strtok(NULL, "_");

18   ?printf("%s\n", s);  //Segmentation fault(分段故障)

19 ? ? ? return 0;

20?

21 }

如果要分割的字符串已經(jīng)到了字符串結(jié)尾懈词,若繼續(xù)調(diào)用strtok則返回Segmentation fault(分段故障)蛇耀。

-----------------------------------------------------------------------------

上面代碼的簡化代碼如下:

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "abc_565656_asadsd";

7   char *s;//定義一個(gè)char的指針變量

8   s = strtok(a, "_");

9?

10   ?while (s) //當(dāng)s = NULL時(shí),就是0,0就是假坎弯。

11 ? ? ?{

12     printf("%s\n", s);

13     s = strtok(NULL, "_");

14   ?}

15     return 0;

16?

17 }

=============================================================================

atoi函數(shù)

atoi函數(shù)的功能是:把一個(gè)char的數(shù)組轉(zhuǎn)化為一個(gè)int纺涤,需要頭文件stdlib.h。

int atoi(const char *nptr);

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "123";  //如何把一個(gè)字符串轉(zhuǎn)化為一個(gè)整數(shù)抠忘?

7   char b[100] = "500";

8?

9   int i = 0;

10  ?i = atoi(a) + atoi(b);

11   printf("%d\n", i);//623

12   return 0;

13 }

-----------------------------------------------------------------------------

atof函數(shù)

atof函數(shù)的功能是:把一個(gè)小數(shù)形式的字符轉(zhuǎn)化為一個(gè)浮點(diǎn)數(shù)撩炊。

double atof(const char *nptr);

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "123.5";

7   char b[100] = "500.489";

8?

9   double i = 0;

10  ? i = atof(a) + atof(b);

11   ?printf("%f\n", i);

12   ?return 0;

13 }

-----------------------------------------------------------------------------

atol函數(shù)

atol函數(shù)的功能是:把一個(gè)字符串轉(zhuǎn)化為long類型。

long atol(const char *nptr);

long long atoll(const char *nptr);

-----------------------------------------------------------------------------

在c語言里面提供了把字符串轉(zhuǎn)化為整數(shù)的函數(shù)崎脉,但并沒有提供把整數(shù)轉(zhuǎn)化為字符串的函數(shù)拧咳,

即:atoi是標(biāo)準(zhǔn)的c語言庫函數(shù),itoa不是c語言標(biāo)準(zhǔn)的庫函數(shù)囚灼。(itoa可以在vs2017下編譯骆膝,但在其他系統(tǒng)下就未知了。)

所以不要嘗試使用itoa這種函數(shù)灶体,可以使用sprintf將一個(gè)int或者其他類型轉(zhuǎn)化為一個(gè)字符串阅签。

即:sprintf可以實(shí)現(xiàn)將數(shù)字轉(zhuǎn)化為字符串的功能。

linux下示例代碼如下:

1 #include

2 #include

3?

4 int main()

5 {

6   char a[100] = "1234";

7   char b[100] = "abc";

8   int c = 45;

9   sprintf(a, "%d", c);  //a[100] = "45";

10   ?strcat(b, a);

11   ?printf("%s\n", b);  //abc45

12   ?return 0;

13 }

=============================================================================

課堂小練習(xí):解析一個(gè)字符串的高級應(yīng)用

例如:

有一個(gè)字符數(shù)組 char a[100] = "12+5=;45-2=;34*2=;54/3=";

這個(gè)字符數(shù)組到底有多少分號(hào)是不確定的蝎抽,

寫個(gè)程序政钟,執(zhí)行后"="號(hào)后面自動(dòng)添加計(jì)算結(jié)果。如下:

“12+5=17;45-2=43;34*2=68;54/3=18”

linux下示例代碼如下:

1 #include

2 #include

3 #include

4?

5 int main()

6 {

7    char a[100] = "12+5=;45-2=;34*2=;54/3=";

8    char b[100] = { 0 };//注意:b是空串罢两帷Q弧!瓢宦!

9    char *s = strtok(a, ";");

10   while (s)

11    {

12       //printf("%s\n", s);

13       int i, j;

14       char c;

15       sscanf(s, "%d%c%d=", &i, &c, &j);

16?

17      int res = 0;

18     ?switch (c)

19     {

20        case '+':

21          res = i + j;

22         break;

23        case '-':

24          res = i - j;

25          break;

26        case '*':

27          res = i * j;

28          break;

29        case '/':

30          res = i / j;

31          break;

32        defalut:

33        res = 0;

34      }

35      //printf("%s%d\n", s, res);

36      //printf("%s%d", s, res);

37      char tmp[10] = { 0 };

38      sprintf(tmp, "%s%d;", s, res);

39      strcat(b, tmp);

40    ? s =strtok(NULL, ";");

41   }

42    strcpy(a, b);

43    printf("%s\n", a);

44    return 0;

45 }

=============================================================================

函數(shù)的定義和聲明

前幾節(jié)學(xué)習(xí)c語言庫函數(shù)的使用碎连,而實(shí)際呢?我們有必要去自己寫函數(shù)刁笙,因?yàn)閏語言庫函數(shù)并不能滿足我們所有的應(yīng)用。即自定義函數(shù)。

在使用函數(shù)前必須要定義或者聲明函數(shù)或者就把整個(gè)函數(shù)寫在main函數(shù)的上面嫌套。

特備注意:自己定義的函數(shù)有兩種聲明有兩種格式。

linux下示例代碼如下:

1 #include

2?

3 //調(diào)用函數(shù)的聲明前鹅。

4 void test1();?

5?

6 //這是一個(gè)自定義的函數(shù),函數(shù)名叫add峭梳,返回值類型是int類型舰绘,函數(shù)有兩個(gè)參數(shù),分別是a和b葱椭。

7 int add(int a, int b)

8 {?

9    return a + b;

10 }

11?

12 //這是一個(gè)自定義的函數(shù)捂寿,函數(shù)名叫test,沒有返回值孵运,沒有參數(shù)秦陋。

13 void test()

14 {?

15    printf("test\n");

16 }

17?

18 void test2(int a) //a是形參。

19 {?

20    printf("a = %d\n", a);

21 }

22?

23 int main()

24 {?

25    int i = 2;

26    int j = 5;

27    int c = add(i, j); //調(diào)用一個(gè)有參數(shù)治笨,有返回值的函數(shù)驳概。

28    printf("%d\n", c);

29    test(); //調(diào)用一個(gè)沒有參數(shù),沒有返回值的函數(shù)旷赖。

30    test1(); //調(diào)用一個(gè)沒有參數(shù)顺又,沒有返回值的函數(shù)。注意這種調(diào)用方式需要在前面進(jìn)行聲明等孵。

31    test2(j); //j是實(shí)參稚照。  //test2(8);  //test2(20 + 4);  //test(i + j);

32    return 0;

33 }

-----------------------------------------------------------------------------

函數(shù)的形式參數(shù)(形參)與實(shí)際參數(shù)(實(shí)參)

在調(diào)用函數(shù)的時(shí)候俯萌,函數(shù)大多數(shù)都有參數(shù)果录,主調(diào)函數(shù)和被調(diào)函數(shù)之間需要傳遞數(shù)據(jù)。

在定義函數(shù)時(shí)函數(shù)名后面括弧中的變量名稱為“形式參數(shù)”绳瘟,簡稱形參雕憔。

在調(diào)用函數(shù)時(shí),函數(shù)名后面的括弧中的變量或者表達(dá)式稱為“實(shí)際參數(shù)”糖声,簡稱實(shí)參。

注意幾點(diǎn):

1分瘦、形參在未出現(xiàn)函數(shù)調(diào)用的時(shí)蘸泻,他們并不占用內(nèi)存單元,只有在發(fā)生函數(shù)調(diào)用的時(shí)候形參才被分配內(nèi)存嘲玫,函數(shù)調(diào)用完成后悦施,形參所占用的內(nèi)存被釋放。

2去团、實(shí)參可以使變量抡诞、常量或者表達(dá)式穷蛹。

3、在定義函數(shù)時(shí)昼汗,一定要指定形參的數(shù)據(jù)類型肴熏。

4、形參與實(shí)參的數(shù)據(jù)類型一定可兼容顷窒。

5蛙吏、在c語言中,實(shí)參與形參的數(shù)據(jù)傳遞是“值的傳遞”鞋吉,即單向傳遞鸦做,即只由實(shí)參傳遞給形參,而不能有形參傳遞給實(shí)參谓着。

即:

實(shí)參的值單向的給形參泼诱,但形參的值不會(huì)傳遞給實(shí)參。

形參的值來自于實(shí)參赊锚,但形參的值改變后并不會(huì)改變實(shí)參的值治筒。

linux下示例代碼如下:

1 #include

2?

3 void test2(int a)

4 {

5    ++a;

6    printf("a = %d\n", a);

7 }

8?

9 int main()

10 {

11    int i = 5;

12    test2(i);

13    printf("i = %d\n", i);//輸出:a = 6 i = 5

14    return 0;

15 }

-------------------------------------

小知識(shí)復(fù)習(xí):

b = a++; //先計(jì)算表達(dá)式的值,即先把a(bǔ)賦值給了b改抡;然后a再自加1矢炼。

b = ++a; //先a自加1后阿纤;然后把a(bǔ)自加后得到的賦值給b句灌。

小結(jié):誰在前面先計(jì)算誰!G肥啊胰锌!

-------------------------------------

-----------------------------------------------------------------------------

函數(shù)的返回值類型和返回值

1、函數(shù)的返回值通過函數(shù)中的return獲得的藐窄,如果函數(shù)的返回值為void资昧,則不需要return語句。

2荆忍、函數(shù)ruturn語句中的返回值數(shù)據(jù)類型應(yīng)該與定義函數(shù)時(shí)相同格带。

3、如果函數(shù)中沒有return語句刹枉,那么函數(shù)將返回一個(gè)不確定的值叽唱。

-----------------------------------------------------------------------------

return函數(shù)與exit函數(shù)(exit更猛,不受位置限制)

exit是c語言的庫函數(shù)微宝,有一個(gè)整型的參數(shù)棺亭,代表進(jìn)程終止。使用這個(gè)函數(shù)需要stdlib.h這個(gè)頭文件蟋软。

在函數(shù)中寫return只是代表函數(shù)終止了镶摘,但不管在程序的任何位置調(diào)用exit嗽桩,那么整個(gè)程序馬上終止了。

在main函數(shù)中執(zhí)行return語句凄敢,程序終止碌冶,但在子函數(shù)中執(zhí)行return只是子函數(shù)終止了,但main依舊運(yùn)行贡未。

在main函數(shù)中執(zhí)行return或者調(diào)用exit結(jié)果是一樣的种樱。

=============================================================================

課堂小練習(xí):

自定義一個(gè)函數(shù),實(shí)現(xiàn)大小寫字母的互相轉(zhuǎn)換功能俊卤。

例如:小寫的a的ASCII是97嫩挤,大寫的A的ASCII是65。

其實(shí)大小寫字母的ASCII相差是32哦消恍,但空格的ASCII是32岂昭。

linux下示例代碼如下:

1 #include

2?

3 char trans(char c)

4 {

5    if (c >= 'a' && c <= 'z')

6    {

7      return c - ' ';

8    }

9    if (c >= 'A' && c <= 'Z')

10   {

11     return c + ' ';

12    }

13 }?

14?

15 int main()

16 {

17    char a = 'r';

18    printf("%c\n", trans(a));

19    return 0;

20 }

-----------------------------------------------------------------------------

c語言有個(gè)庫函數(shù),名字叫atoi狠怨,將一個(gè)字符串轉(zhuǎn)化為整數(shù)约啊。

自定義一個(gè)函數(shù),實(shí)現(xiàn)atoi的功能佣赖,要求是不能使用任何c語言已有的庫函數(shù)恰矩。

"123"

'1' '2''3' '\0'

步驟:

0、首先知道這個(gè)字符串有多長憎蛤。(如果字符串是3位長外傅,那么第一位 * 10 2次方。)

1俩檬、遍歷這個(gè)字符串萎胰。

2、將第一個(gè)'1'取出來棚辽,然后把'1'轉(zhuǎn)化為整數(shù)1技竟,把1 * 100。

將'2'取出來屈藐,轉(zhuǎn)化為2榔组,2 * 10。

將'3'取出來联逻,轉(zhuǎn)化為3瓷患。

3、1 * 100 + 2 * 10 + 3 = 123遣妥;

注意:'0'的ASCII的值是48,'1'的ASCII的值是49攀细,'2'的ASCII的值是50等等箫踩。

所以字符1('1')轉(zhuǎn)換為數(shù)字1(1)就是讓字符1減去字符0可得爱态,

即?

0 = '0' - '0',

1 = '1' - '0'境钟,

2 = '2' - '0'锦担,

......

linux下示例代碼如下:

1 #include

2?

3 //得到一個(gè)字符串長度的函數(shù)

4 int my_strlen(const char *s)

5 {

6    int len = 0;

7    while (s[len])

8    {

9      len++;

10   }

11   return len;

12 }

13?

14 //得到10的n次方的函數(shù)

15 int my_pow10(int n)

16 {

17    if (n == 0) //10的0次方

18    return 1;

19    if (n == 1) //10的1次方

20    return 10;

21?

22    int base = 10;

23    int i;

24    for (i = 1; i < n; i++)

25    {

26      base *= 10;

27    }

28   return base;

29 }

30?

31 //把一個(gè)字符轉(zhuǎn)換為一個(gè)0到9整數(shù)的函數(shù)

32 int my_chartoint(char c)

33 {

34    return c - '0';

35 }

36?

37 //把一個(gè)字符串轉(zhuǎn)化為整數(shù)的函數(shù)

38 int my_atoi(const char *nptr)

39 {

40    int len = my_strlen(nptr);

41?

42    int value = 0;

43    int i;

44    for (i = 0; i < len; i++)

45   {

46      value += my_chartoint(nptr[i]) * my_pow10(len - 1 - i);

47    }

48    return value;

49?}

50?

51 int main()

52 {

53    char a[] = "123";

54    int i = my_atoi(a);

55    printf("%d\n", i);

56  ? return 0;

57 }

=============================================================================

函數(shù)的遞歸

函數(shù)可以自己調(diào)用自己,這就叫函數(shù)的遞歸慨削。

linux下示例代碼如下:

典型的遞歸代碼:

1 #include

2?

3 void test(int n)

4 {

5    printf("n = %d\n", n);

6    if (n < 3)

7    {

8      test(n + 1);

9   }

10 }

11?

12 int main()

13 {

14    int a = 0;

15    test(a);

16    return 0;

17 }

輸出

n = 0

n = 1

n = 2

n = 3

-----------------------------------------------------------------------------

1 #include

2?

3 void test(int n)

4 {

5    //printf("n = %d\n", n);

6    if (n < 3)

7    {

8      test(n + 1);

9    }

10     ? printf("n = %d\n", n);

11 }

12?

13 int main()

14 {?

15    int a = 0;

16    test(a);

17    return 0;

18 }

輸出

n = 3

n = 2

n = 1

n = 0

-----------------------------------------------------------------------------

即:

test(0)

{

  test(1)

  {

    test(2)

    {

      test(3)

      {

        不符合條件退出if判斷語句了洞渔。

        printf("n = %d\n", n);//第一次輸出:n = 3

      }

      printf("n = %d\n", n);//第二次輸出:n = 2

    }

    printf("n = %d\n", n);//第三次輸出:n = 1

  }

  printf("n = %d\n", n);//第四次輸出:n = 0

}

-----------------------------------------------------------------------------

1 #include

2?

3 void test(int n)

4 {

5    printf("n = %d\n", n);//把代碼放到遞歸的前面,叫做先序遞歸缚态。

6    if (n < 3)//遞歸一定要有個(gè)終止條件磁椒。

7    {

8      test(n + 1);

9  ? }

10     ?printf("n = %d\n", n);//把代碼放到遞歸的后面,叫做后序遞歸玫芦。

11 }

12?

13 int main()

14 {?

15    int a = 0;

16    test(a);

17    return 0;

18 }

輸出

n = 0

n = 1

n = 2

n = 3

n = 3

n = 2

n = 1

n = 0

-----------------------------------------------------------------------------

遞歸例子:

有n個(gè)人排成一隊(duì)浆熔,

問第n個(gè)人多少歲,他回答比前面一個(gè)人大2歲桥帆,

再問前面一個(gè)人多少歲医增,他回答比前面一個(gè)人大2歲,

一直問到最后面的一個(gè)人老虫,他回答他是10歲叶骨。

linux下示例代碼如下:

1 #include

2?

3 int age(int n)

4 {

5    if (n == 1) //終止條件

6    {

7      return 10;

8    }

9    else

10   ?{

11     return age(n - 1) + 2;

12   ?}

13 }

14?

15 int main()

16 {

17    int a = 5;

18    printf("%d\n", age(a));//18

19 }

-----------------------------------------------------------------------------

遞歸例子:

將10進(jìn)制數(shù)轉(zhuǎn)化為二進(jìn)制數(shù)。

例如:求十進(jìn)制數(shù)13的二進(jìn)制數(shù)祈匙。

2 13?

6    1

3    0

1    1

0    1

商數(shù)   余數(shù)

倒過來看余數(shù)得:

(13)10 = (1101)2

linux下示例代碼如下:

1 #include

2?

3 void to_bin(unsigned int n)

4 {

5    int i = n % 2;//得到余數(shù)

6 ? ? ? ?//printf("%d\n", i);//看一下忽刽,輸出的余數(shù)。發(fā)現(xiàn)是先序遞歸菊卷。而我們需要的二進(jìn)制需要倒過來缔恳,該如何呢?用后序遞歸洁闰。

7?

8    if (n > 2)

9    {

10      to_bin(n / 2);

11   }

12?

13    printf("%d", i);

14?

15 }

16?

17 int main()

18 {

19    int a = 1300;

20    scanf("%d", &a);

21    to_bin(a);

22    printf("\n");

23    return 0;

24 }

-----------------------------------------------------------------------------

遞歸例子:

寫一個(gè)函數(shù)歉甚,將10進(jìn)制數(shù)轉(zhuǎn)化為16進(jìn)制,不能使用c語言庫函數(shù)扑眉。

不能如下這樣爸叫埂:

void to_hex(int n)

{

printf("%x", n);

}

例如:求十進(jìn)制數(shù)130的十六進(jìn)制數(shù)。

16 130?

8  2

0   8

商數(shù) ? 余數(shù)

倒過來看余數(shù)得:

(130)10 = (82)16

linux下示例代碼如下:

1 #include

2?

3 char hex_char(unsigned int n)

4 {

5    switch (n)

6    {

7      case 0:

8        return '0';

9      case 1:

10       ? return '1';

11     case 2:

12       ? return '2';

13     case 3:

14       ? return '3';

15     case 4:

16       return '4';

17     case 5:

18       return '5';

19     case 6:

20       return '6';

21     case 7:

22       return '7';

23     case 8:

24      return '8';

25     case 9:

26       return '9';

27     case 10:

28        ?return 'a';

29     ? case 11:

30       ? return 'b';

31     case 12:

32       ? return 'c';

33     case 13:

34       ? ?return 'd';

35     case 14:

36       return 'e';

37     case 15:

38       return 'f';

39   }

40   return '0';

41 }

42?

43 void to_hex(unsigned int n)

44 {

45    int i = n % 16;//得到余數(shù)

46    //printf("%d\n", i);//看一下腰素,輸出的余數(shù)聘裁。發(fā)現(xiàn)是先序遞歸。而我們需要的二進(jìn)制需要倒過來弓千,該如何呢衡便?用后序遞歸。

47?

48    if (n > 16)

49   {

50      to_hex(n / 16);

51    }

52?

53    printf("%c",hex_char(i));

54?

55 }

56?

57 int main()

58 {

59   int a = 1300;

60    scanf("%d", &a);

61    to_hex(a);

62    printf("\n");

63    return 0;

64 }

-----------------------------------------------------------------------------

遞歸例子:

菲波那切數(shù)列:

0,1镣陕,1谴餐,2,3呆抑,5岂嗓,8,13鹊碍,21厌殉,34,55侈咕,89公罕,144,......

第零項(xiàng)是0乎完;

第一項(xiàng)是1熏兄;

第二項(xiàng)是1;

第三項(xiàng)是2树姨;

第四項(xiàng)是3摩桶;

......

該數(shù)列從第二項(xiàng)開始,每一項(xiàng)等于前兩項(xiàng)之和帽揪。

linux下示例代碼如下:

1 #include

2?

3 int fib(int n)

4 {

5    if (n == 0)

6       return 0;

7    if (n == 1)

8       return 1;

9    if (n > 1)

10      return fib(n - 1) + fib(n - 2);

11 }

12?

13 int main()

14 {

15   int i;

16   for (i = 0; i < 20; i++)

17    {

18      printf("%d\n", fib(i));

19    }

20    return 0;

21 }

-----------------------------------------------------------------------------

遞歸的優(yōu)點(diǎn):

遞歸給某些編程問題提供了簡單的方法硝清。

遞歸缺點(diǎn):

一個(gè)有缺陷的遞歸會(huì)很快耗盡計(jì)算機(jī)的資源,遞歸的程序難以理解和維護(hù)转晰。

筆試的時(shí)候很可能考遞歸哦芦拿!考驗(yàn)的是智力和思維的能力。

因?yàn)樗哪莻€(gè)圖想起來很費(fèi)勁查邢!需要多加訓(xùn)練蔗崎。

聯(lián)想到我們小時(shí)候聽說的一個(gè)故事:從前有座山,山里有座廟......

或者是畫中畫的放大與縮小的效應(yīng)扰藕。

=============================================================================

多個(gè)源代碼文件程序如何編譯缓苛?

1、頭文件的使用

如何把我們的代碼分解為多個(gè)函數(shù)邓深,如何把函數(shù)放進(jìn)不同的文件里面未桥。

因?yàn)閷?shí)際中我們的函數(shù)是散落在多個(gè)文件里面的。

-----------------------------------------------------------------------------

方法一:

如果把main函數(shù)放在第一個(gè)文件中芥备,而把自定義的函數(shù)放在第二個(gè)文件中冬耿,

那么調(diào)用第二個(gè)文件中的自定義函數(shù)時(shí)就要在第一個(gè)文件中聲明該函數(shù)原型。

方法二:

如果把很多個(gè)函數(shù)原型包含在一個(gè)頭文件里萌壳,那么就不必每次使用自定義的函數(shù)的時(shí)候去聲明函數(shù)原型了亦镶。

把函數(shù)聲明放入頭文件是個(gè)很好的習(xí)慣H赵隆!染乌!

-----------------------------------------------------------------------------

方法一:

如果把main函數(shù)放在第一個(gè)文件中山孔,而把自定義的函數(shù)放在第二個(gè)文件中,

那么調(diào)用第二個(gè)文件中的自定義函數(shù)時(shí)就要在第一個(gè)文件中聲明該函數(shù)原型荷憋。

(即自定義函數(shù)的申明放在有main函數(shù)的第一個(gè)文件中,自定義函數(shù)的定義放在第二個(gè)文件中)

需要在編譯的時(shí)候?qū)Χ哌M(jìn)行一起編譯才行哦褐望!

------------------------------------

例如:

第一個(gè)文件func9.c:

#include

int max(int a, int b);

int add(int a, int b);

int main()

{

int a = 10;

int b = 20;

printf("%d\n", max(a, b));

printf("%d\n", add(a, b));

return 0;

}

------------------------------------

第二個(gè)文件aa.c:

int max(int a, int b)

{

return (a > b) ? a : b;

}

int add(int a, int b)

{

return a + b;

}

一起進(jìn)行編譯:gcc -o f9 func9.c aa.c

-----------------------------------------------------------------------------

上面方法一在主函數(shù)里面聲明函數(shù)原型比較啰嗦勒庄,我們一般不這么做!我們一般用方法二:

方法二:

如果把很多個(gè)函數(shù)聲明原型包含在一個(gè)頭文件里瘫里,那么就不必每次使用自定義的函數(shù)的時(shí)候去聲明函數(shù)原型了实蔽。

把函數(shù)聲明放入頭文件是個(gè)很好的習(xí)慣!=鞫痢局装!

------------------------------------

第一個(gè)文件func9.c:

#include

#include "aa.h"http://雙引號(hào)表示在當(dāng)前目錄下

int main()

{

int a = 10;

int b = 20;

printf("%d\n", max(a, b));

printf("%d\n", add(a, b));

return 0;

}

------------------------------------

第二個(gè)文件aa.c:

#include

int max(int a, int b)

{

return (a > b) ? a : b;

}

int add(int a, int b)

{

return a + b;

}

------------------------------------

第三個(gè)文件aa.h:

int max(int a, int b);

int add(int a, int b);

一起進(jìn)行編譯:gcc -o f9 func9.c aa.c

-----------------------------------------------------------------------------

其實(shí)方法二也有些問題!

如果第一個(gè)文件func9.c中多次出現(xiàn)include劳殖,如下這一句:

#include "a.h"

#include "a.h"

#include "a.h"

進(jìn)行預(yù)編譯:gcc -o ff func9.c -E

則預(yù)編譯時(shí)會(huì)出現(xiàn)多次函數(shù)聲明铐尚!那么如何避免多次出現(xiàn)include呢?

(問題如下圖)

-----------------------------------------------------------------------------

#include 是預(yù)編譯指令哆姻,代表頭文件包含宣增。

#define 定義一個(gè)宏常量。

學(xué)習(xí) #ifdef 與 #ifndef矛缨。

#ifdef 是個(gè)預(yù)編譯指令爹脾,代表只要定義了一個(gè)宏常量,那么就預(yù)編譯下面的代碼箕昭。

#ifndef 是個(gè)預(yù)編譯指令灵妨,代表只要沒有定義了一個(gè)宏常量,那么就預(yù)編譯下面的代碼落竹。

格式如下:

#define 宏

#ifdef 宏

代碼

#endif

演示如下圖:

還有另一種寫法哦泌霍,這里不再贅述!

------------------------------------

鑒于此筋量,我們對aa.h進(jìn)行改造烹吵。

#ifndef _A_H

#define _A_H

int max(int a, int b);

int add(int a, int b);

#endif

//這樣寫的效果是:不管這個(gè)頭文件被包含多少次,只有一次生效桨武。

//這是c語言大多數(shù)的頭文件都會(huì)寫成這個(gè)樣子肋拔,這樣會(huì)避免被多次預(yù)編譯。

.c文件里面放的是函數(shù)的定義呀酸。

.h文件里面放的是函數(shù)的聲明凉蜂。

=============================================================================

“我是一名從事了10年開發(fā)的老程序員,最近我花了一些時(shí)間整理關(guān)于C語言、C++窿吩,自己有做的材料的整合茎杂,一個(gè)完整的學(xué)習(xí)C語言、C++的路線纫雁,學(xué)習(xí)材料和工具煌往。C/C++、編程愛好者的聚集地就在我這里 <進(jìn)入下方專欄就能看到及領(lǐng)取>轧邪!歡迎初學(xué)和進(jìn)階中的小伙伴刽脖。希望你也能憑自己的努力,成為下一個(gè)優(yōu)秀的程序員忌愚。工作需要曲管、感興趣、為了入行硕糊、轉(zhuǎn)行需要學(xué)習(xí)C/C++的伙伴可以跟我一起學(xué)習(xí)院水!”

關(guān)注我的專欄,帶你遨游代碼世界简十!C語言/C++進(jìn)階之路 - 專題 - 簡書

最后分享一張C/C++學(xué)習(xí)路線圖給愛學(xué)習(xí)的小伙伴們

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末檬某,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子勺远,更是在濱河造成了極大的恐慌橙喘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胶逢,死亡現(xiàn)場離奇詭異厅瞎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)初坠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門和簸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碟刺,你說我怎么就攤上這事锁保。” “怎么了半沽?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵爽柒,是天一觀的道長。 經(jīng)常有香客問我者填,道長浩村,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任占哟,我火速辦了婚禮心墅,結(jié)果婚禮上酿矢,老公的妹妹穿的比我還像新娘。我一直安慰自己怎燥,他們只是感情好瘫筐,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铐姚,像睡著了一般策肝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谦屑,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天驳糯,我揣著相機(jī)與錄音,去河邊找鬼氢橙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恬偷,可吹牛的內(nèi)容都是我干的悍手。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼袍患,長吁一口氣:“原來是場噩夢啊……” “哼坦康!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诡延,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤滞欠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后肆良,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筛璧,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年惹恃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了夭谤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡巫糙,死狀恐怖朗儒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情参淹,我是刑警寧澤醉锄,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站浙值,受9級特大地震影響恳不,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜亥鸠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一妆够、第九天 我趴在偏房一處隱蔽的房頂上張望识啦。 院中可真熱鬧,春花似錦神妹、人聲如沸颓哮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冕茅。三九已至,卻和暖如春蛹找,著一層夾襖步出監(jiān)牢的瞬間姨伤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工庸疾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乍楚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓届慈,卻偏偏與公主長得像徒溪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子金顿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容