1. 程式人生 > 實用技巧 >【實驗4】函式和陣列

【實驗4】函式和陣列

實驗任務一

原始程式程式碼:

 1 // 一元二次方程求解
 2 // 重複執行, 直到按Ctrl+Z結束
 3 //
 4 #include <math.h>
 5 #include <stdio.h>
 6 int main() {
 7     float a, b, c, x1, x2;
 8     float delta, real, imag;
 9     printf("Enter a, b, c: ");
10     while(scanf("%f%f%f", &a, &b, &c) != EOF) {
11         if
(a == 0) 12 printf("not quadratic equation.\n\n"); 13 else { 14 delta = b*b - 4*a*c; 15 if(delta >= 0) { 16 x1 = (-b + sqrt(delta)) / (2*a); 17 x2 = (-b - sqrt(delta)) / (2*a); 18 printf("x1 = %.2f, x2 = %.2f\n\n", x1, x2); 19
} 20 else { 21 real = -b/(2*a); 22 imag = sqrt(-delta) / (2*a); 23 printf("x1 = %.2f + %.2fi, x2 = %.2f - %.2fi\n\n", real, 24 imag, real, imag); 25 } 26 } 27 printf("Enter a, b, c: "); 28 } 29 return
0; 30 }

改版程式程式碼:

 1 // 一元二次方程求解(函式實現方式)
 2 // 重複執行, 直到按下Ctrl+Z結束
 3 #include <math.h>
 4 #include <stdio.h>
 5 // 函式宣告
 6 void solve(double a, double b, double c);
 7 // 主函式
 8 int main() {
 9     double a, b, c;
10     printf("Enter a, b, c: ");
11     while(scanf("%lf%lf%lf", &a, &b, &c) != EOF) {
12         solve(a, b, c); // 函式呼叫
13         printf("Enter a, b, c: ");
14     }
15     return 0;
16 }
17 // 函式定義
18 // 功能:求解一元二次方程,列印輸出結果
19 // 形式引數:a,b,c為一元二次方程係數
20 void solve(double a, double b, double c) {
21     double x1, x2;
22     double delta, real, imag;
23     if(a == 0)
24         printf("not quadratic equation.\n");
25     else {
26         delta = b*b - 4*a*c;
27         if(delta >= 0) {
28             x1 = (-b + sqrt(delta)) / (2*a);
29             x2 = (-b - sqrt(delta)) / (2*a);
30             printf("x1 = %f, x2 = %f\n", x1, x2);
31         }
32         else {
33             real = -b/(2*a);
34             imag = sqrt(-delta) / (2*a);
35             printf("x1 = %f + %fi, x2 = %f - %fi\n", real, imag, real,imag);
36         }
37     }
38 }

解析:

1、定義函式solve,則在這個計算一元二次方程的程式中的共能肯定是進行公式求解。

2、既然是用公式求解來定義函式,那麼輸入的形參肯定就是三個,“a,b,c"。

3、通過公式計算出結果可以作為函式返回值也可以直接列印,二者都同等方便,僅看使用者需求。

4、若是無返回值的方式編寫solve函式,則其應當具有判斷是否能成功呼叫程式至輸出結果、計算實參、以及列印計算結果。

  若是帶返回值的方式,則應當將計算的兩根的結果返回給main函式。

5、對比前後兩版本的程式,修改的地方無非是讓主函式的功能由輸入、計算、輸出變化為輸入、引用函式,而已。

  使主函式看起來更加的簡潔明瞭,意圖容易理解。


實驗任務二

原始程式:

 1 // 利用區域性static變數計算階乘
 2 #include <stdio.h>
 3 long long fac(int n); // 函式宣告
 4 int main() {
 5     int i,n;
 6     printf("Enter n: ");
 7     scanf("%d", &n);
 8     for(i=1; i<=n; ++i)
 9         printf("%d! = %lld\n", i, fac(i));
10     return 0;
11 }
12 // 函式定義
13 long long fac(int n) {
14     static long long p = 1;
15     p = p*n;
16     return p;
17 }

執行結果:

為了探究區域性static變數

增加一行程式碼:printf("p = %lld\n", p);

修改程式:

 1 // 利用區域性static變數計算階乘
 2 #include <stdio.h>
 3 long long fac(int n); // 函式宣告
 4 int main() {
 5     int i,n;
 6     printf("Enter n: ");
 7     scanf("%d", &n);
 8     for(i=1; i<=n; ++i)
 9         printf("%d! = %lld\n", i, fac(i));
10     return 0;
11 }
12 // 函式定義
13 long long fac(int n) {
14     static long long p = 1;
15     printf("p = %lld\n", p);
16     p = p*n;
17     return p;
18 }

執行結果:

