C 语言书

例题库

完整可运行小程序。先自己写,再对照。

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。学完指针和字符串后再看更顺。