C语言100个经典编程练习题(完整标题+清晰排版)

以下是整理后的100道编程练习题,补充了完整标题并按序号清晰排版,覆盖基础语法、算法、数据结构、预处理指令、位运算、图形绘制、文件操作等核心知识点:

序号 完整题目名称
1 用指定数字组无重复数字的数
2 根据销售阶段计算利润提成
3 判断一个数是否为完全平方数
4 根据日期判断当年第几天
5 将输入的三个数按由小到大顺序输出
6 用字符输出字母C的图案
7 输出自定义的特殊图案(如菱形、心形等)
8 打印9*9乘法口诀表
9 输出国际象棋棋盘图案(黑白交替)
10 用字符打印笑脸图案
11 求解斐波那契数列(递归/非递归)
12 找出101到200之间的所有素数
13 找出指定范围内的水仙花数(三位数各位立方和等于本身)
14 对输入的正整数分解质因数
15 用三目运算符(a>b)?a:b求两个数的最大值
16 求两个数的最大公约数和最小公倍数
17 统计字符串中字母、数字、空格及其他字符的个数
18 计算s=a+aa+aaa+aaaa+...+a...a(n个a)的值
19 找出指定范围内的完数(所有真因子和等于本身)
20 计算球从指定高度落下后的反弹距离及总路程
21 猴子吃桃问题(递推求解剩余桃子数)
22 乒乓球比赛胜负推理(逻辑判断)
23 打印指定的几何图案(如三角形、正方形等)
24 计算数列2/1 + 3/2 + 5/3 + 8/5 + ...前n项和
25 求1!+2!+3!+...+n!的阶乘和
26 用递归方法求n的阶乘
27 逆序打印输入的字符串(字符)
28 根据条件推理人物的岁数
29 逆序打印一个整数的各位数字
30 判断一个整数是否为回文数(正反读相同)
31 根据数字(1-7)判断对应的星期几
32 删除字符串中指定的字母
33 判断一个数是否为质数(素数)
34 练习函数的定义、声明与调用(多函数协作)
35 实现字符串的反转(指针/数组方式)
36 找出100以内的所有素数
37 实现各种排序算法(冒泡、选择、插入、快速排序等)
38 计算二维矩阵对角线元素的和
39 将一个数插入到有序数组中并保持有序
40 将数组元素逆序输出
41 练习static关键字用法1(局部静态变量)
42 练习auto关键字的用法(自动变量)
43 练习static关键字用法2(全局静态变量/函数)
44 调用外部文件中的函数(多文件编程)
45 练习register关键字的用法(寄存器变量)
46 宏#define练习1(定义常量)
47 宏#define练习2(定义带参数的宏)
48 宏#define练习3(宏替换与函数对比)
49 练习#if、#ifdef、#ifndef条件编译指令
50 练习#include预处理指令(头文件包含)
51 练习按位与&运算符的使用
52 练习按位或
53 练习按位异或^运算符的使用
54 提取一个整数右端第4~7位的二进制数
55 练习按位取反~运算符的使用
56 用图形库circle函数绘制圆形
57 用图形库line函数绘制直线
58 用图形库rectangle函数绘制方形/矩形
59 综合画图1(组合圆形、直线、矩形)
60 综合画图2(绘制复杂图案如五角星、多边形)
61 打印杨辉三角形(帕斯卡三角)
62 用putpixel函数绘制像素点(基础画图)
63 用图形库ellipse函数绘制椭圆
64 自定义画图(如绘制正弦曲线)
65 绘制优美的图案(如螺旋线、分形图案)
66 用指针实现数组元素按大小排序
67 实现数组中指定位置元素的交换
68 将数组中n个指定数字移到数组前面
69 解决约瑟夫环问题(循环链表/数组实现)
70 不使用库函数求字符串的长度
71 用结构体存储并操作学生数据(姓名、学号、成绩等)
72 创建单向链表并添加节点
73 反向输出链表中的节点数据
74 将两个有序链表合并为一个有序链表
75 整数反转输出(如123→321)
76 计算数列1/2 + 1/4 + 1/8 + ... + 1/n的和
77 练习指针的指针(二级指针)操作
78 用结构体存储人员信息,找出年龄最大的人
79 对多个字符串按字典序排序
80 猴子分桃子问题(数学递推)
81 求解指定规则的特殊数(如自幂数、阿姆斯特朗数等)
82 将八进制数转换为十进制数
83 统计指定数字组成的奇数个数
84 验证哥德巴赫猜想(偶数可表示为两个素数之和)
85 找出能被几个9整除的素数
86 实现字符串连接程序(不使用strcat库函数)
87 结构体变量的传递(值传递/地址传递)
88 统计数组中指定值出现的个数并打印
89 实现简单的密码加密(如替换、移位)
90 分析代码并读输出结果(语法/逻辑分析)
91 时间函数库练习1(获取当前时间)
92 时间函数库练习2(计算时间差)
93 时间函数库练习3(格式化输出时间)
94 实现猜数字游戏(随机数+交互)
95 结构体综合练习(嵌套结构体、结构体数组)
96 统计一个子串在主字符串中出现的次数
97 将数据保存到txt文本文件中
98 实现字母的大小写转换
99 读取A.txt内容并处理后写入B.txt(文件对比/合并)
100 结构体数据的磁盘读写(序列化/反序列化)

C语言练习实例100例详解

目录

  • 实例详解
  • 附录
  • 总结

实例详解

实例1:组合无重复数字的三位数

题目:有1、2、3、4四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

程序分析

  • 可填在百位、十位、个位的数字都是1、2、3、4
  • 使用三重循环遍历所有排列组合(4×4×4=64种)
  • 通过条件i != j && i != k && j != k过滤掉有重复数字的情况
  • 满足条件的组合即为答案
复制代码
复制代码
#include <stdio.h>
#define MAX 5

int main() {
    int i, j, k;
    int count = 0;
    for (int i = 1; i < MAX; i++) {
        for (int j = 1; j < MAX; j++) {
            for (int k = 1; k < MAX; k++) {
                // 确保三个位置的数字不重复
                if (i != j && i != k && j != k) {
                    printf("%d%d%d\n", i, j, k);
                    count++;
                }
            }
        }
    }
    printf("总数:%d\n", count);
    return 0;
}

输出结果

复制代码
复制代码
123
124
...
432
总数:24

实例2:企业利润提成

题目:企业发放的奖金根据利润提成,规则如下:

  • 利润≤10万:提成10%
  • 10万<利润≤20万:低于10万部分提成10%,高于10万部分提成7.5%
  • 20万<利润≤40万:高于20万部分提成5%
  • 40万<利润≤60万:高于40万部分提成3%
  • 60万<利润≤100万:高于60万部分提成1.5%
  • 利润>100万:超过100万部分提成1%

程序分析

  • 使用#define LAC 100000定义常量10万
  • 预先计算各区间基准奖金,避免重复计算
  • 使用if-else if结构分段计算
  • 使用double类型处理金额,保证精度
复制代码
复制代码
#include <stdio.h>
#define LAC 100000 // 将10万定义为一个常量

int main() {
    double profit, bonus;
    double bonus_0_10, bonus_10_20, bonus_20_40, bonus_40_60, bonus_60_100;
    
    // 预先计算各区间基准奖金
    bonus_0_10 = LAC * 0.1;
    bonus_10_20 = LAC * 0.075;
    bonus_20_40 = LAC * 2 * 0.05;
    bonus_40_60 = LAC * 2 * 0.03;
    bonus_60_100 = LAC * 4 * 0.015;
    
    printf("请输入当月利润(元):");
    scanf("%lf", &profit);
    
    if (profit <= LAC) {
        bonus = profit * 0.1;
    } else if (profit <= LAC * 2) {
        bonus = bonus_0_10 + (profit - LAC) * 0.075;
    } else if (profit <= LAC * 4) {
        bonus = bonus_0_10 + bonus_10_20 + (profit - LAC * 2) * 0.05;
    } else if (profit <= LAC * 6) {
        bonus = bonus_0_10 + bonus_10_20 + bonus_20_40 + (profit - LAC * 4) * 0.03;
    } else if (profit <= LAC * 10) {
        bonus = bonus_0_10 + bonus_10_20 + bonus_20_40 + bonus_40_60 + (profit - LAC * 6) * 0.015;
    } else {
        bonus = bonus_0_10 + bonus_10_20 + bonus_20_40 + bonus_40_60 + bonus_60_100 + (profit - LAC * 10) * 0.01;
    }
    
    printf("应发放奖金总数:%.2lf元\n", bonus);
    return 0;
}

实例3:完全平方数问题

题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

程序分析

  • 设该数为x,则:x + 100 = n²,x + 100 + 168 = m²
  • 推导得:m² - n² = 168 → (m + n)(m - n) = 168
  • 设m + n = i,m - n = j,则i × j = 168
  • 由数学推导可知i与j必须均为偶数
  • 遍历i从2到84(168/2),找出满足条件的解
复制代码
复制代码
#include <stdio.h>

int main() {
    int i, j, m, n, x;
    printf("---------------------------------------\n");
    for (i = 2; i <= 168 / 2; i++) {
        if (168 % i == 0) { // i必须是168的因子
            j = 168 / i;
            if (i > j && (i + j) % 2  0 && (i - j) % 2  0) {
                m = (i + j) / 2;
                n = (i - j) / 2;
                x = n * n - 100;
                printf("%d + 100 = %d²\n", x, n);
                printf("%d + 100 + 168 = %d²\n", x, m);
                printf("---------------------------------------\n");
            }
        }
    }
    return 0;
}

答案-7521都满足条件


实例4:判断当年第几天

题目:输入某年某月某日,判断这一天是这一年的第几天?

程序分析

  • 使用switch语句累加前几个月的天数
  • 判断是否为闰年:(year%4000) || (year%40 && year%100!=0)
  • 如果是闰年且月份大于2,总天数加1
复制代码
复制代码
#include <stdio.h>

int main() {
    int year, month, day, leap = 0;
    int sum = 0;
    
    printf("请输入年月日(格式:2023,5,20):");
    scanf("%d,%d,%d", &year, &month, &day);
    
    // 计算前几个月的总天数
    switch (month) {
        case 12: sum += 334;
        case 11: sum += 304;
        case 10: sum += 273;
        case 9:  sum += 243;
        case 8:  sum += 212;
        case 7:  sum += 181;
        case 6:  sum += 151;
        case 5:  sum += 120;
        case 4:  sum += 90;
        case 3:  sum += 59;
        case 2:  sum += 31;
        case 1:  sum += 0;
    }
    
    sum += day; // 加上当月天数
    
    // 判断闰年
    if ((year % 400  0) || (year % 4  0 && year % 100 != 0)) {
        leap = 1;
    }
    
    // 闰年且月份大于2,加1天
    if (leap && month > 2) {
        sum++;
    }
    
    printf("%d年%d月%d日是这一年的第%d天\n", year, month, day, sum);
    return 0;
}

实例5:三个数由小到大

题目:输入三个整数x、y、z,请把这三个数由小到大输出。

