重溫c語言之,7天開整,就是隨便的寫寫,第七天

我是一个小笨蛋發表於2024-11-06

一:素數又見素數

  但這次不一樣,這次需要用到函式,利用函式來將素數區分出來,直接上程式碼

 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個位元組

相關文章