C語言的羅盤指針——深入理解C語言指針及其應(yīng)用

      網(wǎng)友投稿 1017 2025-04-05

      ??前面的話??

      前面已經(jīng)簡(jiǎn)要介紹了數(shù)組指針,字符串庫函數(shù)和指針等內(nèi)容,在這篇文章我們將繼續(xù)深入了解有關(guān)字符串庫函數(shù)和指針的探索。

      1.字符指針與字符串

      字符指針即指向字符類型的指針。

      char* pch = NULL; char ch = 's'; pch = &ch;//字符指針

      1.1字符指針與字符串的關(guān)系

      在C語言中,并沒有字符串這種數(shù)據(jù)類型,但是在編程中又常常遇到字符串,那在C語言中然后去表達(dá)字符串呢?

      有兩種方式,一是使用字符數(shù)組表示字符串,本質(zhì)上就是定義一個(gè)char類型的數(shù)組變量去儲(chǔ)存字符串,使用字符數(shù)組表示字符串得到的是一個(gè)字符串變量,它是能夠被修改的;二是使用字符指針的方式去表達(dá)字符串,本質(zhì)上就是使用一個(gè)char指針指向字符串的第一個(gè)字符,因?yàn)樵谳敵鲎址臅r(shí)候計(jì)算機(jī)是以

      有兩種方式,一是使用字符數(shù)組表示字符串,本質(zhì)上就是定義一個(gè)char類型的數(shù)組變量去儲(chǔ)存字符串,使用字符數(shù)組表示字符串得到的是一個(gè)字符串變量,它是能夠被修改的;二是使用字符指針的方式去表達(dá)字符串,本質(zhì)上就是使用一個(gè)char指針指向字符串的第一個(gè)字符,因?yàn)樵谳敵鲎址臅r(shí)候計(jì)算機(jī)是以\0為標(biāo)志來打印字符串的。但是要注意的是,它和使用字符數(shù)組不同,字符數(shù)組定義的是一個(gè)字符串變量,而字符指針定義的是一個(gè)字符串常量,是不能進(jìn)行修改的。

      為標(biāo)志來打印字符串的。但是要注意的是,它和使用字符數(shù)組不同,字符數(shù)組定義的是一個(gè)字符串變量,而字符指針定義的是一個(gè)字符串常量,是不能進(jìn)行修改的。

      #include int main() { char str1[40] = "Come on, China Olympic Games!";//使用字符數(shù)組定義字符串變量 char* str2 = "Come on, China Olympic Games!";//使用字符指針定義字符串常量 printf("str1:%s\nstr2:%s\n", str1, str2); return 0; }

      :bulb:運(yùn)行結(jié)果:

      str1:Come on, China Olympic Games! str2:Come on, China Olympic Games! D:\gtee\C-learning-code-and-project\test_813\Debug\test_813.exe (進(jìn)程 6960)已退出,代碼為 0。 按任意鍵關(guān)閉此窗口. . .

      如果不小心對(duì)字符串常量修改,會(huì)引發(fā)讀寫訪問沖突的異常,對(duì)于VS這個(gè)異常只有在調(diào)試的時(shí)候才能看得見而在編譯的時(shí)候是不會(huì)報(bào)警告或者報(bào)錯(cuò)的,萬一是在一個(gè)很大的工程中出現(xiàn)了這種問題,是很難察覺的,所以一般定義一個(gè)不能被修改的變量或常量的時(shí)候,一般在定義的數(shù)據(jù)類型前面加上一個(gè)const,這樣如果不小心修改了這個(gè)const修飾的變量或常量,編譯器在編譯的時(shí)候就會(huì)報(bào)錯(cuò),這樣就能更容易地發(fā)現(xiàn)讀寫沖突異常的情況。

      :bulb:面試題:

      #include int main() { char str1[] = "hello str."; char str2[] = "hello str."; char* str3 = "hello str."; char* str4 = "hello str."; if (str1 == str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if (str3 == str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }

      使用字符數(shù)組表達(dá)的是字符串變量,本質(zhì)就是數(shù)組,每個(gè)數(shù)組是獨(dú)立儲(chǔ)存的,所以就算兩個(gè)數(shù)組儲(chǔ)存相同的內(nèi)容,但是兩者地址一定是不相同的。

      而使用字符指針表達(dá)的是字符串常量,所以內(nèi)容相同,字符指針指向的就是同一個(gè)地址。

      知道了這個(gè)區(qū)別,那這道面試題也能迎刃而解了。

      :bulb:運(yùn)行結(jié)果:

      str1 and str2 are not same str3 and str4 are same D:\gtee\C-learning-code-and-project\test_813\Debug\test_813.exe (進(jìn)程 16488)已退出,代碼為 0。 按任意鍵關(guān)閉此窗口. . .

      1.2常用的幾個(gè)字符串庫函數(shù)

      在前面介紹字符數(shù)組的時(shí)候簡(jiǎn)要提到了這幾個(gè)與字符串相關(guān)的庫函數(shù),現(xiàn)在我將詳細(xì)介紹這些常用的庫函數(shù)。

      1.2.1輸出輸入字符串的函數(shù)

      puts(字符數(shù)組);//輸出 int puts(const char* string); gets(字符數(shù)組);//輸入 char* gets(char* buffer);

      :mag_right:puts:函數(shù)所在庫為stdio.h;函數(shù)參數(shù)為const修飾的char*類型(使用const修飾是為了防止字符串被修改);函數(shù)返回值為int,如果函數(shù)執(zhí)行失敗則會(huì)返回EOF。

      :mag_right:gets:函數(shù)所在庫為stdio.h;函數(shù)參數(shù)為char*類型(從緩沖區(qū)讀取一行字符串,buffer是緩沖區(qū)的意思);函數(shù)返回值為char*(字符串的第一個(gè)元素地址),函數(shù)不能傳入空指針,如果函數(shù)執(zhí)行失敗會(huì)返回EOF。

      用puts和gets函數(shù)只能輸出或輸入一個(gè)字符串。

      puts作用:將一個(gè)字符串(以′

      puts作用:將一個(gè)字符串(以′\0′結(jié)束的字符序列)輸出到終端。

      ′結(jié)束的字符序列)輸出到終端。

      用puts函數(shù)輸出的字符串中可以包含轉(zhuǎn)義字符。

      在用puts輸出時(shí)將字符串結(jié)束標(biāo)志′

      在用puts輸出時(shí)將字符串結(jié)束標(biāo)志′\0′轉(zhuǎn)換成′\n′,即輸出完字符串后換行。

      ′轉(zhuǎn)換成′\n′,即輸出完字符串后換行。

      gets作用:從終端輸入一個(gè)字符串到字符數(shù)組,并且得到一個(gè)函數(shù)值。該函數(shù)值是字符數(shù)組的起始地址。

      1.2.2字符串連接函數(shù)

      strcat(字符串1, 字符串2); char *strcat( char *strDestination, const char *strSource );

      :mag_right:strcat:函數(shù)所在庫為string.h;函數(shù)參數(shù)有兩個(gè),第一個(gè)為char*類型(目的字符串地址)第二個(gè)參數(shù)為const char*類型(被連接字符串的地址);函數(shù)返回值為char*(返回strDestination的元素地址)。

      strcat函數(shù)將strSource追加到strDestination后面。

      strcat作用:把兩個(gè)字符數(shù)組中的字符串連接起來,把字符串2接到字符串1的后面,結(jié)果放在字符數(shù)組1中,函數(shù)調(diào)用后得到一個(gè)函數(shù)值——字符數(shù)組1的地址。

      字符數(shù)組1必須足夠大,以便容納連接后的新字符串。

      連接前兩個(gè)字符串的后面都有′

      連接前兩個(gè)字符串的后面都有′\0′,連接時(shí)將字符串1后面的′\0′取消,只在新串最后保留′\0′。

      ′,連接時(shí)將字符串1后面的′

      連接前兩個(gè)字符串的后面都有′\0′,連接時(shí)將字符串1后面的′\0′取消,只在新串最后保留′\0′。

      ′取消,只在新串最后保留′

      連接前兩個(gè)字符串的后面都有′\0′,連接時(shí)將字符串1后面的′\0′取消,只在新串最后保留′\0′。

      ′。

      1.2.3字符串復(fù)制函數(shù)

      strcpy(字符串1, 字符串2); char *strcpy( char *strDestination, const char *strSource );

      :mag_right:strcpy:函數(shù)所在庫為string.h;函數(shù)參數(shù)有兩個(gè),第一個(gè)為char*類型(目的字符串地址)第二個(gè)參數(shù)為const char*類型(被復(fù)制字符串的地址);函數(shù)返回值為char*(返回strDestination的元素地址)。

      strcpy函數(shù)將strSource復(fù)制給strDestination。

      strcpy作用:將字符串2復(fù)制到字符數(shù)組1中去。

      字符數(shù)組1必須定義得足夠大,以便容納被復(fù)制的字符串2。字符數(shù)組1的長(zhǎng)度不應(yīng)小于字符串2的長(zhǎng)度。

      “字符數(shù)組1”必須寫成數(shù)組名形式,“字符串2”可以是字符數(shù)組名,也可以是一個(gè)字符串常量。

      若在復(fù)制前未對(duì)字符數(shù)組1初始化或賦值,則其各字節(jié)中的內(nèi)容無法預(yù)知,復(fù)制時(shí)將字符串2和其后的′

      若在復(fù)制前未對(duì)字符數(shù)組1初始化或賦值,則其各字節(jié)中的內(nèi)容無法預(yù)知,復(fù)制時(shí)將字符串2和其后的′\0′一起復(fù)制到字符數(shù)組1中,取代字符數(shù)組1中前面的字符,未被取代的字符保持原有內(nèi)容。

      ′一起復(fù)制到字符數(shù)組1中,取代字符數(shù)組1中前面的字符,未被取代的字符保持原有內(nèi)容。

      不能用賦值語句將一個(gè)字符串常量或字符數(shù)組直接給一個(gè)字符數(shù)組。字符數(shù)組名是一個(gè)地址常量,它不能改變值,正如數(shù)值型數(shù)組名不能被賦值一樣。

      可以用strncpy函數(shù)將字符串2中前面n個(gè)字符復(fù)制到字符數(shù)組1中去。

      將str2中最前面2個(gè)字符復(fù)制到str1中,取代str1中原有的最前面2個(gè)字符。但復(fù)制的字符個(gè)數(shù)n不應(yīng)多于str1中原有的字符(不包括′

      將str2中最前面2個(gè)字符復(fù)制到str1中,取代str1中原有的最前面2個(gè)字符。但復(fù)制的字符個(gè)數(shù)n不應(yīng)多于str1中原有的字符(不包括′\0′)。

      ′)。

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

      strcmp(字符串1, 字符串2); int strcmp( const char *string1, const char *string2 );

      :mag_right:strcmp:函數(shù)所在庫為string.h;函數(shù)參數(shù)有兩個(gè),第一個(gè)為constchar*類型(第一個(gè)字符串地址)第二個(gè)參數(shù)為const char*類型(第二個(gè)字符串的地址);函數(shù)返回值為int(相同則返回0,字符串1>字符串2則返回一個(gè)正整數(shù),字符串1<字符串2則返回一個(gè)負(fù)整數(shù))。

      :bulb:對(duì)兩個(gè)字符串比較不能直接用str1>str2進(jìn)行比較,因?yàn)閟tr1和str2代表地址而不代表數(shù)組中全部元素,而只能用 (strcmp(str1,str2)>0)實(shí)現(xiàn),系統(tǒng)分別找到兩個(gè)字符數(shù)組的第一個(gè)元素,然后順序比較數(shù)組中各個(gè)元素的值。

      strcmp作用:比較字符串1和字符串2。

      字符串比較的規(guī)則是: 將兩個(gè)字符串自左至右逐個(gè)字符相比(按ASCII碼值大小比較),直到出現(xiàn)不同的字符或遇到′

      字符串比較的規(guī)則是: 將兩個(gè)字符串自左至右逐個(gè)字符相比(按ASCII碼值大小比較),直到出現(xiàn)不同的字符或遇到′\0′為止。

      ′為止。

      (1) 如全部字符相同,則認(rèn)為兩個(gè)字符串相等;

      (2) 若出現(xiàn)不相同的字符,則以第1對(duì)不相同的字符的比較結(jié)果為準(zhǔn)。

      比較的結(jié)果由函數(shù)值帶回。

      (1) 如果字符串1與字符串2相同,則函數(shù)值為0。

      (2) 如果字符串1>字符串2,則函數(shù)值為一個(gè)正整數(shù)。

      (3) 如果字符串1<字符串2,則函數(shù)值為一個(gè)負(fù)整數(shù)。

      1.2.5測(cè)字符串長(zhǎng)度的函數(shù)

      strlen(字符串); size_t strlen( const char *string );//size_t本質(zhì)上是unsigned int 類型

      :mag_right:strlen:函數(shù)所在庫為string.h;函數(shù)參數(shù)為const char*類型(需要被計(jì)算字符串長(zhǎng)度的字符串地址);函數(shù)返回值為unsigned int(size_t)(返回傳入字符串長(zhǎng)度大?。?。

      strlen作用:測(cè)試字符串長(zhǎng)度的函數(shù)。函數(shù)的值為字符串中的實(shí)際長(zhǎng)度(不包括′

      strlen作用:測(cè)試字符串長(zhǎng)度的函數(shù)。函數(shù)的值為字符串中的實(shí)際長(zhǎng)度(不包括′\0′在內(nèi))。

      ′在內(nèi))。

      1.2.6轉(zhuǎn)換為大小寫的函數(shù)

      C語言的羅盤指針——深入理解C語言指針及其應(yīng)用

      strlwr(字符串);//大寫字母轉(zhuǎn)小寫字母 char *_strlwr( char *string ); strupr(字符串)//小寫字母轉(zhuǎn)大寫字母

      :mag_right:strlwr:函數(shù)所在庫為string.h;函數(shù)參數(shù)為char*類型(需要被轉(zhuǎn)換成小寫的字符串地址);函數(shù)返回值為char*(返回傳入字符串地址)。

      :mag_right:strupr:函數(shù)所在庫為string.h;函數(shù)參數(shù)為char*類型(需要被轉(zhuǎn)換成大寫的字符串地址);函數(shù)返回值為char*(返回傳入字符串地址)。

      作用:

      srtlwr將字符串中大寫字母換成小寫字母。

      strupr將字符串中小寫字母換成大寫字母。

      2.指針數(shù)組與數(shù)組指針

      2.1指針數(shù)組

      指針數(shù)組就是數(shù)組元素類型為指針的數(shù)組。

      int* arr1[10]; //整形指針的數(shù)組 char* arr2[40]; //一級(jí)字符指針的數(shù)組 char** arr3[50];//二級(jí)字符指針的數(shù)組

      2.2數(shù)組指針

      數(shù)組指針就是指向一個(gè)數(shù)組的指針。要弄清楚數(shù)組指針是什么,首先必須知道數(shù)組指針是指針還是數(shù)組。我們從概念名字上進(jìn)行分析,就能知道它是指針而不是數(shù)組。

      我們以類比的方式來搞清楚數(shù)組指針究竟是什么?

      我們已經(jīng)學(xué)習(xí)過整型指針int*,浮點(diǎn)數(shù)指針float* double*,我們以類型名+變量名的方式定義一個(gè)相應(yīng)類型的指針。

      a = 8; b = 2.2; int* pa = &a;//整型指針 double* pb = &b;//雙精度浮點(diǎn)型指針

      同理數(shù)組指針也是如此,不過需要與指針數(shù)組區(qū)分開來

      int* arr[10];//整型指針數(shù)組,是一個(gè)數(shù)組,存放了10個(gè)整型指針類型元素 int (*parr)[10];//這就是一個(gè)數(shù)組指針,是不是和指針數(shù)組有點(diǎn)像呢? //因?yàn)閇]優(yōu)先級(jí)高于*,如果不加括號(hào),變量名首先會(huì)與[]結(jié)合表示成一個(gè)數(shù)組 //如果(*變量名),那變量名首先會(huì)與*結(jié)合就表示一個(gè)指針

      int (*parr)[10]表示一個(gè)指針,指向一個(gè)數(shù)據(jù)類型為int元素個(gè)數(shù)為10的一個(gè)數(shù)組,所以parr是一個(gè)數(shù)組指針變量。

      2.3數(shù)組名與&數(shù)組名

      數(shù)組名一般情況下指的是數(shù)組首元素地址,與數(shù)組名[0]等價(jià)。但是有二般情況,使用sizeof(數(shù)組名),這里的數(shù)組名指的是全數(shù)組整體;&arr并不是指數(shù)組名存放的地址的地址,而是指一個(gè)數(shù)組整體的首地址。數(shù)組名+1加的是該數(shù)組存放元素的數(shù)據(jù)類型的大小,如果為int類型的數(shù)組,那就是加4,而&arr+1加的是數(shù)組整體的大小,如果一個(gè)int類型的數(shù)組有10個(gè)元素,那就是加40。

      3.數(shù)組傳參與指針傳參

      3.1數(shù)組傳參

      3.1.1一維數(shù)組傳參

      對(duì)于test1 test2函數(shù)形參可以這么寫呢?

      #include int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 }; int* arr2[10] = { 0 }; int i = 0; for (i = 0; i < 10; i++) { arr2[i] = &arr1[i]; } test1(arr1); test2(arr2); return 0; }

      //test1 void test1(int arr[]);//方式1 void test1(int arr[10]);//方式2 void test1(int* arr);//方式3 //test2 void test2(int* arr[]);//方式1 void test2(int* arr[10]);//方式2 void test2(int** arr);//方式3

      3.1.2二維數(shù)組傳參

      對(duì)于test函數(shù)形參可以這么寫呢?

      #include int main() { int arr[4][3] = { 0 }; test(arr); return 0; }

      void test(int arr[4][3]);//方式1 void test(int arr[][3]);//方式2 void test(int arr[][]);//不能省略列數(shù),錯(cuò)誤 //對(duì)于二維數(shù)組來說,每個(gè)元素指的是每一行,首元素指的是第一行數(shù)組,所以可以使用數(shù)組指針傳參 void test(int (*arr)[3]);//方式3

      3.2指針傳參

      3.2.1一級(jí)指針傳參

      一個(gè)函數(shù)test(int* p)能接受什么參數(shù)?

      int arr[10] = {0}; test(arr);//1.數(shù)組名 int a = 10; int* pa = &a; test(pa);//或 test(&a);//2.一級(jí)指針

      3.2.2二級(jí)指針傳參

      一個(gè)函數(shù)test(int** p)能接受什么參數(shù)?

      int n = 10; int* p = &n; int** pp = &p; int* arr[10] = {0}; test(arr);//1.整型指針數(shù)組 test(pp); test(&p);//2.二級(jí)指針

      4.函數(shù)指針與函數(shù)指針數(shù)組

      4.1函數(shù)指針

      如果在程序中定義了一個(gè)函數(shù),在編譯時(shí)會(huì)把函數(shù)的源代碼轉(zhuǎn)換為可執(zhí)行代碼并分配一段存儲(chǔ)空間。這段內(nèi)存空間有一個(gè)起始地址,也稱為函數(shù)的入口地址。每次調(diào)用函數(shù)時(shí)都從該地址入口開始執(zhí)行此段函數(shù)代碼。

      函數(shù)名就是函數(shù)的指針,它代表函數(shù)的起始地址。

      函數(shù)名與數(shù)組名有點(diǎn)相似,對(duì)函數(shù)名取地址得到的還是函數(shù)的地址。

      #include void test() { printf("hehe\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; }

      :bulb:運(yùn)行結(jié)果:

      004713B1 004713B1 D:\gtee\C-learning-code-and-project\test_813\Debug\test_813.exe (進(jìn)程 20032)已退出,代碼為 0。 按任意鍵關(guān)閉此窗口. . .

      可以定義一個(gè)指向函數(shù)的指針變量,用來存放某一函數(shù)的起始地址,這就意味著此指針變量指向該函數(shù)。例如:

      int (*p)(int,int);

      定義p是一個(gè)指向函數(shù)的指針變量,它可以指向函數(shù)類型為整型且有兩個(gè)整型參數(shù)的函數(shù)。此時(shí),指針變量p的類型用int (*)(int,int)表示。

      :star:函數(shù)指針定義通式:類型名 (*指針變量名)(函數(shù)參數(shù)表列)

      :star:對(duì)于函數(shù)指針你要注意以下幾點(diǎn):

      :lemon::定義指向函數(shù)的指針變量,并不意味著這個(gè)指針變量可以指向任何函數(shù),它只能指向在定義時(shí)指定的類型的函數(shù)。

      :lemon::如果要用指針調(diào)用函數(shù),必須先使指針變量指向該函數(shù)。

      :lemon::在給函數(shù)指針變量賦值時(shí),只須給出函數(shù)名而不必給出參數(shù)。

      :lemon::用函數(shù)指針變量調(diào)用函數(shù)時(shí),只須將(*p)代替函數(shù)名即可(p為指針變量名),在(*p)之后的括號(hào)中根據(jù)需要寫上實(shí)參。

      :lemon::對(duì)指向函數(shù)的指針變量不能進(jìn)行算術(shù)運(yùn)算,如p+n,p++,p–等運(yùn)算是無意義的。

      :lemon::用函數(shù)名調(diào)用函數(shù),只能調(diào)用所指定的一個(gè)函數(shù),而通過指針變量調(diào)用函數(shù)比較靈活,可以根據(jù)不同情況先后調(diào)用不同的函數(shù)。

      小栗子:

      #include int Add(int x, int y) { return x + y; } int main() { int a = 2; int b = 6; int (*p)(int, int) = Add; int c = Add(a, b); int d = (*p)(a, b); printf("%d\n%d", c, d); return 0; }

      :bulb:運(yùn)行結(jié)果:

      8 8 D:\gtee\C-learning-code-and-project\test_813\Debug\test_813.exe (進(jìn)程 21292)已退出,代碼為 0。 按任意鍵關(guān)閉此窗口. . .

      :bulb:分析兩個(gè)有趣的代碼

      #include int main() { //代碼1 (*(void (*)())0)(); //代碼2 void (*signal(int, void(*)(int)))(int); return 0; }

      :key:代碼1:

      void (*)()是一個(gè)參數(shù)為空返回值為空的函數(shù)指針類型,(void (*)())0意思是將0強(qiáng)制轉(zhuǎn)換成這種指針類型,(* (void (*)())0)()解引用被轉(zhuǎn)換過的0執(zhí)行在該地址的函數(shù)。

      :key:代碼2:

      定義了一個(gè)名為signal的函數(shù),其中參數(shù)為整型int和參數(shù)為int 返回值為空的函數(shù)指針void(*)(int),返回值為void (*)(int)類型的函數(shù)指針。

      可以使用typedef將這個(gè)代碼簡(jiǎn)化:

      typedef void (*pf)(int) void (*signal(int, void(*)(int)))(int); //相當(dāng)于 pf signal(int, pf);

      4.2函數(shù)指針數(shù)組及其在計(jì)算器的應(yīng)用

      //函數(shù)指針 int (*func)(int, int); //指針數(shù)組 int* arr[10]; //函數(shù)指針數(shù)組 int (*funcarr[10])(int, int); //函數(shù)指針數(shù)組的指針 int (*(*pfuncarr)[10])(int, int);

      函數(shù)指針數(shù)組用途:轉(zhuǎn)移表

      :corn:栗子:整型加減乘除計(jì)算器

      菜單及其加減乘除函數(shù)

      #include void menu() { printf("**********************************\n"); printf("**********************************\n"); printf("******* 1.add *******\n"); printf("******* 2.sub *******\n"); printf("******* 3.mul *******\n"); printf("******* 4.div *******\n"); printf("******* 0.exit *******\n"); printf("**********************************\n"); printf("**********************************\n"); } int Add(int x, int y)//int (*)(int, int) { return x + y; } int Sub(int x, int y)//int (*)(int, int) { return x - y; } int Mul(int x, int y)//int (*)(int, int) { return x * y; } int Div(int x, int y)//int (*)(int, int) { return x / y; } void Calc(int(*pf)(int, int)) { int x = 0; int y = 0; int ret = 0; printf("請(qǐng)輸入2個(gè)操作數(shù):>"); scanf("%d %d", &x, &y); ret = pf(x, y); printf("ret = %d\n", ret); }

      1.使用函數(shù)指針傳參實(shí)現(xiàn)

      int main() { int input = 0; do { menu(); printf("請(qǐng)選擇:>"); scanf("%d", &input); switch (input) { case 1: Calc(Add); break; case 2: Calc(Sub); break; case 3: Calc(Mul); break; case 4: Calc(Div); break; case 0: printf("退出計(jì)算器\n"); break; default: printf("選擇錯(cuò)誤\n"); break; } } while (input); return 0; }

      :bulb:運(yùn)行結(jié)果:

      ********************************** ********************************** ******* 1.add ******* ******* 2.sub ******* ******* 3.mul ******* ******* 4.div ******* ******* 0.exit ******* ********************************** ********************************** 請(qǐng)選擇:>1 請(qǐng)輸入2個(gè)操作數(shù):>2 3 ret = 5 ********************************** ********************************** ******* 1.add ******* ******* 2.sub ******* ******* 3.mul ******* ******* 4.div ******* ******* 0.exit ******* ********************************** ********************************** 請(qǐng)選擇:>3 請(qǐng)輸入2個(gè)操作數(shù):>2 3 ret = 6 ********************************** ********************************** ******* 1.add ******* ******* 2.sub ******* ******* 3.mul ******* ******* 4.div ******* ******* 0.exit ******* ********************************** ********************************** 請(qǐng)選擇:>0 退出計(jì)算器 D:\gtee\C-learning-code-and-project\test_813\Debug\test_813.exe (進(jìn)程 7012)已退出,代碼為 0。 按任意鍵關(guān)閉此窗口. . .

      2.使用函數(shù)指針數(shù)組實(shí)現(xiàn)

      int main() { int input = 0; do { int x = 0; int y = 0; int ret = 0; menu(); printf("請(qǐng)選擇:>");//1 scanf("%d", &input); int (*pfArr[5])(int, int) = {0, Add, Sub, Mul, Div}; //0 1 2 3 4 if (input == 0) { printf("退出計(jì)算器\n"); } else if(input>=1 && input<=4) { printf("請(qǐng)輸入2個(gè)操作數(shù):>"); scanf("%d %d", &x, &y); ret = pfArr[input](x, y); printf("%d\n", ret); } else { printf("選擇錯(cuò)誤\n"); } } while (input); return 0; }

      :bulb:運(yùn)行結(jié)果:

      ********************************** ********************************** ******* 1.add ******* ******* 2.sub ******* ******* 3.mul ******* ******* 4.div ******* ******* 0.exit ******* ********************************** ********************************** 請(qǐng)選擇:>1 請(qǐng)輸入2個(gè)操作數(shù):>2 3 5 ********************************** ********************************** ******* 1.add ******* ******* 2.sub ******* ******* 3.mul ******* ******* 4.div ******* ******* 0.exit ******* ********************************** ********************************** 請(qǐng)選擇:>3 請(qǐng)輸入2個(gè)操作數(shù):>2 3 6 ********************************** ********************************** ******* 1.add ******* ******* 2.sub ******* ******* 3.mul ******* ******* 4.div ******* ******* 0.exit ******* ********************************** ********************************** 請(qǐng)選擇:>0 退出計(jì)算器 D:\gtee\C-learning-code-and-project\test_813\Debug\test_813.exe (進(jìn)程 16872)已退出,代碼為 0。 按任意鍵關(guān)閉此窗口. . .

      5.回調(diào)函數(shù)

      回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。

      比如上述計(jì)算器中的Calc函數(shù),這個(gè)函數(shù)通過傳入的函數(shù)指針,去找到Add Sub Mul Div中的一個(gè)函數(shù)并調(diào)用它。

      int Add(int x, int y)//int (*)(int, int) { return x + y; } int Sub(int x, int y)//int (*)(int, int) { return x - y; } int Mul(int x, int y)//int (*)(int, int) { return x * y; } int Div(int x, int y)//int (*)(int, int) { return x / y; } void Calc(int(*pf)(int, int)) { int x = 0; int y = 0; int ret = 0; printf("請(qǐng)輸入2個(gè)操作數(shù):>"); scanf("%d %d", &x, &y); ret = pf(x, y);//通過函數(shù)指針返回調(diào)用調(diào)用加減乘除函數(shù) printf("ret = %d\n", ret); }

      C 語言 數(shù)據(jù)結(jié)構(gòu)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:關(guān)于篩選(關(guān)于篩選檢查法下列哪一種說法不正確)
      下一篇:wps表格怎樣設(shè)置數(shù)據(jù)反向顯示(wps文字怎么反向)
      相關(guān)文章
      亚洲国产精品无码久久九九大片| 亚洲色少妇熟女11p| 亚洲高清乱码午夜电影网| 亚洲精品自拍视频| 亚洲成人午夜在线| 亚洲国产成人片在线观看| 中文字幕亚洲日韩无线码| 亚洲国产人成中文幕一级二级| 亚洲欧美日韩中文无线码 | 亚洲精品乱码久久久久久蜜桃不卡 | 久久91亚洲精品中文字幕| 亚洲AV永久青草无码精品| 亚洲国产成人一区二区精品区| 亚洲国产精华液网站w| 久久久无码精品亚洲日韩蜜桃| 亚洲AV无码专区电影在线观看| 久久精品国产99精品国产亚洲性色| 久久精品九九亚洲精品天堂| 亚洲av无码不卡一区二区三区| 亚洲A∨无码无在线观看| 亚洲一区影音先锋色资源| 亚洲蜜芽在线精品一区| 亚洲码在线中文在线观看| 亚洲国产精品综合福利专区| 亚洲一区免费视频| 亚洲欧美国产国产一区二区三区| 亚洲丰满熟女一区二区哦| 色噜噜的亚洲男人的天堂| 亚洲精品tv久久久久久久久久| 亚洲精品天堂成人片?V在线播放| 亚洲 综合 国产 欧洲 丝袜| 亚洲美女高清一区二区三区 | 久久久久久亚洲AV无码专区| 亚洲人成影院77777| 亚洲一卡一卡二新区无人区| 在线观看国产一区亚洲bd| 国产啪亚洲国产精品无码| 亚洲精品无码av人在线观看| 久久久久久久久亚洲| 亚洲乱码一二三四区麻豆| 亚洲爆乳AAA无码专区|