程序分析

  • 使用指针交换法,通过自定义swap函数交换数值
  • 采用冒泡排序思想:先让x存储最小值,再让y存储中间值,最后z为最大值
  • 只需3次比较交换即可完成排序
复制代码
复制代码
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x, y, z;
    
    printf("输入三个整数(用空格分隔):");
    scanf("%d %d %d", &x, &y, &z);
    
    // 三次比较交换完成排序
    if (x > y) swap(&x, &y);
    if (x > z) swap(&x, &z);
    if (y > z) swap(&y, &z);
    
    printf("排序结果:%d %d %d\n", x, y, z);
    return 0;
}

实例6:输出字母C图案

题目 :用*号输出字母C的图案。

程序分析

  • 观察字母C的形状:上下各一行4个*,左侧一列3个*
  • 使用printf分行输出即可
  • 注意空格控制形状比例
复制代码
复制代码
#include <stdio.h>

int main() {
    printf("用 * 号输出字母 C!\n");
    printf("  ****\n");
    printf(" *\n");
    printf("*\n");
    printf(" *\n");
    printf("  ****\n");
    return 0;
}

实例7:输出特殊图案

题目:输出特殊图案,请在C环境中运行查看效果。

程序分析

  • 使用扩展ASCII码(176和219)绘制图案
  • 在VC6.0等现代IDE中可能出现中文乱码
  • 需设置控制台代码页为437(OEM-美国)才能正确显示
  • 原理:0xB0DB是"佰"字的内码,导致显示异常
复制代码
复制代码
#include <stdio.h>

int main() {
    char a = 176, b = 219;
    printf("%c%c%c%c%c\n", b, a, a, a, b);
    printf("%c%c%c%c%c\n", a, b, a, b, a);
    printf("%c%c%c%c%c\n", a, a, b, a, a);
    printf("%c%c%c%c%c\n", a, b, a, b, a);
    printf("%c%c%c%c%c\n", b, a, a, a, b);
    return 0;
}

注意:在Windows系统下,需将控制台代码页修改为437才能正确显示图案。


实例8:9×9乘法表

题目:输出9×9口诀表。

程序分析

  • 使用双重循环,外层控制行(1-9),内层控制列
  • 内层循环上限随外层变化:j <= i
  • 每行结束后换行
复制代码
复制代码
#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;
}

格式优化 :使用%-2d使输出左对齐,保持整齐


实例9:国际象棋棋盘

题目:输出国际象棋棋盘。

程序分析

  • 棋盘为8×8的黑白相间格子
  • 使用双重循环控制行列
  • 通过(i+j)%2==0判断黑白格
  • 使用ASCII码219(█)表示黑格
复制代码
复制代码
#include <stdio.h>

int main() {
    int i, j;
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            if ((i + j) % 2 == 0) {
                printf("%c%c", 219, 219); // 黑格
            } else {
                printf("  "); // 白格
            }
        }
        printf("\n");
    }
    return 0;
}

实例10:打印楼梯与笑脸

题目:打印楼梯,同时在楼梯上方打印两个笑脸。

程序分析

  • 使用ASCII码1(☺)输出笑脸
  • 使用嵌套循环控制楼梯层数和每层的方块数
  • 每层楼梯宽度递增,形成阶梯效果
复制代码
复制代码
#include <stdio.h>

int main() {
    int i, j;
    printf("\1\1\n"); /* 输出两个笑脸(ASCII码1) */
    
    for (i = 1; i < 11; i++) {
        for (j = 1; j <= i; j++) {
            printf("%c%c", 219, 219); // 输出楼梯方块
        }
        printf("\n");
    }
    return 0;
}

实例11:斐波那契数列

题目:古典问题:一对兔子,从出生后第3个月起每月生一对兔子,小兔子长到第3个月后每月又生一对,假设兔子不死,问第n个月的兔子总数?

程序分析

  • 数列规律:1, 1, 2, 3, 5, 8, 13, 21...
  • 递推公式:F(n) = F(n-1) + F(n-2)(n≥2)
  • 代码提供递归实现,时间复杂度O(2^n)
  • 建议补充迭代版本以提高效率
复制代码
复制代码
#include <stdio.h>

// 递归实现(效率较低)
int fibonacci(int n) {
    if (n < 2) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 建议补充:迭代实现(效率高)
int fibonacci_iter(int n) {
    if (n < 2) return n;
    int a = 0, b = 1, c;
    for (int i = 2; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return b;
}

int main() {
    int n;
    printf("请输入月份n:");
    scanf("%d", &n);
    printf("第%d个月有%d对兔子\n", n, fibonacci(n));
    return 0;
}

说明:当n较大时(如n>40),递归版本性能急剧下降,建议使用迭代版本。


实例12:101到200的素数

题目:判断101到200之间的所有素数。

程序分析

  • 素数定义:大于1的自然数,除了1和自身外不能被其他数整除
  • 优化:只需检验到√n即可
  • further优化:排除偶数,只检验奇数
复制代码
复制代码
#include <stdio.h>
#include <stdbool.h>

bool isPrime(int num) {
    if (num <= 1) return false;
    if (num  2) return true;
    if (num % 2  0) return false;
    
    for (int i = 3; i * i <= num; i += 2) {
        if (num % i == 0) return false;
    }
    return true;
}

int main() {
    int count = 0;
    printf("101到200之间的素数:\n");
    for (int i = 101; i <= 200; i++) {
        if (isPrime(i)) {
            printf("%d  ", i);
            count++;
            if (count % 5 == 0) printf("\n"); // 每5个换行
        }
    }
    printf("\n总数:%d个\n", count);
    return 0;
}

输出:共21个素数


实例13:水仙花数

题目:打印所有"水仙花数"(三位数,各位数字立方和等于该数本身)。

程序分析

  • 遍历100-999所有三位数
  • 分解出个位、十位、百位
  • 判断:num == b³ + s³ + g³
复制代码
复制代码
#include <stdio.h>

int main() {
    int num, g, s, b;
    printf("水仙花数:\n");
    for (num = 100; num <= 999; num++) {
        b = num / 100;          // 百位
        s = (num / 10) % 10;    // 十位
        g = num % 10;           // 个位
        
        if (num == b * b * b + s * s * s + g * g * g) {
            printf("%d  ", num);
        }
    }
    printf("\n");
    return 0;
}

答案:153, 370, 371, 407


实例14:分解质因数

题目:将一个正整数分解质因数。

程序分析

  • 从最小的质数2开始试除
  • 如果能整除,则输出该质因数,并用商继续分解
  • 如果不能整除,则尝试下一个数
  • 直到商为1时结束
复制代码
复制代码
#include <stdio.h>

void primeFactors(int n) {
    printf("%d = ", n);
    int divisor = 2;
    
    while (n > 1) {
        while (n % divisor == 0) {
            printf("%d", divisor);
            n /= divisor;
            if (n > 1) printf(" * ");
        }
        divisor++;
    }
    printf("\n");
}

int main() {
    int num;
    printf("请输入一个正整数:");
    scanf("%d", &num);
    primeFactors(num);
    return 0;
}

示例 :输入90,输出90 = 2 * 3 * 3 * 5


实例15:条件运算符嵌套

题目:利用条件运算符的嵌套完成成绩评级:≥90分为A,60-89分为B,<60分为C。

程序分析

  • 三目运算符格式:条件 ? 表达式1 : 表达式2
  • 嵌套使用可实现多分支判断
  • 优先级:grade = (score>=90) ? 'A' : ((score>=60) ? 'B' : 'C')
复制代码
复制代码
#include <stdio.h>

int main() {
    int score;
    char grade;
    
    printf("请输入成绩:");
    scanf("%d", &score);
    
    grade = (score >= 90) ? 'A' : (score >= 60 ? 'B' : 'C');
    
    printf("成绩等级:%c\n", grade);
    return 0;
}

实例16:最大公约数与最小公倍数

题目:输入两个正整数m和n,求其最大公约数(GCD)和最小公倍数(LCM)。

程序分析

  • 最大公约数使用辗转相除法(欧几里得算法)
  • 最小公倍数公式:LCM = m × n / GCD
  • 辗转相除法:反复用较小数除较大数取余,直到余数为0
复制代码
复制代码
#include <stdio.h>

// 计算最大公约数
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

// 计算最小公倍数
int lcm(int a, int b) {
    return (a * b) / gcd(a, b);
}

int main() {
    int m, n;
    printf("请输入两个正整数:");
    scanf("%d %d", &m, &n);
    
    printf("最大公约数:%d\n", gcd(m, n));
    printf("最小公倍数:%d\n", lcm(m, n));
    
    return 0;
}

示例:输入12和18,GCD=6,LCM=36


实例17:统计字符类型

题目:输入一行字符,统计英文字母、空格、数字和其他字符的个数。

程序分析

  • 使用getchar()循环读取字符,直到遇到换行符\n
  • 使用if-else if判断字符类型:
    • 字母:(c>='a'&&c<='z') || (c>='A'&&c<='Z')
    • 数字:c>='0' && c<='9'
    • 空格:c==' '
    • 其他:以上都不是
复制代码
复制代码
#include <stdio.h>

int main() {
    char c;
    int letters = 0, spaces = 0, digits = 0, others = 0;
    
    printf("请输入一行字符:\n");
    while ((c = getchar()) != '\n') {
        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
            letters++;
        } else if (c >= '0' && c <= '9') {
            digits++;
        } else if (c == ' ') {
            spaces++;
        } else {
            others++;
        }
    }
    
    printf("字母:%d,数字:%d,空格:%d,其他:%d\n", letters, digits, spaces, others);
    return 0;
}

实例18:数字序列求和

题目:求s = a + aa + aaa + ... + aa...a(n个a)的值。

程序分析

  • 第i项的值:前一项×10 + a
  • 累加每一项得到最终结果
  • 例如a=2, n=5时:2 + 22 + 222 + 2222 + 22222
复制代码
复制代码
#include <stdio.h>

// 生成第n项的值
int generateTerm(int a, int n) {
    int term = 0;
    for (int i = 0; i < n; i++) {
        term = term * 10 + a;
    }
    return term;
}

int main() {
    int a, n;
    long long sum = 0;
    
    printf("请输入数字a和项数n:");
    scanf("%d %d", &a, &n);
    
    for (int i = 1; i <= n; i++) {
        int term = generateTerm(a, i);
        sum += term;
        printf("%d ", term);
        if (i < n) printf("+ ");
    }
    printf("= %lld\n", sum);
    
    return 0;
}

实例19:完数查找

题目:一个数如果恰好等于它的因子之和,这个数就称为"完数"。找出1000以内的所有完数。

程序分析

  • 完数例子:6 = 1 + 2 + 3
  • 因子不包括自身
  • 优化:只需检查到√n,成对添加因子
复制代码
复制代码
#include <stdio.h>

int sumOfFactors(int n) {
    int sum = 1; // 1是所有正整数的因子
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            sum += i;
            if (i != n / i) { // 避免平方数重复添加
                sum += n / i;
            }
        }
    }
    return sum;
}

int main() {
    printf("1000以内的完数:\n");
    for (int i = 2; i <= 1000; i++) {
        if (sumOfFactors(i) == i) {
            printf("%d = 1", i);
            for (int j = 2; j < i; j++) {
                if (i % j == 0) printf(" + %d", j);
            }
            printf("\n");
        }
    }
    return 0;
}

