前言
上一篇文章收集飞花令碎片——C语言分支与循环结构(上)已经跟大家全面讲解了分支与循环的基础知识,这一张会通过几个程序设计项目来锻炼逻辑思维能力,难度从难到易,大家可以根据自己的需求去练习
输⼊⼀个⼈的年龄 如果年龄<
18岁,打印“少年” 如果年龄在18岁⾄44岁打印“⻘年” 如果年龄在45岁⾄59岁打印“中⽼年” 如果年龄在60岁⾄89岁打印“⽼年” 如果90岁及以上打印“⽼寿星”
#include <stdio.h>
int main() {
int age = 0;
scanf("%d", &age);
if (age < 18) {
printf("少年\n");
} else {
if (age <= 44) {
printf("⻘年\n");
} else {
if (age <= 59) {
printf("中⽼年\n");
} else {
if (age <= 89) {
printf("⽼年\n");
} else {
printf("⽼寿星\n");
}
}
}
}
return 0;
}这道题只要你深入理解分支if语句加上一点点烧烤 只能说是

1. 能被4整除并且不能被100整除是闰年
2. 能被400整除是闰年#inlclude <stdio.h>
int main()
{
int yesr = 0;
printf("请输入一个年份:");
scanf_s("%d",&year);
if((year%100!=0&&year%4==0)||(year%400==0)){
printf("是闰年");
}else{
printf("不是闰年");
}
}#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
return 0;
}关键点:
执行过程:
打印时:
输出:
a = 1
b = 2
c = 3
d = 4上⾯的代码执⾏结果是什么?如果把a的值改成1,结果⼜是什么?
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;执行过程:
打印时:
输出:
a = 2
b = 3
c = 3
d = 5#include <stdio.h>
int main()
{
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
return 0;
}
//上⾯的代码执⾏结果是什么?如果把a的值改成0,结果⼜是什么?关键点:
执行过程:
打印时:
输出:
a = 2
b = 2
c = 3
d = 4如果将 a 的值改为 0:
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;执行过程:
打印时:
输出:
a = 1
b = 3
c = 3
d = 4#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch(day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("⼯作⽇\n");
break;
case 6:
case 7:
printf("休息⽇\n");
break;
}
return 0;
}#include <stdio.h>
int main() {
int a = 1, b = 0, c = -1;
if (a++ && b++ || c++) {
if (a-- || b-- && c--)
printf("Block A: %d %d %d\n", a, b, c);
else
printf("Block B: %d %d %d\n", a, b, c);
} else {
printf("Block C: %d %d %d\n", a, b, c);
}
return 0;
}终极问题:逐步分析每个表达式的求值过程和副作用
解:逐步分析代码执行过程
计算 a++: 先用后增,表达式为1 计算a++&&b++ 由于a++为真,所以没有短路特性 b++为0 两者一真一假,所以表达式的值为0 计算a++&&b++||c++ c++为-1,表达式结果为真 左0右1,结果为真
计算 a–: 使用 a 的当前值 2(真) 然后 a 自减为 1(副作用) 表达式结果:1由于 || 的左操作数为真,短路求值,不再计算 b-- && c– b 和 c 保持不变 整个表达式结果为 1(真) 进入 Block A
printf("Block A: %d %d %d\n", a, b, c);考察点:
接下来进入循环节点

