一:素數又見素數
但這次不一樣,這次需要用到函式,利用函式來將素數區分出來,直接上程式碼
1 #include <stdio.h> 2 #include<math.h> 3 int prime_num(int num) 4 { 5 for (int i = 2; i < sqrt(num); i++) 6 { 7 if (num % i == 0) 8 { 9 return 0; 10 } 11 } 12 return 1; 13 } 14 15 int main() 16 { 17 int num = 0; 18 printf("請隨機寫一個數字.\n"); 19 scanf("%d", &num); 20 if ((prime_num(num)) == 1)//其實這裡可以不用寫等於的,因為在判斷裡面,非0為true,0為false 21 { 22 printf("這個數字是素數:%d\n", num); 23 } 24 else 25 { 26 printf("這個數字不是素數:%d\n", num); 27 } 28 return 0; 29 }
我這裡用到了sqrt()這個函式,因為在這裡面,偶數是不能當素數的,所以直接就是更加高效的進化程式
二:這裡是強調函式的高內聚低耦合的觀點
題目:寫一個函式,判斷一年是否是閏年,列印1000~2000之間的閏年
直接上程式碼:
1 #include <stdio.h> 2 int leap_year(int year) 3 { 4 if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) 5 { 6 return 1; 7 } 8 else 9 { 10 return 0; 11 } 12 } 13 int main() 14 { 15 for (int i = 1000; i < 2000; i++) 16 { 17 if (leap_year(i)) 18 { 19 printf("%d ", i); 20 } 21 } 22 }
這個直接讓判斷閏年函式功能變得單一,不去依賴其他函式,自己就可以完成功能,這裡我沒有在這個函式內部輸出閏年,因為可能下一次的時候,我不想輸出,我只想判斷,那我就用不了這個函式的功能,如果讓這個函式變得單一的話,那我所有的想用到這個判斷是否是閏年相關的地方,我都可以用到這個函式
三:函式
1、函式可以巢狀呼叫,但不能巢狀定義
2、函式遞迴
題目是:
接收一個整形值,按照順序列印每一位
//例如:
//輸入:1234 輸出: 1 2 3 4
先直接上程式碼,
1 #include<stdio.h> 2 void print(unsigned int num) { 3 if (num > 9) { 4 print(num / 10); 5 } 6 printf("%u ", num%10); 7 } 8 9 //遞迴的實現 10 int main() 11 { 12 //%d列印有符號的整數,包括正負數 13 //%u列印無符號的整數 14 unsigned int num1 = 0; 15 16 scanf("%u", &num1);//1234 17 //1 2 3 4 18 19 print(num1); 20 return 0; 21 }
一開始我還沒有真正明白這體式什麼意思,知道我知道了這個題目:遞迴,是吧大的問題化成小的問題,就比如這個
這裡就是從鍵盤上面收到:1234,而我們想要的結果是:1 2 3 4 ,那怎麼解決呢?
這個時候我們想到了:求餘運算,它能展現想要的位置上的數字,那這個輸出的遞迴函式該怎麼理解呢?
鍵盤先輸入:1234,計算機收到了數字,隨著程式的執行,把1234這個數字轉入到了print()遞迴函式中,之後因為這個數字要大於9(為什麼是9呢?因為想要個位上的數字,求餘10就可以得出個位上的數字,所以要把十位以上的數字全部去除),之後就是數字大於9,
開始了第一次print()遞迴函式重執行,這個時候傳入的數字是:123,因為裡面的數字是:先進行num/10運算再輸入的,123>9,
所以第二次執行print()遞迴函式重執行,這個時候傳入的數字是:12,方法同上:123/10=12,12>9
最後一次執行print()函式,這個時候傳入的數字是:1,12/10=1,1<9,所以這裡執行printf(),1%10=1 ,並輸出:1 ,螢幕上有:1
再倒回來,輸出printf()函式,12%10=2,並輸出:2 ,螢幕上有:1 2
再次倒回來,執行printf()函式,123%10=3,並輸出:3 ,螢幕上有:1 2 3
最後,再次執行printf()函式,1234%10=4,並輸出:4,螢幕上有:1 2 3 4
最終的螢幕上顯示:1 2 3 4
如果這裡不寫if(num>9),則會造成棧溢位,因為每一次函式呼叫,都會在棧區申請空間
所以遞迴存在限制條件,當滿足這個限制條件的時候,遞迴不再繼續;每次遞迴呼叫之後,越來越接近這個條件
if(num>9) num/10
再來一題:編寫函式不允許建立臨時變數,求字串長度
先來個建立臨時變數的:
1 #include<stdio.h> 2 #include<string.h> 3 int my_strlen(char* str) { 4 int cout = 0;//計數,臨時變數 5 while (*str != '\0') { 6 cout++; 7 str++; 8 } 9 return cout; 10 } 11 int main() 12 { 13 char arr[] = "abc"; 14 int len = my_strlen(arr); 15 printf("%d\n", len); 16 }
再來個不建立臨時變數的(用到了函式遞迴):
1 #include<stdio.h> 2 #include<string.h> 3 int my_strlen(char* str) { 4 if (*str != '\0') { 5 return 1 + my_strlen(str+1); 6 } 7 else 8 { 9 return 0; 10 } 11 } 12 int main() 13 { 14 char arr[] = "abc"; 15 int len = my_strlen(arr); 16 printf("%d\n", len); 17 }
my_strlen("abc");
1 + my_strlen("ab");
1 + 1 + my_strlen("a");
1 + 1 + 1 + my_strlen("");
這個就用到了呼叫,這裡為什麼是str+1,而不是str+4/str+8呢,因為是str是一個指標變數,作業系統根據自身多少位來分配給指標變數多少位元組,用來存放指標所指向的地址的,這裡是不會變動的。
而str+1是因為str這個指標變數所指向的資料型別是char,是佔1個位元組,所以才+1,往後移動1個位元組;如果是int,則+4,往後移動4個位元組