答案:6, 28, 496


实例20:球体反弹问题

题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半。求第10次落地时共经过多少米?第10次反弹多高?

程序分析

  • 初始下落:100米
  • 每次反弹高度 = 前一次高度 / 2
  • 从第2次开始,每次经过的距离 = 反弹高度 × 2(上升+下落)
  • 第10次落地时,总距离不包含最后一次反弹上升
复制代码
复制代码
#include <stdio.h>

int main() {
    double height = 100.0;      // 初始高度
    double totalDistance = 100.0; // 第一次下落距离
    
    // 计算第2到10次落地
    for (int i = 2; i <= 10; i++) {
        height /= 2;            // 反弹高度减半
        totalDistance += height * 2; // 上升+下落
    }
    
    double finalRebound = height / 2; // 第10次反弹高度
    
    printf("第10次落地时总路程:%.2f米\n", totalDistance);
    printf("第10次反弹高度:%.2f米\n", finalRebound);
    
    return 0;
}

答案:总路程约299.61米,第10次反弹约0.10米


实例21:猴子吃桃问题

题目(反向推理):猴子第1天摘了若干桃子,当天吃了一半多一个;以后每天早上吃前一天剩下的一半多一个。第10天早上剩1个,求第1天摘了多少?

程序分析

  • 逆向思维:第10天剩1个 → 第9天有(1+1)×2=4个 → 第8天有(4+1)×2=10个
  • 递推公式:peaches_{n-1} = (peaches_n + 1) × 2
  • 从第10天倒推9次到第1天
复制代码
复制代码
#include <stdio.h>

int main() {
    int peaches = 1; // 第10天的桃子数
    
    for (int day = 10; day > 1; day--) {
        peaches = (peaches + 1) * 2;
    }
    
    printf("第一天共摘了 %d 个桃子\n", peaches);
    return 0;
}

答案:1534个


实例22:乒乓球比赛名单

题目:甲队a,b,c对阵乙队x,y,z。a说不和x比,c说不和x,z比,求比赛名单。

程序分析

  • 使用暴力枚举法,遍历所有可能的对阵组合
  • 约束条件:
    • a ≠ x
    • c ≠ x 且 c ≠ z
    • 每人对手唯一(i ≠ j ≠ k)
复制代码
复制代码
#include <stdio.h>

int main() {
    char i, j, k; // i,j,k分别代表a,b,c的对手
    
    for (i = 'x'; i <= 'z'; i++) {
        for (j = 'x'; j <= 'z'; j++) {
            if (i != j) { // 确保a和b对手不同
                for (k = 'x'; k <= 'z'; k++) {
                    // 满足所有约束条件
                    if (i != k && j != k && i != 'x' && k != 'x' && k != 'z') {
                        printf("比赛名单:a-%c  b-%c  c-%c\n", i, j, k);
                    }
                }
            }
        }
    }
    return 0;
}

答案:a-z, b-y, c-x


实例23:打印菱形图案

题目:打印如下菱形图案:

复制代码
复制代码
   *
  ***
 *****
*******
 *****
  ***
   *

程序分析

  • 分上下两部分打印
  • 上半部分行数n=4(包含中间行)
  • 每行:前导空格数 = n - i - 1,星号数 = 2 × i + 1
  • 下半部分对称递减
复制代码
复制代码
#include <stdio.h>

int main() {
    int n = 4; // 上半部分行数
    
    // 打印上半部分(包括中间行)
    for (int i = 0; i < n; i++) {
        // 打印前导空格
        for (int j = 0; j < n - i - 1; j++) {
            printf(" ");
        }
        // 打印星号
        for (int k = 0; k < 2 * i + 1; k++) {
            printf("*");
        }
        printf("\n");
    }
    
    // 打印下半部分
    for (int i = n - 2; i >= 0; i--) {
        for (int j = 0; j < n - i - 1; j++) {
            printf(" ");
        }
        for (int k = 0; k < 2 * i + 1; k++) {
            printf("*");
        }
        printf("\n");
    }
    
    return 0;
}

实例24:分数序列求和

题目:数列:2/1, 3/2, 5/3, 8/5, 13/8, 21/13...求前20项之和。

程序分析

  • 分子分母均为斐波那契数列
  • 分子 = F(n+1),分母 = F(n)
  • 建议用迭代生成斐波那契数,避免递归重复计算
复制代码
复制代码
#include <stdio.h>

// 迭代生成斐波那契数
int fibonacci(int n) {
    if (n  0) return 0;
    if (n  1) return 1;
    
    int a = 0, b = 1, c;
    for (int i = 2; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return b;
}

int main() {
    double sum = 0.0;
    printf("前20项和:");
    
    for (int i = 1; i <= 20; i++) {
        int denominator = fibonacci(i);     // 分母
        int numerator = fibonacci(i + 1);   // 分子
        sum += (double)numerator / denominator;
        printf("%.4f + ", (double)numerator / denominator);
    }
    
    printf("\b\b= %.6f\n", sum);
    return 0;
}

实例25:阶乘的和

题目:计算1! + 2! + 3! + ... + 20!的值。

程序分析

  • 20! = 2,432,902,008,176,640,000(超过32位整数范围)
  • 使用unsigned long long(64位)存储
  • 可优化:利用前一项结果计算后一项,n! = n × (n-1)!
复制代码
复制代码
#include <stdio.h>

// 计算阶乘
unsigned long long factorial(int n) {
    unsigned long long result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

int main() {
    unsigned long long sum = 0;
    
    for (int i = 1; i <= 20; i++) {
        sum += factorial(i);
    }
    
    printf("1! + 2! + ... + 20! = %llu\n", sum);
    return 0;
}

优化版本

复制代码
复制代码
int main() {
    unsigned long long sum = 0, fact = 1;
    for (int i = 1; i <= 20; i++) {
        fact *= i;      // 递推计算i!
        sum += fact;    // 累加
    }
    printf("结果:%llu\n", sum);
    return 0;
}

实例26:递归求阶乘

题目:利用递归方法求5!。

程序分析

  • 递归定义:n! = n × (n-1)!
  • 终止条件:0! = 1! = 1
  • 递归深度过大会导致栈溢出
复制代码
复制代码
#include <stdio.h>

int factorial(int n) {
    // 基准条件
    if (n  0 || n  1) {
        return 1;
    }
    // 递归调用
    return n * factorial(n - 1);
}

int main() {
    int result = factorial(5);
    printf("5! = %d\n", result);
    return 0;
}

递归调用栈

复制代码
复制代码
factorial(5)
→ 5 × factorial(4)
→ 5 × 4 × factorial(3)
→ 5 × 4 × 3 × factorial(2)
→ 5 × 4 × 3 × 2 × factorial(1)
→ 5 × 4 × 3 × 2 × 1 = 120

实例27:逆序打印字符

题目:利用递归函数,将输入的5个字符以相反顺序打印。

程序分析

  • 递归思路:先递归打印后面的字符,再打印当前字符
  • 基准条件:索引小于0时停止
  • 或使用栈结构实现非递归版本
复制代码
复制代码
#include <stdio.h>

void reversePrint(char str[], int index) {
    if (index < 0) return; // 基准条件
    
    printf("%c", str[index]);
    reversePrint(str, index - 1); // 递归调用
}

int main() {
    char str[6]; // 5字符+1个'\0'
    printf("请输入5个字符:");
    scanf("%5s", str);
    
    printf("逆序输出:");
    reversePrint(str, 4);
    printf("\n");
    
    return 0;
}

实例28:岁数推理

题目:5个人依次比前一个人大2岁,第1个人10岁,第5个人多少岁?

程序分析

  • 递推关系:age(n) = age(n-1) + 2
  • 已知基准:age(1) = 10
  • 可使用递归或简单循环
复制代码
复制代码
#include <stdio.h>

int getAge(int person) {
    if (person == 1) {
        return 10; // 基准条件
    }
    return getAge(person - 1) + 2; // 递归
}

int main() {
    printf("第五个人的年龄:%d岁\n", getAge(5));
    return 0;
}

答案:18岁


实例29:逆序打印整数各位

题目:给一个不多于5位的正整数,求它是几位数,并逆序打印各位数字。

程序分析

  • 通过除法和取模运算分解各位
  • 从高位到低位判断是否为0确定位数
  • 逆序打印:个位→十位→百位→千位→万位
复制代码
复制代码
#include <stdio.h>

int main() {
    int num, temp;
    int digits[5] = {0};
    int count = 0;
    
    printf("请输入一个正整数(≤5位):");
    scanf("%d", &num);
    
    temp = num;
    // 分解各位并逆序存储
    while (temp > 0) {
        digits[count++] = temp % 10;
        temp /= 10;
    }
    
    printf("这是%d位数\n", count);
    printf("逆序打印:");
    for (int i = 0; i < count; i++) {
        printf("%d", digits[i]);
    }
    printf("\n");
    
    return 0;
}

实例30:判断回文数

题目:判断一个5位数是否为回文数(如12321)。

程序分析

  • 回文条件:个位万位 && 十位千位
  • 分解各位数字进行比较
复制代码
复制代码
#include <stdio.h>

int main() {
    int num, ge, shi, qian, wan;
    
    printf("请输入一个5位数:");
    scanf("%d", &num);
    
    wan = num / 10000;          // 万位
    qian = (num / 1000) % 10;   // 千位
    shi = (num / 10) % 10;      // 十位
    ge = num % 10;              // 个位
    
    if (ge  wan && shi  qian) {
        printf("%d是回文数\n", num);
    } else {
        printf("%d不是回文数\n", num);
    }
    
    return 0;
}

实例31:判断星期几

题目:输入星期几的首字母判断是星期几,若首字母相同则继续判断第二个字母。

程序分析

  • 使用switch处理首字母
  • 对冲突的t/s,用if判断第二个字母
  • 注意getchar()读取换行符的问题
复制代码
复制代码
#include <stdio.h>

int main() {
    char first, second;
    
    printf("请输入星期几的首字母:");
    scanf("%c", &first);
    
    switch (first) {
        case 'm': printf("Monday\n"); break;
        case 'w': printf("Wednesday\n"); break;
        case 'f': printf("Friday\n"); break;
        case 't':
            printf("请输入第二个字母:");
            scanf(" %c", &second); // 注意空格跳过换行符
            if (second  'u') printf("Tuesday\n");
            else if (second  'h') printf("Thursday\n");
            break;
        case 's':
            printf("请输入第二个字母:");
            scanf(" %c", &second);
            if (second  'a') printf("Saturday\n");
            else if (second  'u') printf("Sunday\n");
            break;
        default: printf("输入错误\n");
    }
    
    return 0;
}

实例32:删除字符串指定字母

题目:删除字符串中的指定字母(如"aca"删除'a'变为"c")。

程序分析

  • 双指针法:一个读,一个写
  • 遍历原字符串,遇到非删除字符则写入新位置
  • 最后添加字符串结束符\0
复制代码
复制代码
#include <stdio.h>
#include <string.h>

void removeChar(char *str, char ch) {
    int src = 0, dst = 0;
    while (str[src] != '\0') {
        if (str[src] != ch) {
            str[dst++] = str[src];
        }
        src++;
    }
    str[dst] = '\0';
}

int main() {
    char str[] = "Hello World";
    char ch = 'l';
    
    printf("原字符串:%s\n", str);
    removeChar(str, ch);
    printf("删除'%c'后:%s\n", ch, str);
    
    return 0;
}

实例33:判断质数

题目:判断一个数是否为质数。

程序分析

  • 质数定义:≥2的自然数,只能被1和自身整除
  • 优化:排除偶数,只检查奇数因子到√n
复制代码
复制代码
#include <stdio.h>
#include <stdbool.h>

bool isPrime(int num) {
    if (num < 2) return false;
    if (num  2) return true;
    if (num % 2  0) return false;
    
    for (int i = 3; i * i <= num; i += 2) {
        if (num % i == 0) return false;
    }
    return true;
}

int main() {
    int num;
    printf("请输入一个整数:");
    scanf("%d", &num);
    
    if (isPrime(num)) {
        printf("%d是质数\n", num);
    } else {
        printf("%d不是质数\n", num);
    }
    
    return 0;
}

实例34:练习函数调用

题目:练习函数调用。

程序分析

  • 简单演示函数调用关系
  • mainthree_helloshello_world
  • 展示代码模块化思想
复制代码
复制代码
#include <stdio.h>

void helloWorld(void) {
    printf("Hello, world!\n");
}

void threeHellos(void) {
    for (int i = 0; i < 3; i++) {
        helloWorld(); // 调用3次
    }
}

int main(void) {
    threeHellos(); // 主函数调用
    return 0;
}

实例35:字符串反转

题目:将字符串反转(如"www.csdn.net"→"ten.ndcs.www")。

程序分析

  • 双指针法:头指针和尾指针交换字符
  • 直到两指针相遇或交叉
复制代码
复制代码
#include <stdio.h>
#include <string.h>

void reverseString(char *str) {
    int left = 0;
    int right = strlen(str) - 1;
    char temp;
    
    while (left < right) {
        // 交换字符
        temp = str[left];
        str[left] = str[right];
        str[right] = temp;
        
        left++;
        right--;
    }
}

int main() {
    char str[] = "www.csdn.net";
    printf("原字符串:%s\n", str);
    
    reverseString(str);
    printf("反转后:%s\n", str);
    
    return 0;
}

实例36:100以内的素数

题目:输出100以内的所有素数。

程序分析

  • 双重循环:外层遍历2-100,内层检验是否为素数
  • 内层只需检验到√i
  • 优化:跳过偶数
复制代码
复制代码
#include <stdio.h>
#include <math.h>

int main() {
    int count = 0;
    printf("100以内的素数:\n");
    
    // 2是素数
    printf("2  ");
    count++;
    
    for (int i = 3; i <= 100; i += 2) { // 跳过偶数
        int isPrime = 1;
        int k = (int)sqrt(i);
        
        for (int j = 2; j <= k; j++) {
            if (i % j == 0) {
                isPrime = 0;
                break;
            }
        }
        
        if (isPrime) {
            printf("%d  ", i);
            count++;
            if (count % 10 == 0) printf("\n");
        }
    }
    
    printf("\n总数:%d个\n", count);
    return 0;
}

答案:共25个素数


实例37:数组排序算法

题目:对10个数进行排序(演示插入排序、选择排序、冒泡排序)。

程序分析

  • 提供三种基础排序算法实现
  • 插入排序:将元素插入已排序序列
  • 选择排序:每次选择最小元素
  • 冒泡排序:相邻元素两两比较
复制代码
复制代码
#include <stdio.h>

// 插入排序
void insertionSort(int arr[], int n) {
    for (int i = 1; i < n; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

// 选择排序
void selectionSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int minIdx = i;
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIdx]) {
                minIdx = j;
            }
        }
        // 交换
        int temp = arr[i];
        arr[i] = arr[minIdx];
        arr[minIdx] = temp;
    }
}