#include <stdio.h>
int main()
{
int i = 1;
while(i <= 10)
{
printf("%d ", i);
i = i + 1;
}
return 0;
}例如: 输⼊:1234,输出:4 3 2 1 输⼊:521,输出:1 2 5
题目解析
#include <stdio.h>
int main(){
int num = 0;
printf("请输入一个数字:");
scanf_s("%d",&num);//scanf_s是Microsoft特有的安全版本,通常建议使用标准 的scanf函数,除非在特定环境下需要使用scanf_s。
while(num){
printf("%d",num%10);
num /= 10;
}
return 0;
}#include <stdio.h>
int main(){
int n = 3;
int sum = 0;
for (int i = 1; i <= 100; i++) {
if (i % n == 0) {
sum += i;
}
}
printf("%d",sum);
return 0;
}#include <stdio.h>
int main() {
int n = 0;
scanf_s("%d", &n);
int sum = 0;
do {
sum++;
n /= 10;
} while (n != 0);
printf("%d", sum);
return 0;
}我们先来看看下面这段代码有没有问题
#include <stdio.h>
int main() {
int j;
scanf_s("%d", &j);
for (int i = 2; i < j; i++) {
if (i % j == 0) {
printf("j不是素数");
break;
}
}
printf("j是素数");
return 0;
}在 for 循环中,如果发现 j 不是素数,程序会输出 “j不是素数” 并跳出循环。然而,无论 j 是否为素数,程序都会在循环结束后输出 “j是素数”。这会导致即使 j 不是素数,程序也会错误地输出 “j是素数”。
这时候就需要引入一个参数了
#include <stdio.h>
int main() {
int j;
scanf_s("%d", &j);
int isPrime = 1; // 假设 j 是素数
for (int i = 2; i < j; i++) {
if (j % i == 0) {
isPrime = 0; // j 不是素数
break;
}
}
if (isPrime) {
printf("j是素数");
} else {
printf("j不是素数");
}
return 0;
}对于较大的数,可以通过优化循环条件来提高效率。例如,只需循环到 sqrt(j) 即可,因为如果 j 不是素数,它必定有一个因子小于或等于 sqrt(j)。
#include <stdio.h>
#include <math.h>
int main() {
int j;
scanf_s("%d", &j);
int isPrime = 1; // 假设 j 是素数
for (int i = 2; i <= sqrt(j); i++) {
if (j % i == 0) {
isPrime = 0; // j 不是素数
break;
}
}
if (isPrime) {
printf("j是素数");
} else {
printf("j不是素数");
}
return 0;
}
C语言提供了⼀个函数叫 rand,这函数是可以生成随机数的,rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的,但是⼤部分编译器上是32767。
rand函数的使用需要包含⼀个头⽂件是:stdlib.h
代码展示
int rand (void);下面是两次随机数输出的结果

我们可以看到虽然⼀次运⾏中产⽣的5个数字是相对随机的,但是下⼀次运⾏程序⽣成的结果和上⼀次⼀模⼀样,这就说明有点问题。
如果再深入了解⼀下,我们就不难发现,其实 rand 函数⽣成的随机数是伪随机的,伪随机数不是真正的随机数,是通过某种算法⽣成的随机数。真正的随机数的是无法预测下⼀个值是多少的。⽽ rand 函数是对⼀个叫
种⼦的基准值进行运算⽣成的随机数。
C语⾔中⼜提供了⼀个函数叫 srand,⽤来初始化随机数的⽣成器的
void srand (unsigned int seed)程序中在调⽤ rand 函数之前先调⽤ srand 函数,通过 srand 函数的参数seed来设置rand函数⽣成随机数的时候的种⼦,只要种⼦在变化,每次⽣成的随机数序列也就变化起来了。
那也就是说给srand的种⼦是如果是随机的,rand就能⽣成随机数
C语言中的time函数用于获取当前日历时间,通常以秒为单位表示自1970年1月1日00:00:00 UTC(即UNIX纪元)以来的时间。
time函数的时候需要包含头⽂件:time.h
代码展示
#include <stdio.h>
#include <time.h>
int main() {
time_t current_time;
time(¤t_time); // 获取当前时间
printf("Current time: %ld\n", current_time);
return 0;
}进一步处理
time函数返回的时间通常是一个整数,表示自UNIX纪元以来的秒数。为了将其转换为更易读的格式,可以使用ctime
#include <stdio.h>
#include <time.h>
int main() {
time_t current_time;
time(¤t_time); // 转换为可读格式
printf("Current time:%ld\n",ctime(¤t_time));
return 0;
}
如果 timer 是 NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
//使⽤time函数的返回值设置种⼦
//因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换
srand((unsigned int)time(NULL));
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}如果要生成A~B的随机数,方法如下:
int num = rand() % (B - A + 1) + A;生成 [0, N-1] 的随机数
int num = rand() % N; // 范围:0 ~ N-1生成 [1, N] 的随机数
int num = rand() % N + 1; // 范围:1 ~ Ndo~while循环
所以我们main函数的基本格式就是:int main(){
do{
}while();
return 0;
}void menu()
{
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");int main(){
int input = 0;
do{
menu();
printf("请选择:"); //选择肯定直接选`switch`语句
scanf("%d",&input);
switch(input){
case 1:
printf("猜数字");
game(); //游戏函数
break;
case 0:
printf("退出游戏");
break;
default:
printf("选择错误,请重新选择");
break;
}while(input);
return 0;
}
}void game(){
//生成一个0~100的随机数
int r = rand()%(100+1);
int guess = 0;
int count = 5;
while(count){
printf("你还有%d次机会",count);
printf("请猜出你的数字");
scanf("%d",&guess);
count--;
if (guess < r) {
printf("猜⼩了\n");
} else if (guess > r) {
printf("猜⼤了\n");
} else {
printf("恭喜你,猜对了\n");
break;
}
}
if (count == 0) {
printf("你失败了,正确值是:%d\n", r);
}
}完整代码展示
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game() {
int r = rand() % (100 + 1);
int guess = 0;
int count = 5;
while (count) {
printf("\n你还有%d次机会\n", count);
printf("请猜数字>:");
scanf("%d", &guess);
if (guess < r) {
printf("猜⼩了\n");
} else if (guess > r) {
printf("猜⼤了\n");
} else {
printf("恭喜你,猜对了\n");
break;
}
count--;
}
if (count == 0) {
printf("你失败了,正确值是:%d\n", r);
}
}
void menu() {
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
return 0;
}本任务是键盘输入某班n个学生成绩,直至输入-1时结束,编程求出这n个学生的最高分以及平均分。


