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;
}

答案 :-75和21都满足条件


实例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:练习函数调用

题目:练习函数调用。

程序分析:

  • 简单演示函数调用关系
  • main → three_hellos → hello_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语言的核心概念和编程技巧,为后续深入学习打下坚实基础。

相关推荐
Decay__9 分钟前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
贞明电子2 小时前
工业三色报警灯怎么接入项目系统?开关量与RS485控制应用指南
运维·网络·微信公众平台·贞明电子
万联WANFLOW3 小时前
海外网络故障怎么排查?Cloudflare 三季度断网报告解读与 mtr 实战
运维·网络·故障分析
听风说ml3 小时前
socket编程 【C语言】
c语言·udp·tcp·socket编程
吠品3 小时前
智谱开源 ZCode 之后,真正的考试才开始
单片机·嵌入式硬件·1024程序员节
学逆向的4 小时前
C 局部静态变量
c语言·开发语言·网络安全
Chery11404 小时前
高速ADC与精密DAC怎么选?DP9230D与DP8532D应用解析
嵌入式硬件·物联网·射频工程
UIU1145 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
Ruiery5 小时前
Linux 6.6内核内存管理深度解析(十三):slab/slub 分配器
linux·运维·服务器
论文复现现场5 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算