// 冒泡排序
void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[] = {64, 34, 25, 12, 22, 11, 90, 88, 76, 45};
    int n = sizeof(arr) / sizeof(arr[0]);
    
    printf("原数组:");
    printArray(arr, n);
    
    // 测试插入排序
    int arr1[10];
    memcpy(arr1, arr, sizeof(arr));
    insertionSort(arr1, n);
    printf("插入排序后:");
    printArray(arr1, n);
    
    return 0;
}

实例38:矩阵对角线元素和

题目:求一个3×3矩阵的主对角线元素之和。

程序分析

  • 对角线元素特征:行号 == 列号,即a[i][i]
  • 使用双重循环输入矩阵
  • 累加对角线元素
复制代码
复制代码
#include <stdio.h>
#define N 3

int main() {
    int matrix[N][N];
    int sum = 0;
    
    printf("请输入3×3矩阵:\n");
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }
    
    // 计算主对角线和
    for (int i = 0; i < N; i++) {
        sum += matrix[i][i];
    }
    
    printf("主对角线元素和:%d\n", sum);
    return 0;
}

实例39:数组插入元素

题目:在已排序数组中插入一个数,保持原有顺序。

程序分析

  • 从后往前比较,找到插入位置
  • 元素后移腾出空间
  • 插入新元素
复制代码
复制代码
#include <stdio.h>

void insertSorted(int arr[], int *n, int num) {
    int i;
    // 找到插入位置并后移元素
    for (i = *n - 1; i >= 0 && arr[i] > num; i--) {
        arr[i + 1] = arr[i];
    }
    arr[i + 1] = num;
    (*n)++;
}

void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[20] = {1, 3, 5, 7, 9};
    int n = 5;
    int num = 4;
    
    printf("原数组:");
    printArray(arr, n);
    
    insertSorted(arr, &n, num);
    
    printf("插入%d后:", num);
    printArray(arr, n);
    
    return 0;
}

实例40:数组逆序输出

题目:将一个数组逆序输出。

程序分析

  • 双指针交换法:首尾元素逐个交换
  • 只需遍历一半数组
复制代码
复制代码
#include <stdio.h>
#define N 10

int main() {
    int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    printf("原数组:");
    for (int i = 0; i < N; i++) {
        printf("%d ", arr[i]);
    }
    
    // 逆序
    for (int i = 0; i < N / 2; i++) {
        int temp = arr[i];
        arr[i] = arr[N - i - 1];
        arr[N - i - 1] = temp;
    }
    
    printf("\n逆序后:");
    for (int i = 0; i < N; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}

实例41:static用法1

题目:学习static定义静态变量的用法。

程序分析

  • static变量生命周期贯穿整个程序
  • 只初始化一次,保留上次调用值
  • 对比普通局部变量(每次调用重新初始化)
复制代码
复制代码
#include <stdio.h>

void funcWithoutStatic() {
    int x = 0; // 普通局部变量
    x++;
    printf("普通变量:%d\n", x);
}

void funcWithStatic() {
    static int x = 0; // 静态变量,只初始化一次
    x++;
    printf("静态变量:%d\n", x);
}

int main() {
    printf("第一次调用:\n");
    funcWithoutStatic();
    funcWithStatic();
    
    printf("\n第二次调用:\n");
    funcWithoutStatic(); // 重新初始化为0,输出1
    funcWithStatic();    // 保留上次的值,输出2
    
    return 0;
}

输出

复制代码
复制代码
第一次调用:
普通变量:1
静态变量:1

第二次调用:
普通变量:1
静态变量:2

实例42:auto用法

题目:学习auto定义变量的用法。

程序分析

  • auto是默认存储类型,可省略
  • 作用域为块作用域,随块结束而销毁
  • 现代C语言中很少显式使用
复制代码
复制代码
#include <stdio.h>

int main() {
    int num = 2; // 等价于auto int num = 2;
    
    for (int i = 0; i < 3; i++) {
        printf("外层num: %d\n", num);
        num++;
        
        {
            auto int num = 1; // 块作用域,覆盖外层的num
            printf("内层num: %d\n", num);
            num++;
        }
        // 内层num已销毁
    }
    
    return 0;
}

实例43:static用法2

题目:学习static的另一用法。

程序分析

  • 演示静态变量在块作用域中的行为
  • 再次证明其生命周期贯穿程序全过程
复制代码
复制代码
#include <stdio.h>

int main() {
    for (int i = 0; i < 3; i++) {
        int num = 3; // 普通变量
        printf("普通num: %d\n", num);
        num--;
        
        {
            static int staticNum = 1; // 静态变量,只初始化一次
            printf("静态num: %d\n", staticNum);
            staticNum++;
        }
    }
    
    return 0;
}

输出

复制代码
复制代码
普通num: 3
静态num: 1
普通num: 3
静态num: 2
普通num: 3
静态num: 3

实例44:调用外部函数

题目:学习如何调用外部函数。

程序分析

  • 演示全局变量与局部变量的作用域
  • 全局变量可在所有函数中访问
  • 局部变量同名时优先使用局部变量
复制代码
复制代码
#include <stdio.h>

int a, b, c; // 全局变量

void add() {
    int a = 3; // 局部变量a覆盖全局变量
    c = a + b; // 使用局部a和全局b
}

int main() {
    a = b = 4; // 给全局变量赋值
    add();
    printf("c = %d (使用局部a=3 + 全局b=4)\n", c); // c=7
    
    return 0;
}

实例45:register用法

题目:学习register定义变量的方法。

程序分析

  • register建议编译器将变量存储在寄存器中,提高访问速度
  • 现代编译器自动优化,显式使用register意义不大
  • 不能对register变量取地址
复制代码
复制代码
#include <stdio.h>

int main() {
    register int i; // 建议存放在寄存器
    int sum = 0;
    
    for (i = 1; i <= 100; i++) {
        sum += i;
    }
    
    printf("1+2+...+100 = %d\n", sum);
    // printf("%p", &i); // 错误:不能对register变量取地址
    
    return 0;
}

实例46:宏#define练习1

题目:宏#define命令练习。

程序分析

  • 宏定义:#define 宏名 替换文本
  • 预处理器直接替换,不进行类型检查
  • 注意括号避免运算优先级问题
复制代码
复制代码
#include <stdio.h>
#define SQUARE(x) ((x) * (x)) // 正确:加括号
// #define SQUARE(x) x * x // 错误:可能导致优先级问题

int main() {
    int a = 5;
    printf("SQUARE(%d) = %d\n", a, SQUARE(a));
    printf("SQUARE(%d+1) = %d\n", a, SQUARE(a + 1)); // 测试括号重要性
    
    return 0;
}

实例47:宏#define练习2

题目:使用宏实现交换两个数。

程序分析

  • 宏可以包含多条语句,使用do-while(0)结构是良好实践
  • 直接操作变量,无函数调用开销
复制代码
复制代码
#include <stdio.h>
// 使用do-while(0)确保宏的行为类似函数
#define SWAP(a, b) do { \
    int temp = (a); \
    (a) = (b); \
    (b) = temp; \
} while(0)

int main() {
    int x = 10, y = 20;
    
    printf("交换前:x=%d, y=%d\n", x, y);
    SWAP(x, y);
    printf("交换后:x=%d, y=%d\n", x, y);
    
    return 0;
}