#include <stdio.h>
int main() {
int avg = 0, sum = 0, score = 0;
int n = 0, max = 0;
while (1) {
printf("请输入第%d位的成绩:", n + 1);
scanf_s("%d", &score);
if (score == -1) {
break;
}
if (score > max) {
max = score;
}
sum += score;
n++;
}
avg = sum / n;
printf("平均分:%d\n", avg);
printf("最高分:%d\n", max);
return 0;
}#include <stdio.h>
int main()
{
int n = 0;
scanf_s("%d", &n); // 输入整数n
long long sum = 0; // 初始化阶乘和为0
// 外层循环:计算1到n的阶乘和
for (int i = 1; i <= n; i++)
{
long long fac = 1; // 初始化当前数的阶乘
// 内层循环:计算i的阶乘
for (int j = 1; j <= i; j++)
{
fac *= j;
}
sum += fac; // 将当前阶乘加入总和
}
// 输出结果
printf("%d的阶乘和是%lld", n, sum);
return 0;
}#include <stdio.h>
int main() {
double e = 1.0; // 使用 double 提高精度
double fac = 1.0; // 阶乘也必须是浮点型
int terms = 0;
printf("输入计算的项数:");
scanf_s("%d", &terms); // 或者 scanf_s("%d", &terms);
for (int i = 1; i <= terms; i++) { // 注意是 i <= terms
fac *= i; // 计算 i! (1, 2, 6, 24, ...)
e += 1.0 / fac; // 加上 1/i!,注意 1.0 确保浮点除法
}
printf("e ≈ %.15f\n", e); // 输出 e 的值,保留 15 位小数
return 0;
}这个问题要求计算一个交替正负的倒数阶乘序列的和,即:
S = 1/1! - 1/2! + 1/3! - 1/4! + ... ± 1/n!
这一关可以有三种方法去
#include <stdio.h>
int main() {
double sum = 0.0;
double fac = 1.0; // 0! = 1
int sign = 1; // 初始符号为正
int terms = 0;
printf("请输入项数:");
scanf("%d", &terms); // 或scanf_s("%d", &terms)
// 处理i=0的特殊情况
sum += sign * (1.0 / fac);
sign *= -1;
for(int i = 1; i < terms; i++) {
fac *= i; // 计算i!
sum += sign * (1.0 / fac);
sign *= -1; // 改变符号
}
printf("前%d项交替倒数阶乘和为: %.15f\n", terms, sum);
return 0;
}double sum = 0.0; // 存储最终的和
double fac = 1.0; // 用于计算阶乘,初始为0! = 1
int sign = 1; // 控制正负号,初始为1(正)int terms = 0;
printf("请输入项数:");
scanf("%d", &terms); // 获取用户输入的项数n
- **处理第一项(i=0)**
```c
sum += sign * (1.0 / fac); // 计算第一项:1/0! = 1/1 = 1
sign *= -1; // 符号变为负,准备下一项for(int i = 1; i < terms; i++) {
fac *= i; // 计算i! (1!, 2!, 3!,...)
sum += sign * (1.0 / fac); // 加上当前项:±1/i!
sign *= -1; // 每次循环改变符号
}printf("前%d项交替倒数阶乘和为: %.15f\n", terms, sum);最终结果:1 - 1 + 0.5 - 0.166667 ≈ 0.333333
#include <stdio.h>
// 阶乘函数
double fac(int n) {
if (n == 0 || n == 1) return 1.0;
return n * fac(n - 1);
}
// 修正后的求和函数
double sum(int n) {
if (n < 0) return 0.0; // 处理非法输入
// 第0项:1/0! = +1
if (n == 0) return 1.0;
// 从第1项开始,奇数项为负,偶数项为正
double sign = (n % 2 == 1) ? -1.0 : 1.0;
return sign / fac(n) + sum(n - 1);
}
int main() {
int n;
printf("请输入项数n: ");
scanf_s("%d", &n);
// 计算从第0项到第n-1项的和
double result = sum(n - 1);
printf("前%d项交替倒数阶乘和为: %.15f\n", n, result);
return 0;
}/*从第1项开始*/
#include <stdio.h>
// 阶乘函数
double fac(int n) {
if (n == 0 || n == 1) return 1.0;
return n * fac(n - 1);
}
// 计算从第1项开始的交替倒数阶乘和(第一项为正)
double sum(int n) {
if (n < 1) return 0.0; // 处理无效输入
// 第1项:+1/1!
if (n == 1) return 1.0 / fac(1);
// 从第2项开始,奇数项为正,偶数项为负
double sign = (n % 2 == 0) ? -1.0 : 1.0;
return sign / fac(n) + sum(n - 1);
}
int main() {
int n;
printf("请输入项数n: ");
scanf("%d", &n);
// 计算从第1项到第n项的和
double result = sum(n);
printf("前%d项交替倒数阶乘和(+1/1! -1/2! +...): %.15f\n", n, result);
return 0;
}#include <stdio.h>
double optimized_alternating_sum(int n) {
double sum = 0.0;
double term = 1.0; // 第一项1/1!
int sign = 1;
for (int i = 1; i <= n; i++) {
sum += sign * term;
term /= (i + 1); // 计算下一项1/(i+1)!
sign *= -1; // 改变符号
}
return sum;
}
int main() {
int n;
printf("请输入项数n: ");
scanf("%d", &n);
double result = optimized_alternating_sum(n);
printf("前%d项交替倒数阶乘和为: %.15f\n", n, result);
return 0;
}由于我们还没研究函数递归,我们主要讲基本方法,另外两种方法也会给大家带上,方便大家后面回来复习

本任务是输出指定数以内所有的水仙花数。 水仙花数:是 n位数且等于其各位数字的 n次方和。
注意:水仙花数至少为3位数
#include <stdio.h>
#include <math.h>
int main() {
int num = 0, max = 0;
printf("请输入范围:");
scanf_s("%d",&max);
int a = 0, b = 0, c = 0;
printf("0~%d范围内的水仙花数是:");
for (int i = 0; i <= max && i <= 999; i++) {
a = i % 10;
b = i / 10 % 10;
c = i / 100;
int sum = pow(a, 3) + pow(b, 3) + pow(c, 3);
if (i == sum&&i >100){
printf("%d\n", sum);
}
}
return 0;
}#include <stdio.h>
#include <math.h>
int isNarcissistic(int num) {
if (num < 100) return 0; // 至少3位数
int original = num;
int sum = 0;
int digits = (int)log10(num) + 1; // 计算位数
while (num > 0) {
int digit = num % 10;
sum += pow(digit, digits); // 动态计算幂次
num /= 10;
}
return sum == original;
}
int main() {
int max;
printf("请输入范围:");
scanf("%d", &max);
printf("0~%d范围内的水仙花数是:\n", max);
for (int i = 100; i <= max; i++) {
if (isNarcissistic(i)) {
printf("%d\n", i);
}
}
return 0;
}这一关我会给出几种方法来求解,其中莱布尼茨的方法最简单,剩下的几种方法自己可以斟酌练习(因为小编也很头疼)

#include <stdio.h>
int main() {
int terms = 0;//定义项数和总数并初始化
double pi, variable = 0.0; //根据公式pi/4=...(我们把右边代为variable)
scanf_s("%d", &terms);
for (int i = 1, count = 1; count < terms;count++, i += 2) {
//奇数项为正,偶数项为负
int sign = (count % 2 == 1 ? 1 : -1);
variable += sign * (1.0 / i);
}
pi = 4 * variable;
printf("π ≈ %.15f (使用莱布尼茨级数,%d项)\n",
pi, terms);
return 0;
}100000000项以上这个代码光理解起来难度就很大,建议斟酌考虑学习
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double calculate_pi_monte_carlo(int samples) {
int hits = 0;
srand(time(NULL));
for (int i = 0; i < samples; i++) {
double x = (double)rand() / RAND_MAX;
double y = (double)rand() / RAND_MAX;
if (x * x + y * y <= 1.0) hits++;
}
return 4.0 * hits / samples;
}
int main() {
int samples = 1000000;
printf("π ≈ %.6f (蒙特卡洛方法,%d次采样)\n", calculate_pi_monte_carlo(samples), samples);
return 0;
}
利用if语句编写出分支函数体
#include <stdio.h>
int cow_number(int n) {
if (n <= 3) {
return 1;
}
else {
return cow_number(n - 1) + cow_number(n - 3);
}
}
int main() {
int n;
printf("请输入年份n:");
scanf("%d", &n);
printf("第%d年有%d头母牛\n", n, cow_number(n));
return 0;
}这道关具有高难度、多样性、逻辑严密,将它放最后一道也无可厚非 但是同时它也是分支与循环的重点题目之一,需要多加练习熟练掌握
C语言打印九九乘法表可以直角在
左上角``右上角``左下角``右下角``顶部正中央,当然,难度也逐级递增
设计思路: 外层循环控制行数(乘数) 内层循环控制列数(被乘数),但只循环到当前行数 这样每行输出的乘法式子数量等于行号
for (int i = 1; i <= 9; i++) for (j = 1; j <= i; j++)注意:打印完一行的列数记得换行
printf("%d×%d=%-2d ", j, i, i*j);#include <stdio.h>
int main() {
int i, j;
for (i = 1; i <= 9; i++) {
for (j = 1; j <= i; j++) {
printf("%d×%d=%-2d ", j, i, i*j);
}
printf("\n");
}
return 0;
}设计思路: 内外层都完整循环1-9 当列数小于行数时,输出空格占位 否则输出乘法式子
for (i = 1; i <= 9; i++)for (j = 1; j <= 9; j++)if(j < i) printf(" "); // 空格占位
else printf("%d×%d=%-2d ", i, j, i*j);#include <stdio.h>
int main() {
int i, j;
for (i = 1; i <= 9; i++) {
for (j = 1; j <= 9; j++) {
if (j < i) {
printf(" ");
} else {
printf("%d×%d=%-2d ", i, j, i*j);
}
}
printf("\n");
}
return 0;
}这道题如果你结合前两道其实难度不大,不作过多讲解
#include <stdio.h>
int main() {
int i, j;
for (i = 1; i <= 9; i++) {
for (j = 1; j <= 9; j++) {
printf("%d×%d=%-2d ", i, j, i*j);
}
printf("\n");
}
return 0;
}#include <stdio.h>
int main() {
int i, j;
for (i = 1; i <= 9; i++) {
for (j = 1; j <= 10-i; j++) {
printf("%d×%d=%-2d ", i, j, i*j);
}
printf("\n");
}
return 0;
}注意 这道题的第二个for循环
i~10-i(结合乘法表理解)
难点 计算需要前面需要打印多少个空格
第1行:9-1=8组空格 第2行:9-2=7组空格 … 第9行:9-9=0组空格
设计思路
格式调整技巧
#include <stdio.h>
int main() {
int i, j, k;
for (i = 1; i <= 9; i++) {
// 打印前导空格,实现居中效果
for (k = 1; k <= 9 - i; k++) {
printf(" "); // 每个乘法项预留4个字符空间
}
// 打印乘法表内容
for (j = 1; j <= i; j++) {
printf("%d×%d=%-2d ", j, i, j * i);
}
printf("\n");
}
return 0;
}首先你能看到这里,坚持到这里,小编倍感荣幸能和你一起在代码的世界里面奋斗 分支与循环是是所有代码编程的重难点,所以一方面为让大家掌握透彻,另一方面小编也是在突破自己 代码的世界很精彩,希望小编能陪伴你走完
C语言剩下的路程!!