【实验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.

 

posted @ 2020-11-27 22:00  katachip  阅读(124)  评论(2)    收藏  举报