实例48:宏#define练习3

题目:使用宏定义比较运算符。

程序分析

  • 宏可以替换运算符
  • 提高代码可读性或实现特定功能
复制代码
复制代码
#include <stdio.h>
#define GT >
#define LT <
#define EQ ==

int main() {
    int a = 10, b = 20;
    
    if (a GT b) printf("%d > %d\n", a, b);
    else if (a EQ b) printf("%d = %d\n", a, b);
    else if (a LT b) printf("%d < %d\n", a, b);
    
    return 0;
}

实例49:#if/#ifdef/#ifndef综合应用

题目:演示条件编译指令的使用。

程序分析

  • #if:根据常量表达式值决定是否编译
  • #ifdef:检查宏是否已定义
  • #ifndef:检查宏是否未定义
  • #undef:取消宏定义
复制代码
复制代码
#include <stdio.h>
#define DEBUG
#define VERSION 2

int main() {
    // 示例1:条件编译
    #if VERSION >= 2
        printf("版本2或以上\n");
    #else
        printf("版本1\n");
    #endif
    
    // 示例2:检查宏是否定义
    #ifdef DEBUG
        printf("调试模式开启\n");
    #endif
    
    // 示例3:检查宏是否未定义
    #ifndef RELEASE
        printf("Release模式未定义\n");
    #endif
    
    return 0;
}

实例50:#include练习

题目:演示#include的应用。

程序分析

  • #include <file.h>:系统头文件
  • #include "file.h":用户自定义头文件
  • 头文件通常包含宏定义、函数声明等
复制代码
复制代码
// test.h
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))

// main.c
#include "test.h" // 包含自定义头文件
#include <stdio.h>

int main() {
    double area = PI * 2 * 2;
    printf("圆面积:%f\n", area);
    
    int x = 10, y = 20;
    printf("最大值:%d\n", MAX(x, y));
    
    return 0;
}

实例51:按位与&使用

题目:学习按位与运算符。

程序分析

  • 按位与规则:1&1=1,其他为0
  • 用途:清零、取特定位、判断奇偶性
复制代码
复制代码
#include <stdio.h>

int main() {
    unsigned char a = 077; // 八进制63,二进制00111111
    unsigned char b = a & 3; // 00000011
    
    printf("a = %d (0x%02X)\n", a, a);
    printf("a & 3 = %d (0x%02X)\n", b, b);
    
    // 判断奇偶性
    int num = 10;
    if (num & 1) printf("%d是奇数\n", num);
    else printf("%d是偶数\n", num);
    
    return 0;
}

实例52:按位或|使用

题目:学习按位或运算符。

程序分析

  • 按位或规则:有1则1,全0为0
  • 用途:设置特定位为1
复制代码
复制代码
#include <stdio.h>

int main() {
    unsigned char a = 077; // 00111111
    unsigned char b = a | 3; // 00000011
    
    printf("a = %d (0x%02X)\n", a, a);
    printf("a | 3 = %d (0x%02X)\n", b, b);
    
    // 设置特定位为1
    unsigned char flags = 0;
    flags |= (1 << 0); // 设置第0位
    flags |= (1 << 2); // 设置第2位
    printf("设置位后:0x%02X\n", flags);
    
    return 0;
}

实例53:按位异或^使用

题目:学习按位异或运算符。

程序分析

  • 异或规则:相同为0,不同为1
  • 特性:自反性,(a b) b = a
  • 用途:交换两个数、加密
复制代码
复制代码
#include <stdio.h>

int main() {
    unsigned char a = 077; // 00111111
    unsigned char b = a  3; // 00000011
    
    printf("a = %d (0x%02X)\n", a, a);
    printf("a  3 = %d (0x%02X)\n", b, b);
    
    // 交换两个数(不使用临时变量)
    int x = 10, y = 20;
    printf("交换前:x=%d, y=%d\n", x, y);
    x = x  y;
    y = x  y;
    x = x ^ y;
    printf("交换后:x=%d, y=%d\n", x, y);
    
    return 0;
}

实例54:取整数右端4-7位

题目:取一个整数a从右端开始的4~7位。

程序分析

  • 右移4位使目标位对齐到最低位
  • 掩码0x0F(二进制00001111)提取低4位
  • 通用公式:(a >> start) & ((1 << length) - 1)
复制代码
复制代码
#include <stdio.h>

int main() {
    unsigned int a = 0xABCD1234; // 示例数
    unsigned int result;
    
    // 提取第4-7位(从0开始计数)
    result = (a >> 4) & 0x0F;
    
    printf("原数:0x%X\n", a);
    printf("第4-7位:0x%X\n", result);
    
    return 0;
}

实例55:按位取反~

题目:学习按位取反运算符。

程序分析

  • 按位取反:0变1,1变0
  • 在补码表示中,~x = -x - 1
复制代码
复制代码
#include <stdio.h>

int main() {
    signed char a = 5; // 00000101
    signed char b = ~a; // 11111010 = -6
    
    printf("a = %d\n", a);
    printf("~a = %d\n", b);
    printf("验证:~a = -a - 1 → %d\n", -a - 1);
    
    return 0;
}

实例56:circle画圆形

题目:使用graphics.h中的circle函数画圆。

程序分析

  • 此代码只能在Turbo C环境运行
  • initgraph初始化图形模式
  • circle(x, y, radius)画圆
复制代码
复制代码
#include <graphics.h> // 仅Turbo C支持

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    setbkcolor(YELLOW);
    setcolor(RED);
    
    // 画同心圆
    for (int r = 10; r <= 100; r += 10) {
        circle(320, 240, r);
    }
    
    getch(); // 等待按键
    closegraph();
    return 0;
}

注意 :现代编译器(如GCC, MSVC)不支持<graphics.h>,需使用SDL, OpenGL等替代。


实例57:line画直线

题目:使用line函数画直线。

程序分析

  • line(x1, y1, x2, y2)画线段
  • 此代码仅适用于Turbo C
复制代码
复制代码
#include <graphics.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    setbkcolor(GREEN);
    setcolor(RED);
    
    // 画多条线段
    for (int i = 0; i < 10; i++) {
        line(100 + i*20, 100, 200 + i*20, 200);
    }
    
    getch();
    closegraph();
    return 0;
}

实例58:rectangle画方形

题目:使用rectangle函数画矩形。

程序分析

  • rectangle(left, top, right, bottom)画矩形
  • 参数为左上角和右下角坐标
复制代码
复制代码
#include <graphics.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    setbkcolor(YELLOW);
    setcolor(BLUE);
    
    // 画同心矩形
    for (int i = 0; i < 5; i++) {
        rectangle(100 - i*10, 100 - i*10, 300 + i*10, 200 + i*10);
    }
    
    getch();
    closegraph();
    return 0;
}

实例59:综合画图1

题目:综合使用图形函数画图(TC环境)。

程序分析

  • 结合circle, line, setcolor等函数
  • 演示复杂图形绘制
复制代码
复制代码
#include <graphics.h>
#include <math.h>

#define PI 3.14159

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    setbkcolor(BLACK);
    setcolor(WHITE);
    
    // 画圆形和辐射线
    circle(320, 240, 100);
    for (int i = 0; i < 12; i++) {
        float angle = i * PI / 6;
        line(320, 240, 320 + 150 * cos(angle), 240 + 150 * sin(angle));
    }
    
    getch();
    closegraph();
    return 0;
}

实例60:综合画图2

题目:动态画图演示(TC环境)。

程序分析

  • 使用循环和延时实现动画效果
  • 检测键盘输入退出
复制代码
复制代码
#include <graphics.h>
#include <conio.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    int x = 320, y = 240, r = 20;
    int dx = 2, dy = 3;
    
    while (!kbhit()) { // 直到按键退出
        cleardevice();
        circle(x, y, r);
        delay(50); // 延时50ms
        
        x += dx;
        y += dy;
        
        // 边界检测
        if (x - r <= 0 || x + r >= 640) dx = -dx;
        if (y - r <= 0 || y + r >= 480) dy = -dy;
    }
    
    closegraph();
    return 0;
}

实例61:杨辉三角形

题目:打印10行杨辉三角形。

程序分析

  • 每个数等于上方两数之和:tri[i][j] = tri[i-1][j-1] + tri[i-1][j]
  • 边界条件:每行首尾为1
复制代码
复制代码
#include <stdio.h>
#define MAX_ROWS 10

int main() {
    int triangle[MAX_ROWS][MAX_ROWS];
    
    // 生成杨辉三角
    for (int i = 0; i < MAX_ROWS; i++) {
        for (int j = 0; j <= i; j++) {
            if (j  0 || j  i) {
                triangle[i][j] = 1;
            } else {
                triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j];
            }
        }
    }
    
    // 打印
    for (int i = 0; i < MAX_ROWS; i++) {
        // 打印空格
        for (int k = 0; k < MAX_ROWS - i - 1; k++) {
            printf("   ");
        }
        // 打印数字
        for (int j = 0; j <= i; j++) {
            printf("%6d", triangle[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

实例62:putpixel画点

题目:使用putpixel函数绘制点阵(TC环境)。

程序分析

  • putpixel(x, y, color)在指定位置画点
  • 可绘制图案、曲线等
复制代码
复制代码
#include <graphics.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    setcolor(RED);
    // 画点阵
    for (int x = 100; x < 200; x += 5) {
        for (int y = 100; y < 200; y += 5) {
            putpixel(x, y, RED);
        }
    }
    
    getch();
    closegraph();
    return 0;
}

实例63:画椭圆ellipse

题目:使用ellipse函数画椭圆。

程序分析

  • ellipse(x, y, start_angle, end_angle, x_radius, y_radius)
  • 可画完整椭圆或弧
复制代码
复制代码
#include <graphics.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    // 画椭圆
    ellipse(320, 240, 0, 360, 100, 50);
    
    // 画椭圆弧
    ellipse(320, 240, 0, 180, 150, 100);
    
    getch();
    closegraph();
    return 0;
}

实例64:ellipse和rectangle组合

题目:组合使用ellipse和rectangle画图。

程序分析

  • 结合多种图形函数创建复杂图案
复制代码
复制代码
#include <graphics.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    // 画组合图形
    rectangle(200, 150, 440, 330);
    ellipse(320, 240, 0, 360, 120, 90);
    ellipse(320, 240, 0, 360, 80, 60);
    
    getch();
    closegraph();
    return 0;
}

实例65:画优美图案

题目:绘制复杂几何图案(TC环境)。

程序分析

  • 使用数学函数计算坐标
  • 绘制多边形和连线
复制代码
复制代码
#include <graphics.h>
#include <math.h>

int main() {
    int driver = VGA, mode = VGAHI;
    initgraph(&driver, &mode, "");
    
    int centerX = 320, centerY = 240;
    int radius = 100;
    int points = 12;
    
    // 画圆
    circle(centerX, centerY, radius);
    
    // 画多边形
    for (int i = 0; i < points; i++) {
        float angle1 = 2 * M_PI * i / points;
        float angle2 = 2 * M_PI * (i + 1) / points;
        int x1 = centerX + radius * cos(angle1);
        int y1 = centerY + radius * sin(angle1);
        int x2 = centerX + radius * cos(angle2);
        int y2 = centerY + radius * sin(angle2);
        line(x1, y1, x2, y2);
    }
    
    getch();
    closegraph();
    return 0;
}

实例66:指针排序三个数

题目:输入3个数,用指针方法按大小顺序输出。

程序分析

  • 使用指针传递地址,实现交换
  • 函数参数为指针类型int*
复制代码
复制代码
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int a, b, c;
    int *p1 = &a, *p2 = &b, *p3 = &c;
    
    printf("输入三个整数:");
    scanf("%d %d %d", p1, p2, p3);
    
    if (a > b) swap(p1, p2);
    if (a > c) swap(p1, p3);
    if (b > c) swap(p2, p3);
    
    printf("排序后:%d %d %d\n", a, b, c);
    return 0;
}