明顯可見,雖然在fac()函式的首段具有p的初始化,但是p的值一直保留著上一次呼叫結果的p值。

例題:

 1 // 練習:區域性static變數特性
 2 #include<stdio.h>
 3 int func(int, int);
 4 int main() {
 5     int k=4,m=1,p1,p2;
 6     p1 = func(k,m) ;
 7     p2 = func(k,m) ;
 8     printf("%d,%d\n",p1,p2) ;
 9     return 0;
10 }
11 int func(int a,int b) {
12     static int m=0,i=2;
13     i += m+1;
14     m = i+a+b;
15     return (m);
16 }

猜想列印結果:8 17


實驗任務三

題目:填入空缺程式碼

 1 //尋找兩個整數之間的所有素數(包括這兩個整數),把結果儲存在陣列bb中,函式返回素數的個數。
 2 // 例如,輸入6和21,則輸出為:7 11 13 17 19。
 3 #include <stdio.h>
 4 #define N 1000
 5 int fun(int n,int m,int bb[N]) {
 6     int i,j,k=0,flag;
 7     for(j=n;j<=m;j++) {
 8         flag=1;/*補足1*/
 9         for(i=2;i<j;i++)
10             if(j%i==0/*補足2*/) {
11                 flag=0;
12                 break;
13             }
14         if(flag!=0/*補足3*/)
15             bb[k++]=j;
16     }
17     return k;
18 }
19 int main(){
20     int n=0,m=0,i,k,bb[N];
21     scanf("%d",&n);
22     scanf("%d",&m);
23     for(i=0;i<m-n;i++)
24         bb[i]=0;
25     k=fun(n,m,bb/*補足4*/);
26     for(i=0;i<k;i++)
27         printf("%4d",bb[i]);
28     return 0;
29 }

執行結果:

思路:

補足1:將flag初始化,作為判定是否為素數的標誌

補足2:測試目前檢查的這個整數是否能被一個數整除

補足3:如果已經判斷出該數為素數

補足4:以主函式中的變數呼叫函式


實驗任務四

例題:實現f(n)=2^n-1

程式:

 1 #include <stdio.h>
 2 long long fun(int n); // 函式宣告
 3 int main() {
 4     int n;
 5     long long f;
 6     while(scanf("%d", &n) != EOF) {
 7         f = fun(n); // 函式呼叫
 8         printf("n = %d, f = %lld\n", n, f);
 9     }
10     return 0;
11 }
12 // 函式定義
13 // 補足。。。
14 long long fun(int n){
15     long long g=0,f=0; 
16     if(n==1){
17         g=2;
18     }
19     else{
20         g=2*(fun(n-1)+1);
21     }
22     f=g-1;
23     return f;
24 }

輸出結果:

bonus part:

例題:實現2^n-1

(待補充


實驗任務五

原始程式:

 1 #include <stdio.h>
 2 void draw(int n, char symbol); // 函式宣告
 3 #include <stdio.h>
 4 int main() {
 5     int n, symbol;
 6     while(scanf("%d %c", &n, &symbol) != EOF) {
 7     draw(n, symbol); // 函式呼叫
 8     printf("\n");
 9     }
10     return 0;
11 }
12 // 函式定義
13 // 補足程式碼。。。
14 void draw(int n, char symbol){
15     int st;
16     int count=1;
17     for(;n>=0;n--){        
18         //前半空白 
19         for(int i=n;i>0;i--)
20             printf(" ");
21         //列印字元 
22         st=2*count-1;
23         count++;
24         while(st--){
25             printf("%c",symbol);
26         }
27         //後半空白 
28         for(int t=n;t>0;t--)
29             printf(" ");
30         //換行 
31         printf("\n");
32         fflush(stdin);    
33     }        
34 }

執行結果:


實驗總結

說實話我覺得這章和上章的關係太緊密了,函式是這一章的主要內容,我們是學會怎麼使用、建構函式,

讓它成為我們第三章演算法的偷懶工具。遞迴什麼的,函式的亮點在編寫程式裡還是很能表現出來的。

嗯……熟能生巧還是真理,這是減少你除錯次數的絕對辦法之一。

有一句話不是說沒有人能一遍編出完美的程式嗎?Linus Torvalds也說

實際上沒有人能一次就寫出完美的程式碼,除了我。但是世界上只有一個我。

我嘗試用陣列和字串的方法去寫實驗任務四的bonus part,但是寫都寫不出來。

現在先vacant,待我日後經驗豐富了立刻回頭來補足。

我認為編碼風格、編碼規範是很重要的東西,一類東西不應當隔著放,而且應當與不同的類隔行。

養成寫開頭註釋,結尾註釋,行註釋的習慣。

Thanks for reading.