以下是整理后的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-20)
- 掌握变量、运算符、控制结构
- 理解数组和字符串基本操作
- 熟悉循环和条件判断
-
进阶阶段(实例21-40)
- 掌握函数定义与调用
- 理解指针概念和操作
- 学习结构体使用
-
高级阶段(实例41-60)
- 理解存储类别和作用域
- 掌握预处理指令
- 学习位运算
-
综合应用(实例61-100)
- 文件操作
- 动态内存管理
- 链表等数据结构
- 简单算法实现
常见问题解答
Q: 图形程序无法运行? A: 实例56-65使用<graphics.h>,仅Turbo C支持。现代编译器需使用SDL、OpenGL或Windows API。
Q: 为什么有些代码有安全警告? A: 部分代码使用scanf等不安全的函数,实际开发中应使用scanf_s或限制输入长度。
Q: 如何优化这些练习? A: 可添加输入验证、错误处理、注释说明,并考虑使用更高效的算法。
总结
本系列100个C语言练习实例涵盖了从基础语法到高级应用的各个方面,是C语言学习的宝贵资源。建议读者:
- 按顺序逐一实践,理解每个实例的核心思想
- 尝试修改代码,观察结果变化
- 对相似实例进行对比分析
- 在理解基础上,尝试用不同方法实现同一功能
- 将多个实例组合,实现更复杂的功能
通过系统练习这些实例,读者可以逐步掌握C语言的核心概念和编程技巧,为后续深入学习打下坚实基础。