实例67:数组交换位置

题目:输入数组,将最大值与第一个元素交换,最小值与最后一个元素交换。

程序分析

  • 先找出最大值和最小值的索引
  • 注意交换后索引可能变化(如果最大值在最后或最小值在第一个)
复制代码
复制代码
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int arr[100];
    int n;
    
    printf("输入数组长度:");
    scanf("%d", &n);
    
    printf("输入数组元素:");
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    int maxIdx = 0, minIdx = 0;
    for (int i = 1; i < n; i++) {
        if (arr[i] > arr[maxIdx]) maxIdx = i;
        if (arr[i] < arr[minIdx]) minIdx = i;
    }
    
    // 交换最大值和第一个元素
    swap(&arr[0], &arr[maxIdx]);
    
    // 如果最小值在第一个位置,更新其索引
    if (minIdx == 0) minIdx = maxIdx;
    
    // 交换最小值和最后一个元素
    swap(&arr[n-1], &arr[minIdx]);
    
    printf("交换后:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}

实例68:数组元素后移

题目:将数组后m个元素移到前面。

程序分析

  • 使用临时数组保存后m个元素
  • 整体右移前n-m个元素
  • 将临时数组元素放回原数组前面
复制代码
复制代码
#include <stdio.h>

void rotateRight(int arr[], int n, int m) {
    m %= n; // 处理m>n的情况
    int temp[m];
    
    // 保存后m个元素
    for (int i = 0; i < m; i++) {
        temp[i] = arr[n - m + i];
    }
    
    // 右移前n-m个元素
    for (int i = n - m - 1; i >= 0; i--) {
        arr[i + m] = arr[i];
    }
    
    // 恢复前m个元素
    for (int i = 0; i < m; i++) {
        arr[i] = temp[i];
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7};
    int n = sizeof(arr) / sizeof(arr[0]);
    int m = 3;
    
    printf("原数组:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    
    rotateRight(arr, n, m);
    
    printf("\n后移%d位:", m);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}

实例69:约瑟夫环问题

题目:n个人围成一圈,从1报数到3,报到3者退出,求最后留下的人的原始编号。

程序分析

  • 经典约瑟夫问题
  • 递推公式:f(n, k) = (f(n-1, k) + k) % n
  • 本例k=3
复制代码
复制代码
#include <stdio.h>

int josephus(int n, int k) {
    if (n == 1) return 0; // 最后剩下的人在新序列中的位置
    
    // 递归:找到n-1个人的幸存者,然后调整位置
    return (josephus(n - 1, k) + k) % n;
}

int main() {
    int n = 10, k = 3;
    
    int survivor = josephus(n, k) + 1; // 转换为1-based编号
    
    printf("n=%d, k=%d时,最后留下的是第%d个人\n", n, k, survivor);
    
    return 0;
}

实例70:求字符串长度

题目:自定义函数求字符串长度。

程序分析

  • 遍历字符串直到遇到\0
  • 或使用指针运算:ptr - str
复制代码
复制代码
#include <stdio.h>

int myStrlen(const char *str) {
    int len = 0;
    while (*str != '\0') {
        len++;
        str++;
    }
    return len;
}

// 指针版本
int myStrlenPtr(const char *str) {
    const char *start = str;
    while (*str) str++;
    return str - start;
}

int main() {
    char str[] = "Hello, World!";
    
    printf("字符串:%s\n", str);
    printf("长度(数组版):%d\n", myStrlen(str));
    printf("长度(指针版):%d\n", myStrlenPtr(str));
    
    return 0;
}

实例71:结构体学生数据

题目:使用结构体输入输出5个学生的数据记录。

程序分析

  • 定义struct Student结构体
  • 包含学号、姓名、成绩等字段
  • 使用数组存储多个学生
复制代码
复制代码
#include <stdio.h>

struct Student {
    int id;
    char name[50];
    float score;
};

int main() {
    struct Student students[5];
    
    // 输入数据
    for (int i = 0; i < 5; i++) {
        printf("输入第%d个学生信息(学号 姓名 成绩):", i + 1);
        scanf("%d %s %f", &students[i].id, students[i].name, &students[i].score);
    }
    
    // 输出数据
    printf("\n学生信息表:\n");
    printf("学号\t姓名\t成绩\n");
    printf("-------------------------\n");
    for (int i = 0; i < 5; i++) {
        printf("%d\t%s\t%.2f\n", students[i].id, students[i].name, students[i].score);
    }
    
    return 0;
}

实例72:创建链表

题目:创建一个单链表。

程序分析

  • 定义节点结构体
  • 包含数据和next指针
  • 实现创建、插入、打印功能
复制代码
复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

// 创建新节点
Node* createNode(int data) {
    Node *newNode = (Node*)malloc(sizeof(Node));
    if (!newNode) {
        printf("内存分配失败\n");
        exit(1);
    }
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 在链表末尾插入
void append(Node **head, int data) {
    Node *newNode = createNode(data);
    
    if (*head == NULL) {
        *head = newNode;
        return;
    }
    
    Node *temp = *head;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    temp->next = newNode;
}

// 打印链表
void printList(Node *head) {
    while (head != NULL) {
        printf("%d → ", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

// 释放链表
void freeList(Node *head) {
    Node *temp;
    while (head != NULL) {
        temp = head;
        head = head->next;
        free(temp);
    }
}

int main() {
    Node *head = NULL;
    
    // 创建链表:1→2→3→4→NULL
    append(&head, 1);
    append(&head, 2);
    append(&head, 3);
    append(&head, 4);
    
    printList(head);
    freeList(head);
    
    return 0;
}

实例73:反向输出链表

题目:反向输出链表。

程序分析

  • 方法一:递归(隐式栈)
  • 方法二:显式栈(数组)
  • 方法三:先反转链表再输出(修改原链表)
复制代码
复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

// 递归反向打印
void reversePrintRecursive(Node *head) {
    if (head == NULL) return;
    reversePrintRecursive(head->next);
    printf("%d ", head->data);
}

// 使用栈反向打印
void reversePrintStack(Node *head) {
    int stack[100];
    int top = -1;
    
    while (head != NULL) {
        stack[++top] = head->data;
        head = head->next;
    }
    
    while (top >= 0) {
        printf("%d ", stack[top--]);
    }
}

int main() {
    // 创建链表:1→2→3→4→NULL
    Node *head = malloc(sizeof(Node));
    head->data = 1;
    head->next = malloc(sizeof(Node));
    head->next->data = 2;
    head->next->next = malloc(sizeof(Node));
    head->next->next->data = 3;
    head->next->next->next = NULL;
    
    printf("原链表:1 2 3 4\n");
    printf("反向(递归):");
    reversePrintRecursive(head);
    printf("\n");
    
    printf("反向(栈):");
    reversePrintStack(head);
    printf("\n");
    
    return 0;
}

实例74:连接两个链表

题目:将两个链表连接。

程序分析

  • 找到第一个链表的尾节点
  • 将尾节点的next指向第二个链表的头节点
  • 返回连接后的链表
复制代码
复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

// 连接链表
Node* concatenate(Node *head1, Node *head2) {
    if (head1  NULL) return head2;
    if (head2  NULL) return head1;
    
    Node *temp = head1;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    temp->next = head2;
    
    return head1;
}

// 打印链表
void printList(Node *head) {
    while (head != NULL) {
        printf("%d → ", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

int main() {
    // 创建链表1:1→2→NULL
    Node *head1 = malloc(sizeof(Node));
    head1->data = 1;
    head1->next = malloc(sizeof(Node));
    head1->next->data = 2;
    head1->next->next = NULL;
    
    // 创建链表2:3→4→NULL
    Node *head2 = malloc(sizeof(Node));
    head2->data = 3;
    head2->next = malloc(sizeof(Node));
    head2->next->data = 4;
    head2->next->next = NULL;
    
    printf("链表1:");
    printList(head1);
    printf("链表2:");
    printList(head2);
    
    Node *result = concatenate(head1, head2);
    printf("连接后:");
    printList(result);
    
    return 0;
}

实例75:整数反转输出

题目:输入一个整数,将其反转后输出。

程序分析

  • 处理正负号
  • 通过%10/10提取和移除最后一位
  • 注意溢出处理(本例假设输入在int范围内)
复制代码
复制代码
#include <stdio.h>
#include <limits.h>

int main() {
    long long num, reversed = 0;
    int sign = 1;
    
    printf("请输入一个整数:");
    scanf("%lld", &num);
    
    // 处理符号
    if (num < 0) {
        sign = -1;
        num = -num;
    }
    
    // 反转数字
    while (num != 0) {
        int digit = num % 10;
        reversed = reversed * 10 + digit;
        num /= 10;
    }
    
    reversed *= sign;
    
    // 检查溢出
    if (reversed > INT_MAX || reversed < INT_MIN) {
        printf("反转后超出整数范围\n");
    } else {
        printf("反转后:%lld\n", reversed);
    }
    
    return 0;
}

实例76:分数序列求和

题目:根据n的奇偶性,计算不同序列的和。

程序分析

  • n为偶数:1/2 + 1/4 + ... + 1/n
  • n为奇数:1/1 + 1/3 + ... + 1/n
  • 使用函数指针优化代码结构
复制代码
复制代码
#include <stdio.h>

// 计算偶数序列和
double sumEven(int n) {
    double sum = 0.0;
    for (int i = 2; i <= n; i += 2) {
        sum += 1.0 / i;
    }
    return sum;
}

// 计算奇数序列和
double sumOdd(int n) {
    double sum = 0.0;
    for (int i = 1; i <= n; i += 2) {
        sum += 1.0 / i;
    }
    return sum;
}

int main() {
    int n;
    printf("请输入整数n:");
    scanf("%d", &n);
    
    double result = (n % 2 == 0) ? sumEven(n) : sumOdd(n);
    printf("结果:%lf\n", result);
    
    return 0;
}

实例77:指针的指针练习

题目:练习指向指针的指针。

程序分析

  • 指针的指针用于存储指针变量的地址
  • 常用于函数参数修改指针本身
复制代码
复制代码
#include <stdio.h>

int main() {
    const char *words[] = {"man", "woman", "girl", "boy", "sister"};
    const char **ptr; // 指向指针的指针
    
    for (int i = 0; i < 5; i++) {
        ptr = &words[i];
        printf("%s\n", *ptr);
    }
    
    return 0;
}

应用场景

复制代码
复制代码
void allocateMemory(int **ptr) {
    *ptr = malloc(sizeof(int) * 10); // 修改指针
}

int main() {
    int *arr;
    allocateMemory(&arr); // 传递指针的地址
    // 使用arr...
    free(arr);
    return 0;
}

实例78:结构体找年龄最大

题目:找出结构体数组中年龄最大的人。

程序分析

  • 定义结构体数组并初始化
  • 遍历比较age字段
  • 使用指针操作提高效率
复制代码
复制代码
#include <stdio.h>

struct Person {
    char name[20];
    int age;
};

int main() {
    struct Person people[] = {
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 28}
    };
    int n = sizeof(people) / sizeof(people[0]);
    
    struct Person *oldest = &people[0];
    for (int i = 1; i < n; i++) {
        if (people[i].age > oldest->age) {
            oldest = &people[i];
        }
    }
    
    printf("年龄最大:%s, %d岁\n", oldest->name, oldest->age);
    
    return 0;
}

实例79:字符串排序

题目:对字符串数组进行排序。

程序分析

  • 使用strcmp比较字符串
  • 使用strcpy交换字符串
  • 实现冒泡排序或选择排序
复制代码
复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char strings[5][50] = {"banana", "apple", "orange", "grape", "cherry"};
    int n = 5;
    
    // 冒泡排序
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (strcmp(strings[j], strings[j + 1]) > 0) {
                char temp[50];
                strcpy(temp, strings[j]);
                strcpy(strings[j], strings[j + 1]);
                strcpy(strings[j + 1], temp);
            }
        }
    }
    
    printf("排序后:\n");
    for (int i = 0; i < n; i++) {
        printf("%s\n", strings[i]);
    }
    
    return 0;
}

实例80:猴子分桃问题

题目:五只猴子分桃,每只都将桃子分成五份多一个,扔掉多的一个后拿走一份,求最初最少有多少桃子。

程序分析

  • 正向思考复杂,使用逆向思维
  • 从最后一只猴子倒推
  • 设第i只猴子操作后有x个桃,则操作前有(x * 5 + 1)
复制代码
复制代码
#include <stdio.h>

int main() {
    int peaches = 1; // 第五只猴子操作后
    
    for (int i = 5; i >= 1; i--) {
        peaches = peaches * 5 + 1;
    }
    
    printf("最初最少有%d个桃子\n", peaches);
    
    return 0;
}

答案:3121个(此为简化版本,原题需满足每次恰好多1个)


实例81:求特殊两位数

题目 :求满足809*?? = 800*?? + 9*??的两位数??

程序分析

  • 简化:809x = 800x + 9x → 恒成立
  • 实际应理解为:809×??是四位数,8×??是两位数,9×??是三位数
  • 即:1000 ≤ 809x ≤ 9999, 10 ≤ 8x ≤ 99, 100 ≤ 9x ≤ 999
复制代码
复制代码
#include <stdio.h>

int main() {
    for (int x = 10; x <= 99; x++) {
        int p1 = 809 * x;
        int p2 = 8 * x;
        int p3 = 9 * x;
        
        if (p1 >= 1000 && p1 <= 9999 &&
            p2 >= 10 && p2 <= 99 &&
            p3 >= 100 && p3 <= 999) {
            printf("找到的数:%d\n", x);
            printf("809×%d = %d\n", x, p1);
        }
    }
    
    return 0;
}

答案:12(809×12=9708,8×12=96,9×12=108)


实例82:八进制转十进制

题目:将八进制数转换为十进制。

程序分析

  • 从右到左,每位乘以8的幂次
  • 或使用scanf("%o", &num)直接读取八进制
复制代码
复制代码
#include <stdio.h>

int main() {
    int octal, decimal = 0, base = 1;
    
    printf("请输入八进制数:");
    scanf("%o", &octal); // %o读取八进制
    
    // 手动转换
    int temp = octal;
    while (temp != 0) {
        int digit = temp % 10;
        decimal += digit * base;
        temp /= 10;
        base *= 8;
    }
    
    printf("八进制%o = 十进制%d\n", octal, decimal);
    
    return 0;
}

示例 :输入17(八进制),输出15(十进制)


实例83:组成奇数个数

题目:求0-7能组成多少奇数。

程序分析

  • 奇数条件:末位为奇数(1,3,5,7)
  • 分情况讨论1-8位数
  • 注意首位不能为0
复制代码
复制代码
#include <stdio.h>

int main() {
    int count = 0;
    
    // 1位数:4个奇数
    count += 4;
    
    // 2位数:末位4种,首位7种(不能为0)
    count += 4 * 7;
    
    // 3位数:末位4种,首位7种,中间8种
    count += 4 * 7 * 8;
    
    // 4位数:末位4种,首位7种,中间两位各8种
    count += 4 * 7 * 8 * 8;
    
    // 5位数
    count += 4 * 7 * 8 * 8 * 8;
    
    // 6位数
    count += 4 * 7 * 8 * 8 * 8 * 8;
    
    // 7位数
    count += 4 * 7 * 8 * 8 * 8 * 8 * 8;
    
    // 8位数
    count += 4 * 7 * 8 * 8 * 8 * 8 * 8 * 8;
    
    printf("0-7能组成的奇数个数:%d\n", count);
    
    return 0;
}

实例84:哥德巴赫猜想验证

题目:验证一个偶数可以表示为两个素数之和。

程序分析

  • 输入偶数n
  • 遍历i从2到n/2,检查i和n-i是否均为素数
复制代码
复制代码
#include <stdio.h>
#include <stdbool.h>

bool isPrime(int num) {
    if (num < 2) return false;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) return false;
    }
    return true;
}

int main() {
    int n;
    printf("请输入一个偶数:");
    scanf("%d", &n);
    
    if (n % 2 != 0 || n < 4) {
        printf("请输入≥4的偶数\n");
        return 1;
    }
    
    printf("%d = ", n);
    for (int i = 2; i <= n / 2; i++) {
        if (isPrime(i) && isPrime(n - i)) {
            printf("%d + %d\n", i, n - i);
            break; // 找到一个即可
        }
    }
    
    return 0;
}

实例85:素数被9整除次数

题目:判断一个素数能被9整除多少次。

程序分析

  • 素数定义:只能被1和自身整除
  • 因此大于3的素数不可能被9整除
  • 只有3能被9整除0次(因为9>3)
复制代码
复制代码
#include <stdio.h>
#include <stdbool.h>

bool isPrime(int num) {
    if (num < 2) return false;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) return false;
    }
    return true;
}

int main() {
    int prime;
    printf("请输入一个素数:");
    scanf("%d", &prime);
    
    if (!isPrime(prime)) {
        printf("不是素数\n");
        return 1;
    }
    
    int count = 0;
    int temp = prime;
    while (temp % 9 == 0) {
        count++;
        temp /= 9;
    }
    
    printf("%d能被9整除%d次\n", prime, count);
    printf("商为:%d\n", temp);
    
    return 0;
}

结论:只有3能被9整除0次(因为9>3)


实例86:字符串连接程序

题目:连接两个字符串。

程序分析

  • 使用strcat或手动实现
  • 注意目标数组要有足够空间
复制代码
复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* myStrcat(const char *s1, const char *s2) {
    char *result = malloc(strlen(s1) + strlen(s2) + 1);
    if (!result) return NULL;
    
    strcpy(result, s1);
    strcat(result, s2);
    
    return result;
}

int main() {
    char str1[50], str2[50];
    
    printf("输入两个字符串:");
    scanf("%s %s", str1, str2);
    
    char *result = myStrcat(str1, str2);
    if (result) {
        printf("连接结果:%s\n", result);
        free(result);
    }
    
    return 0;
}

实例87:结构体变量传递

题目:结构体变量作为函数参数传递。

程序分析

  • 结构体默认按值传递(拷贝)
  • 修改函数内的结构体不影响原结构体
  • 如需修改,应传递指针
复制代码
复制代码
#include <stdio.h>

struct Student {
    int id;
    char grade;
};

// 按值传递(不能修改原结构体)
void modifyByValue(struct Student s) {
    s.id = 100;
    s.grade = 'A';
}

// 按指针传递(可以修改原结构体)
void modifyByPointer(struct Student *s) {
    s->id = 100;
    s->grade = 'A';
}

int main() {
    struct Student stu = {1, 'C'};
    
    printf("原结构体:id=%d, grade=%c\n", stu.id, stu.grade);
    
    modifyByValue(stu);
    printf("值传递后:id=%d, grade=%c\n", stu.id, stu.grade); // 未改变
    
    modifyByPointer(&stu);
    printf("指针传递后:id=%d, grade=%c\n", stu.id, stu.grade); // 已改变
    
    return 0;
}

实例88:打印星号图案

题目 :读取7个数(1-50),每读取一个打印对应数量的*

程序分析

  • 循环读取7个数
  • 每读一个立即打印*
  • 输入验证确保在1-50范围内
复制代码
复制代码
#include <stdio.h>

int main() {
    int num;
    
    printf("请输入7个数字(1-50):\n");
    for (int i = 0; i < 7; i++) {
        scanf("%d", &num);
        
        // 输入验证
        if (num < 1 || num > 50) {
            printf("输入无效,请输入1-50之间的数\n");
            i--; // 重新输入
            continue;
        }
        
        // 打印星号
        for (int j = 0; j < num; j++) {
            printf("*");
        }
        printf("\n");
    }
    
    return 0;
}

实例89:加密四位数

题目:加密规则:每位加5,取模10,然后交换第一位与第四位,第二位与第三位。

程序分析

  • 分解四位数字
  • 加密每位:(digit + 5) % 10
  • 交换位置
复制代码
复制代码
#include <stdio.h>

int main() {
    int num, digits[4];
    
    printf("请输入一个四位数:");
    scanf("%d", &num);
    
    // 分解数字
    digits[0] = num / 1000;      // 千位
    digits[1] = (num / 100) % 10; // 百位
    digits[2] = (num / 10) % 10;  // 十位
    digits[3] = num % 10;         // 个位
    
    // 加密每位
    for (int i = 0; i < 4; i++) {
        digits[i] = (digits[i] + 5) % 10;
    }
    
    // 交换位置
    int temp = digits[0];
    digits[0] = digits[3];
    digits[3] = temp;
    
    temp = digits[1];
    digits[1] = digits[2];
    digits[2] = temp;
    
    // 输出加密结果
    printf("加密后:");
    for (int i = 0; i < 4; i++) {
        printf("%d", digits[i]);
    }
    printf("\n");
    
    return 0;
}

实例90:数组反转输出

题目:使用指针反转数组并输出。

程序分析

  • 使用指针运算访问数组元素
  • 首尾指针交换
复制代码
复制代码
#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    int *start = arr;
    int *end = arr + n - 1;
    
    printf("原数组:");
    for (int i = 0; i < n; i++) {
        printf("%d ", *(arr + i));
    }
    
    // 反转
    while (start < end) {
        int temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
    
    printf("\n反转后:");
    for (int i = 0; i < n; i++) {
        printf("%d ", *(arr + i));
    }
    printf("\n");
    
    return 0;
}

实例91:时间函数库1

题目:获取并显示当前本地时间。

程序分析

  • time()获取当前时间(秒数)
  • localtime()转换为本地时间结构体
  • asctime()格式化为字符串
复制代码
复制代码
#include <stdio.h>
#include <time.h>

int main() {
    time_t rawtime;
    struct tm *timeinfo;
    
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    
    printf("当前本地时间:%s", asctime(timeinfo));
    printf("年月日:%04d-%02d-%02d\n", 
           timeinfo->tm_year + 1900,
           timeinfo->tm_mon + 1,
           timeinfo->tm_mday);
    
    return 0;
}

实例92:时间函数库2

题目:测量程序执行时间。

程序分析

  • clock()获取CPU时钟周期
  • CLOCKS_PER_SEC转换为秒
  • 可测量代码执行时间
复制代码
复制代码
#include <stdio.h>
#include <time.h>

int main() {
    clock_t start, end;
    double cpu_time;
    
    start = clock();
    
    // 待测代码
    long sum = 0;
    for (int i = 0; i < 100000000; i++) {
        sum += i;
    }
    
    end = clock();
    cpu_time = ((double)(end - start)) / CLOCKS_PER_SEC;
    
    printf("执行时间:%.3f秒\n", cpu_time);
    
    return 0;
}

实例93:时间函数库3

题目:测量空循环时间。

程序分析

  • 演示clock()的基本用法
  • 注意空循环可能被编译器优化
复制代码
复制代码
#include <stdio.h>
#include <time.h>

int main() {
    long i = 10000000L;
    clock_t start, end;
    
    start = clock();
    while (i--);
    end = clock();
    
    double time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("空循环耗时:%f秒\n", time_used);
    
    return 0;
}

实例94:猜数字游戏

题目:猜数字游戏,根据猜测次数给出评价。

程序分析

  • 生成随机数:rand() % 100 + 1
  • 循环猜测,给出提示
  • 根据次数分级评价
复制代码
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void guessGame() {
    srand(time(NULL));
    int target = rand() % 100 + 1;
    int guess, count = 0;
    
    printf("我想了一个1-100的数字,猜猜看!\n");
    
    do {
        printf("你的猜测:");
        scanf("%d", &guess);
        count++;
        
        if (guess > target) {
            printf("太大了!\n");
        } else if (guess < target) {
            printf("太小了!\n");
        } else {
            printf("恭喜猜中了!用了%d次\n", count);
            
            if (count <= 5) {
                printf("表现优秀!\n");
            } else if (count <= 10) {
                printf("表现不错!\n");
            } else {
                printf("再试一次吧!\n");
            }
        }
    } while (guess != target);
}

int main() {
    guessGame();
    return 0;
}

实例95:结构体实例

题目:简单的结构体应用实例。

程序分析

  • 结构体可包含不同类型成员
  • 使用.运算符访问成员
复制代码
复制代码
#include <stdio.h>

struct Data {
    int id;
    float value;
    char name[20];
};

int main() {
    struct Data item = {1, 3.14, "Test"};
    
    printf("ID: %d\n", item.id);
    printf("Value: %.2f\n", item.value);
    printf("Name: %s\n", item.name);
    
    // 修改成员
    item.value = 2.718;
    printf("修改后Value: %.3f\n", item.value);
    
    return 0;
}

实例96:统计子串出现次数

题目:统计一个字符串中子串出现的次数。

程序分析

  • 使用strstr查找子串
  • 每次找到后,指针移到找到位置+1,继续查找
复制代码
复制代码
#include <stdio.h>
#include <string.h>

int countSubstring(const char *str, const char *substr) {
    int count = 0;
    const char *ptr = str;
    
    while ((ptr = strstr(ptr, substr)) != NULL) {
        count++;
        ptr++; // 移动到下一个位置继续查找
    }
    
    return count;
}

int main() {
    char str[] = "ababababab";
    char substr[] = "ab";
    
    int count = countSubstring(str, substr);
    printf("子串\"%s\"在\"%s\"中出现%d次\n", substr, str, count);
    
    return 0;
}

实例97:保存到txt文件

题目:从键盘输入字符,保存到文件直到输入'#'。

程序分析

  • fopen打开文件
  • fputc写入字符
  • fclose关闭文件
复制代码
复制代码
#include <stdio.h>

int main() {
    FILE *fp;
    char ch;
    
    fp = fopen("output.txt", "w");
    if (fp == NULL) {
        perror("文件打开失败");
        return 1;
    }
    
    printf("请输入字符(#结束):\n");
    while ((ch = getchar()) != '#') {
        fputc(ch, fp);
    }
    
    fclose(fp);
    printf("内容已保存到output.txt\n");
    
    return 0;
}

实例98:字母大小写转换

题目:输入字符串,将小写字母转大写,大写转小写,保存到文件。

程序分析

  • 使用islower()isupper()判断
  • 使用toupper()tolower()转换
  • 使用fputs写入文件
复制代码
复制代码
#include <stdio.h>
#include <ctype.h>

int main() {
    FILE *fp;
    char str[100];
    
    printf("请输入字符串:");
    fgets(str, sizeof(str), stdin);
    
    // 转换大小写
    for (int i = 0; str[i] != '\0'; i++) {
        if (islower(str[i])) {
            str[i] = toupper(str[i]);
        } else if (isupper(str[i])) {
            str[i] = tolower(str[i]);
        }
    }
    
    // 保存到文件
    fp = fopen("converted.txt", "w");
    if (fp) {
        fputs(str, fp);
        fclose(fp);
        printf("转换后:%s", str);
        printf("已保存到converted.txt\n");
    }
    
    return 0;
}

实例99:合并两个文件

题目:合并两个txt文件并按字母排序。

程序分析

  • 分别读取两个文件内容
  • 合并字符串
  • 使用冒泡排序对字符排序
  • 写入新文件
复制代码
复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    FILE *fa, *fb, *fc;
    char content1[100] = {0}, content2[100] = {0}, merged[200];
    
    // 读取文件A
    fa = fopen("A.txt", "r");
    if (fa) {
        fgets(content1, sizeof(content1), fa);
        fclose(fa);
    }
    
    // 读取文件B
    fb = fopen("B.txt", "r");
    if (fb) {
        fgets(content2, sizeof(content2), fb);
        fclose(fb);
    }
    
    // 合并
    strcpy(merged, content1);
    strcat(merged, content2);
    
    // 排序
    int len = strlen(merged);
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            if (merged[j] > merged[j + 1]) {
                char temp = merged[j];
                merged[j] = merged[j + 1];
                merged[j + 1] = temp;
            }
        }
    }
    
    // 写入文件C
    fc = fopen("C.txt", "w");
    if (fc) {
        fputs(merged, fc);
        fclose(fc);
        printf("合并排序后已保存到C.txt: %s\n", merged);
    }
    
    return 0;
}

