例题库
完整可运行小程序。先自己写,再对照。
Hello 与多行打印
练什么:熟悉输出、换行、多次调用 printf
#include <stdio.h>
int main(void)
{
printf("Hello, C!\n");
printf("第二行\n\n"); /* 两个换行 = 空一行 */
printf("第三行不自带换行");
printf(",接着打\n");
return 0;
}
\n 是转义字符,表示换行。printf 从左到右依次输出。
四则运算与整数除法
练什么:分清 / 与 %,以及浮点除法
#include <stdio.h>
int main(void)
{
int a = 7, b = 2;
printf("a+b=%d\n", a + b);
printf("a-b=%d\n", a - b);
printf("a*b=%d\n", a * b);
printf("a/b=%d (整数除)\n", a / b);
printf("a%%b=%d\n", a % b);
printf("a/b小数=%f\n", (double)a / b);
return 0;
}
两个 int 用 / 得整数;要小数就先把一边转成 double。
函数:求两数较大值
练什么:参数、返回值、三目运算符
#include <stdio.h>
int max2(int a, int b)
{
if (a > b) return a;
return b;
/* 等价:return a > b ? a : b; */
}
int main(void)
{
printf("%d\n", max2(3, 9)); /* 9 */
printf("%d\n", max2(10, 4)); /* 10 */
return 0;
}
函数先想清楚:输入是什么、返回什么。名字要能读出意图。
循环求 1..n 之和
练什么:for 累加;用公式对拍验证
#include <stdio.h>
int sum_to(int n)
{
int i, s = 0;
for (i = 1; i <= n; i++)
{
s += i;
}
return s;
}
int main(void)
{
printf("%d\n", sum_to(100)); /* 5050 = 100*101/2 */
return 0;
}
n*(n+1)/2 可用来检查循环写对没有。
数组:求最大值与下标
练什么:遍历、维护 max 与 idx
#include <stdio.h>
int main(void)
{
int a[6] = {12, 45, 7, 88, 23, 56};
int max = a[0];
int idx = 0;
int i;
for (i = 1; i < 6; i++)
{
if (a[i] > max)
{
max = a[i];
idx = i;
}
}
printf("max=%d at %d\n", max, idx);
return 0;
}
先假设 a[0] 最大,再从 1 开始比较——这是标准套路。
字符串:长度与拷贝
练什么:strlen、strcpy、strcmp、缓冲够大
#include <stdio.h>
#include <string.h>
int main(void)
{
char src[32] = "Hello";
char dst[32];
strcpy(dst, src); /* 拷贝 */
printf("dst=%s len=%zu\n", dst, strlen(dst));
if (strcmp(src, dst) == 0)
{
printf("两个字符串相同\n");
}
return 0;
}
dst 必须装得下 src(含 \0)。strcpy 不检查空间大小。
指针:交换两个变量
练什么:传址才能改到外面
#include <stdio.h>
void swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
int main(void)
{
int x = 3, y = 8;
swap(&x, &y);
printf("x=%d y=%d\n", x, y); /* x=8 y=3 */
return 0;
}
若参数写成 int a, int b,函数里换的只是副本,外面不变。
结构体:学生表
练什么:typedef、结构体数组、遍历打印
#include <stdio.h>
typedef struct
{
char name[20];
int score;
} Stu;
int main(void)
{
Stu a[3] = {
{"Ann", 90},
{"Bob", 75},
{"Cid", 88}
};
int i;
for (i = 0; i < 3; i++)
{
printf("%-6s %d\n", a[i].name, a[i].score);
}
return 0;
}
%-6s 表示左对齐、宽度 6,打印表格更整齐。
菜单:while + switch
练什么:可退出的命令循环
#include <stdio.h>
int main(void)
{
int cmd = -1;
while (cmd != 0)
{
printf("====\n1 你好\n2 求和\n0 退出\n> ");
if (scanf("%d", &cmd) != 1) break;
switch (cmd)
{
case 1: printf("你好!\n"); break;
case 2: printf("1+2=3\n"); break;
case 0: printf("再见\n"); break;
default: printf("无效\n"); break;
}
}
return 0;
}
scanf 返回成功读入的个数;不是 1 说明输入不是整数,直接退出避免死循环。
综合:算 BMI 并给建议
练什么:读入、浮点、多分支判断
#include <stdio.h>
int main(void)
{
double h, m, bmi;
printf("身高(m) 体重(kg): ");
if (scanf("%lf %lf", &h, &m) != 2)
{
printf("输入错误\n");
return 1;
}
if (h <= 0)
{
printf("身高必须为正\n");
return 1;
}
bmi = m / (h * h);
printf("BMI = %.1f\n", bmi);
if (bmi < 18.5) printf("偏瘦\n");
else if (bmi < 24) printf("正常\n");
else if (bmi < 28) printf("超重\n");
else printf("肥胖\n");
return 0;
}
真实程序一定要校验输入。BMI = 体重 / 身高²。
字符串:统计元音字母
练什么:遍历 char 数组、switch/if、大小写
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[128];
int i, n = 0;
printf("输入一句英文: ");
scanf("%127s", s); /* 简化:只读一个单词 */
for (i = 0; s[i] != '\0'; i++)
{
char c = s[i];
if (c >= 'A' && c <= 'Z') c = (char)(c - 'A' + 'a');
if (c=='a'||c=='e'||c=='i'||c=='o'||c=='u') n++;
}
printf("元音个数 = %d\n", n);
return 0;
}
字母大小写:先统一转小写再判断。也可以用 strchr("aeiou", c)。
排序:冒泡(把大数往后推)
练什么:双重循环交换;理解「每轮把最大冒到末尾」
#include <stdio.h>
int main(void)
{
int a[6] = {5, 2, 9, 1, 7, 3};
int i, j, t;
for (i = 0; i < 5; i++) /* 趟 */
{
for (j = 0; j < 5 - i; j++) /* 相邻比较 */
{
if (a[j] > a[j + 1])
{
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
for (i = 0; i < 6; i++) printf("%d ", a[i]);
printf("\n");
return 0;
}
内层只到 5-i,因为最后 i 个已经排好。O(n²),够教学用。
判断素数(质数)
练什么:试除到 sqrt;函数返回真假
#include <stdio.h>
#include <math.h>
int is_prime(int n)
{
int i;
if (n < 2) return 0;
if (n == 2) return 1;
if (n % 2 == 0) return 0;
for (i = 3; i * i <= n; i += 2)
{
if (n % i == 0) return 0;
}
return 1;
}
int main(void)
{
int x;
printf("输入整数: ");
scanf("%d", &x);
if (is_prime(x)) printf("%d 是素数\n", x);
else printf("%d 不是素数\n", x);
return 0;
}
只要试到 √n。偶数先排除可以少一半循环。编译有时要 -lm。
反转字符串
练什么:头尾对交换;理解下标移动
#include <stdio.h>
#include <string.h>
void reverse(char s[])
{
int i = 0;
int j = (int)strlen(s) - 1;
while (i < j)
{
char t = s[i];
s[i] = s[j];
s[j] = t;
i++;
j--;
}
}
int main(void)
{
char s[64];
printf("单词: ");
scanf("%63s", s);
reverse(s);
printf("反转: %s\n", s);
return 0;
}
j 从最后一个字符(不是 \0)开始。i<j 时交换。
文件:写入再读回(了解)
练什么:fopen/fprintf/fclose/fgets;失败要检查
#include <stdio.h>
int main(void)
{
FILE *fp;
char line[128];
fp = fopen("data.txt", "w");
if (fp == NULL)
{
printf("无法写入\n");
return 1;
}
fprintf(fp, "score=%d\n", 95);
fprintf(fp, "name=%s\n", "Ada");
fclose(fp);
fp = fopen("data.txt", "r");
if (fp == NULL)
{
printf("无法读取\n");
return 1;
}
while (fgets(line, sizeof line, fp) != NULL)
{
printf("%s", line);
}
fclose(fp);
return 0;
}
fopen 失败返回 NULL,必须判。用完 fclose。学完指针和字符串后再看更顺。