【实验3】C语言分支语句和循环语句编程应用
-
实验任务一
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 }
运行结果:
分析程序:运用必要条件a!=0 , delta分虚实情况讨论。作为判断条件使用,是程序的骨架。
运用宽度格式字符输入方法,限制保留小数位。
运用!=EOF循环,实现多组输入。
-
实验任务二
1 // 生成N个0~9之间的随机整数,并打印输出 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <time.h> 5 #define N 5 6 int main() { 7 int x, n; 8 srand(time(0)); // 以当前系统时间作为随机种子 9 n = 0; 10 do { 11 n++; 12 x = rand()%10; // 生成一个0~9之间的随机整数 13 printf("%3d", x); 14 }while(n<N); 15 printf("\n"); 16 return 0; 17 }
运行结果:
程序分析:这串17行代码中用到了“函数”,及使用函数的必要条件“预处理与头文件”
因为还没学习,在这里我自己实践了一下函数的普通用法
1 #include <stdio.h> 2 3 int max(int a, int b){ 4 if(a > b){ 5 return a; 6 }else{ 7 return b; 8 } 9 } 10 int main(){ 11 int a,b,c; 12 scanf("%d%d",&a,&b); 13 c = max(a,b); 14 printf("%d",c); 15 return 0; 16 }
函数是一个很方便的东西。
do-while语句和while语句是差不多的用法,但while就感觉多了个if的感觉,这个程序我也可以改成while:
1 // 生成N个0~9之间的随机整数,并打印输出 2 //do-while 改 while 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <time.h> 6 #define N 5 7 int main() { 8 int x, n; 9 srand(time(0)); // 以当前系统时间作为随机种子 10 n = 0; 11 while(n<N){ 12 n++; 13 x = rand()%10; // 生成一个0~9之间的随机整数 14 printf("%3d", x); 15 } 16 printf("\n"); 17 return 0; 18 }
运行结果:
所以dowhile就是“先do再while”。
-
实验任务三
第一回,我得到了错误答案。
1 #include<stdio.h> 2 #include<math.h> 3 4 int main(){ 5 int a=101,i,sum=0; 6 int max=sqrt(a); 7 for(int a=101;a<=200;a++){ 8 for(int i=2;i<=max;i++){ 9 if(a%i!=0){ 10 if(i==max){ 11 printf("%5d",a); 12 sum++; 13 } 14 else 15 continue; 16 } 17 else{ 18 break; 19 } 20 } 21 } 22 printf("101-200间共有%d个素数",sum); 23 return 0; 24 }
运行结果:
没错,多出来了几个数,那就是可以开平方的数(121、169),但我很好奇为什么144没算在里面。
修正之后:
1 #include<stdio.h> 2 #include<math.h> 3 4 int main(){ 5 int a=101,i,sum=0,r; 6 for(int a=101;a<=200;a++){ 7 int max=sqrt(a); 8 for(int i=2;i<=max;i++){ 9 r=a%i; 10 if(r==0){ 11 break; 12 } 13 else{ 14 continue; 15 } 16 } 17 if(r!=0){ 18 printf("%5d",a); 19 sum++; 20 } 21 22 } 23 printf("\n101-200间共有%d个素数",sum); 24 return 0; 25 }
运行结果:
没错,我把打印函数从最初的那个代码的最后一步if判断是不是质数中拿了出来,放在了最外面筛选质数的for循环中。
总结:我的算法写得还比较稚嫩,跟着感觉走是我的代码风格 。我还不熟练,视野略窄,做了上步就想立刻达成下步,没有跳跃思维。
It is always true that Practice makes perfect .
-
实验任务四
实验任务四看着就是一道简单的、像OJ上的题,但是我在自主编写时有些够呛。
弄了很久,最后受到同学们的热心帮助,合力做出来了。
最终答案:
1 #include<stdio.h> 2 #include<string.h> 3 4 int main(){ 5 char s[16]; 6 printf("Enter a number: "); 7 8 while(scanf("%s",s)!=EOF){ 9 printf("new number is: "); 10 int i=0; 11 int len; 12 len = strlen(s); 13 14 while(i<=len-1){ 15 int a=s[i]; 16 if(a%2!=0){ 17 printf("%c",s[i]); 18 i++; 19 } 20 else { 21 i++; 22 continue; 23 } 24 } 25 printf("\n\nEnter a number: "); 26 } 27 28 return 0; 29 }
运行结果:
程序思路:因为我用的是字符串的方法去做这道题,所以调用字符串中的奇数字符与最终按顺序打印输出几乎不用考虑。也有同学是用long方法去做的,可能我这个方法就方便在这里。
即:输入字符→扫描字符→调用字符→打印字符。
下面是我的struggle process:
初始版本:
可见,这个程序真是千疮百孔、漏洞百出、不堪入目,但错误是最好的老师不是吗?我把他记录下来的意义……
- i=1没有初始化
- scanf了%d赋给字符串s
- printf了%d的字符s[i]
这是目前可见的错误,我开始联合同学们一起讨论更正。
1、“scanf后面没有&”
结果是字符串可以不用&赋值的。之后同学的告知并且我上网查找了一下
“scanf对象是数组名不需要&,数组名本身是数组首个单位的地址。”
2、“把scanf的%d换成%s”
虽然没有解决输出结果完全错误的问题,但是好歹数值变了,这就说明了我原本是有问题的!
3、“大家讨论了while语句中的输入问题”
1)同学共享了方案“gets()!=NULL”
但结果我发现不能把这个方案放到while循环的括号里。
即while(s=getchar()!=EOF) 是行不通的。大概是赋值语句之后不能加上关系运算符的问题。
2)在末尾加一句getchar()
这是符合逻辑的,因为循环末尾有getchar,循环条件有输入scanf。可以实现多组输入。但是我第二次输入再输出结果是空白这个问题的来源不是这个…
4、“i=0放在循环里面”
这是一个关键的问题!我把i=0放在了开头。虽然说第一遍循环时没有哪个方法动了i的值。但是从第二遍循环开始时,i的初始值就变成了max-1。这是致命的错误。
-
实验任务五
1 #include<stdio.h> 2 3 double stage(double t){ //stage函数的意义是阶乘 4 double b=1.0; //b作为起始值1与最后阶乘函数的值的输出 5 for(int i=1;i<=t;i++){ 6 b=b*i; 7 } 8 return b; 9 } 10 11 int main(){ 12 printf("Enter n(1~10): "); 13 int n; 14 15 while(scanf("%d",&n)!=EOF){ 16 double a,s=0.0; 17 printf("n = %d, ",n); 18 for(double t=1;t<=n;t+=1){ //t指的是每一个分母,即t的最大值是n 19 a=1.0/stage(t); //a指的是每一个项(每一个分式) 20 if((int)t%2==0){ 21 a*=(-1.0); 22 } 23 s+=a; 24 } 25 printf("s = %lf",s); 26 printf("\n\nEnter n(1~10): "); 27 } 28 return 0; 29 }
运行结果:
程序分析:我用的是函数方法,可能又和同学们的做法不一样。我的思路是:先把阶乘“!”编制为函数方法,然后再直接倒数求和。其中通过规律我不难发现若分式分母为偶数,则该分式的值为负。
-
实验任务六
1 #include<stdio.h> 2 #include <stdlib.h> 3 #include <time.h> 4 5 int main(){ 6 int day,guess; 7 int chance = 3; 8 9 srand(time(0)); 10 day = rand() % 31; 11 12 printf("猜猜12月的哪一天会是你的lucky day★"); 13 getchar(); 14 printf("\n开始喽★你有三次机会,请猜吧(1~31)→ "); 15 16 judge:while(chance--){ 17 scanf("%d",&guess); 18 if(guess==day) return 0; 19 if(guess>day){ 20 printf("\n\n你猜的日期晚了,lucky day悄悄溜到前面啦:(\n"); 21 if(chance==0){ 22 printf("\n\n残念だ,次数已经用完了,偷偷告诉你☆,12月你的lucky day是%d号~\n",day); 23 return 0; 24 } 25 printf("\n再猜★→ "); 26 goto judge; 27 } 28 if(guess<day){ 29 printf("\n\n你猜的日期早了,lucky day还没到呢2333\n"); 30 if(chance==0){ 31 printf("\n\n残念だ,次数已经用完了,偷偷告诉你☆,12月你的lucky day是%d号~\n",day); 32 return 0; 33 } 34 printf("\n再猜★→ "); 35 goto judge; 36 } 37 } 38 return 0; 39 }
运行结果:
~实验结论~
- 通过这次实验,我渐渐地习惯使用字符串和函数了,毕竟在这两个方法上消磨了很多时间w。
- 再一个,很开心能和同学们一起讨论解决问题,思维的碰撞是最高效率学习的方法之一。
- 基础语法错误已经完全可以避免了,现在出现的主要问题是逻辑错误。例如有的时候该放在循环里的语句我却放在了外面,该放在外面的我又放在了里面。这个是硬伤,得自己治。
- 罗马不是一天建成的。
Thanks for reading