实例100:学生数据管理

题目:管理5个学生的信息(学号、姓名、3门成绩),计算平均分并保存到文件。

程序分析

  • 使用结构体存储学生信息
  • 计算平均成绩
  • 使用fprintf格式化写入文件
复制代码
复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int id;
    char name[20];
    int math, english, c;
    float average;
} Student;

int main() {
    Student students[5];
    
    // 输入数据
    for (int i = 0; i < 5; i++) {
        printf("输入第%d个学生信息(学号 姓名 数学 英语 C语言):\n", i + 1);
        scanf("%d %s %d %d %d", &students[i].id, students[i].name,
              &students[i].math, &students[i].english, &students[i].c);
        
        students[i].average = (students[i].math + students[i].english + students[i].c) / 3.0;
    }
    
    // 写入文件
    FILE *fp = fopen("students.txt", "w");
    if (!fp) {
        perror("文件打开失败");
        return 1;
    }
    
    fprintf(fp, "学号\t姓名\t数学\t英语\tC语言\t平均分\n");
    fprintf(fp, "---------------------------------------------------\n");
    
    for (int i = 0; i < 5; i++) {
        fprintf(fp, "%d\t%s\t%d\t%d\t%d\t%.2f\n",
                students[i].id, students[i].name,
                students[i].math, students[i].english, students[i].c,
                students[i].average);
    }
    
    fclose(fp);
    printf("学生信息已保存到students.txt\n");
    
    return 0;
}

