前言:
本讲习题来自谭老先生的《C程序设计》
对于这些题目进行了细致的讲解,
以求带你掌握循环的知识。
★博文转载请注明出处。
1. 请补充例5. 7程序,分别统计当“fabs(t)>= 1e- 6”和“fabs(t)> =1e-8”时执行循环体的次数。
例中程序如下:
#include<stdio.h> #include<math.h> int main() { int sign = 1; double pi = 0.1,n = 1.0,term = 1.0;//term代表当前项的值 while(fabs(term) >= 1e-6) { pi = pi + term; n = n + 2; sign = -sign; term = sign/n; } pi = pi * 4; printf("pi = %10.8f\n",pi); return 0; }
现在要我们统计循环执行的次数,只需要加一个变量count,在循环中随着循环进行++操作计数,最后打印即可
#include<stdio.h> #include<math.h> int main() { int sign = 1; double pi = 0.1,n = 1.0,term = 1.0;//term代表当前项的值 int count = 0; while(fabs(term) >= 1e-6) { pi = pi + term; n = n + 2; sign = -sign; term = sign / n; count++; } pi = pi * 4; printf("pi = %10.8f\n",pi); printf("count = %d\n",count); return 0; }
又说要求fabs(t)> =1e-8时循环次数,这时只需要把1e - 6改成1e - 8即可
解答这道题时要求要知道5.7这个程序在说什么(就是求Π的值),也要知道fabs这个函数就是用来求绝对值的(不要忘了它的头文件哦!)以及科学计数法的表达形式
2. 输人两个正整数m和n,求其最大公约数和最小公倍数
在解答这道题之前要知道最大公约数和最小公倍数之间的性质:两个自然数的乘积等于这两个自然数的最大公约数和最小公倍数的乘积。所以,当我们求出最大公约数,就可以很轻松的求出最小公倍数。
该题题目直接使用“辗转相除法”来求解最大公约数,以除数和余数反复做除法运算,当余数为 0 时,就取得当前算式中的除数为最大公约数。
eg:77 28
77%28 = 2……21
28%21=1……7
21%7=3……0
此时算是中的除数7就是最大公约数了
最小公倍数:两个自然数的乘积 = 最大公约数 * 最小公倍数
代码步骤:
- 从标准输入当中获取两个数字
- 区分两个正整数当中的较大值(较大值 % 较小值)
- 辗转相除法 ——> 最大公约数
- 两数乘积 / 最大公约数 = 最小公倍数
- 输出
#include <stdio.h> int main() { int p, r, n, m; printf("请输入两个正整数n,m:"); scanf("%d%d,", &n, &m); //选出较大值,保存在n当中 if (n < m) { int tmp = n; n = m; m = temp; } //p是为了保存两者乘积,因为在辗转相除的时候,n*m会变化 int p = n * m; //辗转相除 while (m != 0) { r = n % m; //为下一次循环做准备 n = m; m = r; } printf("它们的最大公约数为:%d\n", n); printf("它们的最小公倍数为:%d\n", p / n); return 0; }
3. 输人一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数
需要从标准输入当中获取一行字符,我们需要对每一个字符进行甄别,判断其是英文字母还是空格,数字,其它字符
用getchar函数,可以从标准输入当中获取一个字符;当标准输入输入了多个字符的时候,getchar函数就会从缓冲区当中读取字符(我们可以输入多个字符,然后用getchar函数循环读取),当我们输入一行字符串的时候,字符串尾部是 \n,此时可以利用它来终止循环
统计
根据字符在ASC码表上的顺序判断
int main() { //定义eng_char为英文字母的个数,初始值为0 //定义space_char为空格字符的个数,初始值为0 //定义digit_char为数字字符的个数,初始值为0 //定义other_char为其他字符的个数,初始值为0 int eng_char = 0, space_char = 0, digit_char = 0, other_char = 0; printf("请输入一行字符:"); //c是从标准输入当中获取的 char c; //如果字符不等于\n,就意味着还没有读完 while ((c = getchar()) != '\n') { if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { eng_char++; } else if (c == ' ') { space_char++; } else if (c >= '0' && c <= '9') { digit_char++; } else { other_char++; } } printf("英文字母数量:%d\n空格数量:%d\n数字数量:%d\n其他字符数量:%d\n", eng_char,space_char, digit_char, other_char); return 0; }
4. 求S_n=a+aa+aaa+...+aa……aa 之值,其中a是一个数字,n表示a的位数,n由键盘输入。例如:2+22+222+2222+22222 (此时n=5)
该题目可以将数字拆分为 a * 10^n + 前一个数字 ,例如:
2 = 2 * 10^0 + 0 : 默认2的前一个数字为0,也就是没有任何值
22 = 2 * 10^1 + 2 : 22的前一个数字为2
222 = 2*10^2 + 22 :222的前一个数字为22
以此类推...
所以,在每次循环的时候,需要保存下,上一次结果的值,方便下一次计算
还需要使用到C库当中使用的pow函数,来计算某个数的n次方,我们在该题目当中使用的是10的n次方,n随着循环的次数,以此递增。
#include <stdio.h> #include <math.h> int main() { //n为a的个数 int n; double a, signle_num = 0.0, total_sum = 0.0; printf("请输入a的值以及n的值: "); scanf("%lf %d", &a, &n); //循环n次求总和 for (int i = 0; i < n; i++) { signle_num += a * pow(10, i);//这里就是每一项数的值 total_sum += signle_num;//每一项相加 } printf("总和为:%lf\n", total_sum); return 0; }
对于循环部分如果不太清楚的话可以在纸上将流程画出来,这样有助于理解过程
5. 求1!+2!+3!+4!+...+20!
该题需要从1循环到20,依次求出每一个数字阶乘的结果。所以在代码当中需要有两个循环,大循环从1到20,保证1到20个数字都被循环到,小循环里计算N阶乘,累加求和。
注意:对于20的阶乘已经超出了 int 类型能过表示的数字范围,所以在代码当中使用 double 类型
遍历获取每一个数字
对于每一个数字进行阶乘
对于每一个数字阶乘的结果进行求和
# include<stdio.h> int main() { double total_sum = 0。0; for(int i = 1; i <= 20; i++) { double single_sum = 1; //for循环求每一个数字的阶乘 for (int j = i; j > 0; j--) { single_sum *= j; } total_sum += single_sum; } printf("1~20每个数字阶乘总和为:%lf\n",total_sum); return 0; }
6. 求阶乘的和
综上所述:求和结果不是整数,所以定义求和变量是需要定义为带有精度的变量 double
该题目,最大的求和是从从1到100,所以需要一个循环,从1遍历到100。针对第一种情况,则遍历100次停下来。针对第二种情况,则遍历50次的时候停下来,针对第三种情况,则遍历10遍就停下来。
最后,在遍历每一个数字的时候,针对三种不同的情况求和。最后将三种不同请求的和加起来就是总体的和
#include <stdio.h> int main() { double total_sum = 0, sum1 = 0, sum2 = 0, sum3 = 0.0; for (int k = 1; k <= 100; k++) { sum1 += k; //遍历50次就不再执行情况2 if (k <= 50) { sum2 += k * k; } //遍历10次就不再执行情况3 if (k <= 10) { sum3 += 1.0 / k; } } total_sum = sum1 + sum2 + sum3; printf("三种情况求和结果为:%lf\n", total_sum); return 0; }
其实本题可以使用暴力法来解,直接用三个for循环,只不过从算法的角度来看,那显然不如上面给的程序
7. 输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如,153是水仙花数,因为153=1+5+3。
- 当前题意当中描述的水仙花数是一个三位数,1~1000
- 采用%10的方式,求得三位数当中的每一位数字
#include<stdio.h> int main() { //a表示百位数字,b表示十位数字,c表示个位数字 int a,b,c; //获取三位数 for(int i = 100;i <= 999; i++) { //获取每一位 a = i/100; b = (i/10)%10; c = i%10; if(a*a*a+b*b*b+c*c*c == i) { printf("%d\n",i); } } return 0; }
8. 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并按下面格式输出其因子: 6 its factors are 1,2,3
代码如下:
9. 有一个分数序列,求出这个数列的前20项之和
2/1 3/2 5/3 8/5 13/8 21/13 ……
规律:下一个分式当中的分子为上一个分式中分子和分母的和,分母为上一个分式的分子
还有一个需要注意的点是:保存数据的时候使用浮点数