【趣学C语言和数据结构100例】
问题描述
输入两个正整数 m 和 n,求其最大公约数和最小公倍数
输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数
求 Sn = a + aa + aaa + … + a…a 之值,其中 a 是一个数字,n 表示 a 的位数,n、a 由键盘输入。例如: 2 + 22 + 222 + 2222 + 22222(此时 n=5)
求 1! + 2! + 3! + 4! + … + 20!
(扩展)输入一个 n,求 n 的双阶乘,例如输入 20,求 2! + 4! + … + 18! + 20!
求 2/1 + 3/2 + 5/3 + 8/5 + ... 前 20 项
代码分析
==1. 最大公约数和最小公倍数==
**最大公约数(GCD)的解法** 辗转相除法(也称欧几里得算法):直接从 m 和 n 中较小的数开始递减,直到找到能同时整除 m 和 n 的最大数
最小公倍数(LCM)的解法
(1)普通解法:使用公式 LCM = (m * n) / 最大公约数 来计算。
(2)暴力解法:通过不断增加 y 的值,直到 y 能同时被 m 和 n 整除。效率较低。
==2. 输入一行字符,统计个数==
定义数组str存储输入的字符串,定义四个整型变量,用来计数。初始值都设为0。
使用fgets函数从标准输入(stdin)读取一行字符,存储到str数组中。
(fgets函数用法:fgets(str, 100, stdin))
for循环遍历
(1)使用函数:isalpha函数检查是否为英文字母,isspace函数检查是否为空格,isdigit函数检查是否为数字。
(2)使用==: str[i] = =' '等。
==3. 求 Sn = a + aa + aaa + … + a…a 之值,其中 a 是一个数字,n 表示 a 的位数,n、a 由键盘输入。例如: 2 + 22 + 222 + 2222 + 22222(此时 n=5)==
找规律:输入n和a,定义pre_num和num用来表示当前aaa和 a + aa + aaa,for循环即可,循环次数为n,使用pre_num += a * pow(10, i);。
==4. 求 1! + 2! + 3! + 4! + … + 20!==
找规律:关于阶乘,考虑数值过大,使用long long定义变量,factorial和sum用来表示当前3! 和 1! + 2! + 3!。
//求阶乘使用
for (j = 1; j <= i; j++) {
factorial *= j;
}
==(扩展)输入一个 n,求 n 的双阶乘,例如输入 20,求 2! + 4! + … + 18! + 20!==
突然想到可以扩展题求n 的双阶乘,思路同上。
==5. 求 2/1 + 3/2 + 5/3 + 8/5 + ... 前 20 项==
找规律:可发现,后一个的分子为前一个的分子+分母,后一个的分子为前一个的分子,定义sum为和,for循环求,每次吧前一个的分子给temp保管,分别赋值。
代码实现
#include <stdio.h>
#include <cstring>
#include <ctype.h>
#include <math.h>
int main() {
// 1.输人两个正整数 m 和 n,求其最大公约数和最小公倍数
int m, n, i, gcd, lcm, x, y;
printf("请输入两个正整数 m 和 n:");
scanf("%d %d", &m, &n);
if(m<n)
{
x=m;y=n;} //x为求gcd时的小数,y为求lcm的大数
else
{
x=n;y=m;}
while (m % x != 0 || n % x != 0) {
x--;
}
printf("最大公约数为:%d\n", x);
//最小公倍数(LCM)的解法
printf("方法一:最小公倍数为:%d\n", x = m * n / x);
while (y % m != 0 || y % n != 0) {
y++;
}
printf("方法二:最小公倍数为:%d\n", y);
// 2.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数
char str[100];
int letters = 0;
int spaces = 0;
int digits = 0;
int others = 0;
int i;
printf("请输入一行字符:");
fgets(str, 100, stdin); //存储到字符数组 str 中
for (i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i])) {
// 使用 isalpha函数 判断字母
letters++;
} else if (isspace(str[i])) {
// 使用 isspace函数 判断空格
spaces++;
} else if (isdigit(str[i])) {
// 使用 isdigit函数 判断数字
digits++;
} else {
others++;
}
}
printf("英文字母个数:%d\n", letters);
printf("空格个数:%d\n", spaces);
printf("数字个数:%d\n", digits);
printf("其他字符个数:%d\n", others);
// 3.求 Sn =a+aa+aaa+…+a…a之值,其中a是一个数字,n 表示a的位数,n、a由键盘输入。例如:2+22+222+2222+22222(此时 n=5)
int n, a, pre_num = 0, num = 0;
printf("输入n和a的值(n,a):");
scanf("%d,%d", &n, &a);
for (int i = 0; i < n; i++) {
pre_num += a * pow(10, i);
num += pre_num;
}
printf("%d\n", num);
return 0;
// 4.求1!+2!+3!+4!+…+20!
int i, j;
long long factorial = 1;
long long sum = 0;
for (i = 1; i <= 20; i++) {
factorial = 1;
for (j = 1; j <= i; j++) {
//求阶乘
factorial *= j;
}
sum += factorial;
}
printf("%lld\n", sum);
// (扩展)输入一个n,求n的双阶乘 ,例如输入20,求2!+4!+…18!+20!
int n;
long long factorial = 1;
long long sum = 0;
printf("输入n的值(n>2):");
scanf("%d",&n);
for (int i = n; i > 2; i -= 2) {
factorial = 1;
for (int j = 1; j <= i; j++) {
factorial *= j;
}
sum += factorial;
}
printf("%lld\n", sum);
// 5.求2/1+3/2+5/3+8/5+...前20项
double a = 2 , b = 1 , sum = 0 ,temp;
for(int i = 1;i <= 20; i++)
{
sum = a / b;
temp = b;
b = a;
a += temp;
}
printf("前20项和为:%lf",sum);
return 0;
}
总结
本文介绍了五个编程问题及其C语言实现,这些问题覆盖了数学计算、字符串处理、数列求和等多个领域。这些编程问题不仅锻炼了我们的编程技巧,也加深了对算法和数据结构的理解。
最大公约数和最小公倍数问题要求我们找出两个正整数的最大公约数和最小公倍数。这个问题的解决关键在于理解辗转相除法(欧几里得算法)和最小公倍数的计算公式。
字符统计问题要求我们统计输入字符串中的英文字母、空格、数字和其他字符的个数。这个问题的解决需要我们遍历字符串,并使用字符判断函数来分类统计。
数列求和问题要求我们计算一个特定模式的数列和。这个问题的解决关键在于理解数列的生成规律,并使用循环累加求和。
阶乘求和问题要求我们计算从1到20的阶乘和,以及一个数的双阶乘。这个问题的解决需要我们编写阶乘计算函数,并使用循环累加阶乘结果。
分数数列求和问题要求我们计算一个特定分数数列的前20项和。这个问题的解决需要我们理解数列的生成规律,并使用循环累加分数结果。
这些算法的实现不仅展示了C语言在处理数学问题和字符串时的能力,也体现了算法设计的基本思想,如循环控制、条件判断和递归。通过这些算法的学习,我们可以更好地理解数据结构和算法的基本概念,提高解决实际问题的能力。
总的来说,这些算法问题不仅锻炼了编程能力,也加深了对数据结构和算法的理解。通过这些问题的解决,我们可以逐步提高自己的编程技能,为将来的学习和工作做好准备。这些算法的掌握对于计算机专业的学生和软件开发人员来说都是非常重要的。通过这些练习,我们可以逐步提高自己的编程技能,为将来的学习和工作做好准备。同时,这些问题的解决也体现了算法在处理数据时的灵活性和效率,为我们在实际开发中遇到类似问题提供了解决思路。