附录

C语言学习路径建议

  1. 基础阶段(实例1-20)

    • 掌握变量、运算符、控制结构
    • 理解数组和字符串基本操作
    • 熟悉循环和条件判断
  2. 进阶阶段(实例21-40)

    • 掌握函数定义与调用
    • 理解指针概念和操作
    • 学习结构体使用
  3. 高级阶段(实例41-60)

    • 理解存储类别和作用域
    • 掌握预处理指令
    • 学习位运算
  4. 综合应用(实例61-100)

    • 文件操作
    • 动态内存管理
    • 链表等数据结构
    • 简单算法实现

常见问题解答

Q: 图形程序无法运行? A: 实例56-65使用<graphics.h>,仅Turbo C支持。现代编译器需使用SDL、OpenGL或Windows API。

Q: 为什么有些代码有安全警告? A: 部分代码使用scanf等不安全的函数,实际开发中应使用scanf_s或限制输入长度。

Q: 如何优化这些练习? A: 可添加输入验证、错误处理、注释说明,并考虑使用更高效的算法。


总结

本系列100个C语言练习实例涵盖了从基础语法到高级应用的各个方面,是C语言学习的宝贵资源。建议读者:

  1. 按顺序逐一实践,理解每个实例的核心思想
  2. 尝试修改代码,观察结果变化
  3. 对相似实例进行对比分析
  4. 在理解基础上,尝试用不同方法实现同一功能
  5. 将多个实例组合,实现更复杂的功能

通过系统练习这些实例,读者可以逐步掌握C语言的核心概念和编程技巧,为后续深入学习打下坚实基础。

相关推荐
Tisfy1 小时前
LeetCode 2943.最大化网格图中正方形空洞的面积:小小思维
算法·leetcode·题解·数组·思维·排序·连续
久绊A1 小时前
RAID10 单盘失效降级处理实操
linux·运维·服务器
LDG_AGI2 小时前
【机器学习】深度学习推荐系统(二十六):X 推荐算法多模型融合机制详解
人工智能·分布式·深度学习·算法·机器学习·推荐算法
小尧嵌入式2 小时前
【基础学习七十】ffmpeg命令
c++·stm32·嵌入式硬件·ffmpeg
高山上有一只小老虎2 小时前
小红的矩阵染色
java·算法·矩阵
WuChao_JMUer2 小时前
YOLO26 on RDK S100P 端侧部署技术报告
人工智能·算法·yolo·rdk
Ro Jace2 小时前
传统雷达信号分选方法之SDIF:Improved algorithm for the deinterleaving of radar pulses
网络·人工智能·算法
松涛和鸣2 小时前
54、DS18B20单线数字温度采集
linux·服务器·c语言·开发语言·数据库
小杨同学492 小时前
【嵌入式 C 语言实战】手动实现字符串四大核心函数(strcpy/strcat/strlen/strcmp)
后端·深度学习·算法