C语言程序设计习题与实验指导
前言
C语言是计算机科学的基石,是学习后续高级编程语言(如C++、Java、Python)和操作系统、数据结构等课程的必修课,本指导旨在通过“理论-例题-习题-实验”四位一体的模式,帮助读者巩固C语言的理论知识,提升编程实践能力和问题解决能力。

(图片来源网络,侵删)
使用建议:
- 循序渐进:按照章节顺序学习,确保基础知识牢固后再进入下一阶段。
- 动手实践:编程是“做”出来的,而非“看”出来的,务必亲手敲代码、调试、运行。
- 独立思考:先尝试独立完成习题和实验,遇到困难时再参考答案或寻求帮助。
- 善用调试器:学习使用GDB(Linux/macOS)或VS Debugger(Windows)来定位程序中的错误,这是程序员的必备技能。
第一部分:基础入门
第1章 C语言概述与环境搭建
核心知识点:
- C语言的特点:结构化、高效、可移植、底层操作能力强。
- C程序的基本结构:
#include、main()函数、变量声明、语句、函数定义。 - 开发环境:集成开发环境(IDE,如Visual Studio, Dev-C++, Code::Blocks, CLion)和编译器(如GCC, Clang)。
- 编译过程:预处理、编译、汇编、链接。
精选习题:
- 简答题:简述C语言的主要特点。
- 选择题:一个完整的C语言程序必须包含哪个函数?
- A)
main()函数 - B)
printf()函数 - C)
scanf()函数 - D) 自定义函数
- A)
- 填空题:C语言源程序文件的扩展名通常是__,经过编译后生成的目标文件扩展名是__,经过链接后生成的可执行文件扩展名是__。
- 编程题:编写一个C程序,在屏幕上输出 "Hello, World!"。
第2章 数据类型、运算符与表达式
核心知识点:

(图片来源网络,侵删)
- 数据类型:
- 基本类型:
int,float,double,char。 - 类型修饰符:
short,long,signed,unsigned。 - 常量与变量:整型常量、实型常量、字符常量、字符串常量;变量的定义、初始化、命名规则。
- 基本类型:
- 运算符:
- 算术运算符:, , , , (注意整数除法和取模)。
- 赋值运算符:, , , , , 。
- 自增自减运算符:, (前置和后置的区别)。
- 关系运算符:
>,<,>=,<=, , 。 - 逻辑运算符:
&&(与), (或), (非)。 - 逗号运算符和 sizeof 运算符。
- 表达式:
- 表达式的求值规则:运算符优先级和结合性。
- 类型转换:自动类型转换(隐式)和强制类型转换(显式)。
典型例题:
int a = 5, b = 8;
int c = a++ + --b;
printf("a = %d, b = %d, c = %d\n", a, b, c);
// 解析:a++ 是后置,先取值5,a再自增为6;--b 是前置,b先自减为7,再取值7。
// c = 5 + 7 = 12,最终输出: a = 6, b = 7, c = 12。
精选习题:
- 选择题:执行
int x = 5 / 2;后,变量x的值是__。A) 2.5 B) 2 C) 3 D) 2.0
- 填空题:表达式
10 + 'a' * 2的数据类型是__。 - 编程题1:从键盘输入一个华氏温度,将其转换为摄氏温度并输出,转换公式为:
C = (F - 32) * 5 / 9。 - 编程题2:编写一个程序,交换两个变量的值(要求不使用临时变量)。
第二部分:程序流程控制
第3章 顺序与选择结构
核心知识点:
printf()和scanf()函数的详细用法(格式控制符、地址运算符&)。getchar()和putchar()函数。if语句的三种形式:if,if-else,if-else if-else。switch语句:用于多分支选择,注意break的作用。
精选习题:
- 编程题1:输入一个3位整数,分别输出其个位、十位和百位上的数字。
- 编程题2:使用
if-else语句实现一个简单的计算器程序,支持加减乘除四则运算。 - 编程题3:使用
switch语句,根据输入的数字(1-7)输出对应的星期几。
第4章 循环结构
核心知识点:
for循环:最常用的循环,适用于循环次数明确的情况。while循环:适用于循环条件循环前不明确的情况。do-while循环:至少执行一次循环体。break和continue语句:控制循环流程。- 循环的嵌套:一个循环体内包含另一个完整的循环结构。
典型例题:
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%d*%d=%-2d ", j, i, i * j); // %-2d 表示左对齐,占2位
}
printf("\n"); // 每行结束后换行
}
精选习题:
- 编程题1:计算 1 到 100 之间所有奇数的和。
- 编程题2:判断一个整数是否为素数(质数)。
- 编程题3:打印所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于它本身,153 = 1³ + 5³ + 3³。
- 编程题4:打印如下图案:
第三部分:核心数据结构
第5章 数组
核心知识点:
- 一维数组:
- 定义:
数据类型 数组名[数组长度]; - 初始化:完全初始化、部分初始化、不初始化。
- 引用:
数组名[下标],下标从0开始。
- 定义:
- 二维数组:
- 定义:
数据类型 数组名[行数][列数]; - 初始化和引用。
- 定义:
- 字符数组与字符串:
- 字符数组的定义和初始化。
- 字符串的表示:以
'\0'结尾的字符数组。 strlen(),strcpy(),strcmp()等字符串处理函数(需包含string.h)。
精选习题:
- 编程题1:使用数组实现斐波那契数列的前20项。
- 编程题2:从键盘输入10个整数,存入数组中,找出其中的最大值和最小值。
- 编程题3:实现一个简单的字符串反转函数。
- 编程题4:打印一个N×N的矩阵,其两条对角线上的元素为1,其余为0。
第6章 函数
核心知识点:
- 函数的定义:返回值类型 函数名(形参列表) { 函数体 }
- 函数的声明:
返回值类型 函数名(形参列表);(函数调用之前) - 函数的调用:
函数名(实参列表); - 参数传递:
- 值传递:C语言中默认的传递方式,形参是实参的副本,修改形参不影响实参。
- 指针传递:用于实现“引用传递”的效果,通过地址修改实参的值。
- 函数的递归:函数直接或间接地调用自身。
- 变量的作用域与生命周期:局部变量、全局变量、静态变量(
static)。
典型例题:
void swap(int *p1, int *p2) {
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main() {
int a = 10, b = 20;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b); // 输出 a = 20, b = 10
return 0;
}
精选习题:
- 编程题1:编写一个函数,判断一个数是否为素数,并在
main函数中调用。 - 编程题2:使用递归函数计算阶乘。
- 编程题3:编写一个函数,实现两个字符串的连接(不使用
strcat)。 - 编程题4:使用函数和数组,实现冒泡排序算法。
第四部分:高级特性
第7章 指针
核心知识点:
- 指针的本质:一个变量,其值为另一个变量的内存地址。
- 指针变量的定义:
数据类型 *指针变量名;(如int *p;) - 指针的基本操作:
&(取地址), (解引用/间接寻址)。 - 指针与数组的关系:数组名是数组首元素的地址。
p = arr;等价于p = &arr[0];*(p + i)等价于arr[i]。
- 指针与函数:指针作为函数参数,返回指针。
- 指针数组与数组指针。
- 多级指针。
精选习题:
- 编程题1:使用指针遍历数组并输出所有元素。
- 编程题2:使用指针实现数组元素逆序。
- 编程题3:编写一个函数,使用指针参数,实现一个选择排序算法。
第8章 结构体、共用体与枚举
核心知识点:
- 结构体:
- 定义:
struct 结构体名 { 成员列表 }; - 定义结构体变量:
struct 结构体名 变量名; - 成员访问: (结构体变量) 和
->(结构体指针)。
- 定义:
- 共用体:
- 定义:
union 共用体名 { 成员列表 }; - 特点:所有成员共享同一段内存空间,大小是最大成员的大小。
- 定义:
- 枚举:
- 定义:
enum 枚举名 { 枚举常量列表 }; - 用于定义一组命名的整数常量。
- 定义:
精选习题:
- 编程题1:定义一个包含学生姓名、学号、成绩的结构体,输入5名学生的信息,并找出成绩最高的学生。
- 编程题2:定义一个表示日期的结构体(年、月、日),编写一个函数计算今天是今年的第几天。
第9章 文件操作
核心知识点:
- 文件指针:
FILE *fp; - 文件打开与关闭:
fopen(),fclose()。 - 文件读写:
- 字符读写:
fgetc(),fputc()。 - 字符串读写:
fgets(),fputs()。 - 格式化读写:
fscanf(),fprintf()。 - 数据块读写:
fread(),fwrite()。
- 字符读写:
- 文件定位:
rewind(),fseek(),ftell()。
精选习题:
- 编程题1:将一个文本文件的内容复制到另一个文本文件中。
- 编程题2:将之前习题中创建的学生信息(结构体数组)保存到一个二进制文件中,然后再从文件中读取并显示出来。
第五部分:综合实验项目
项目1:学生成绩管理系统
- 功能要求:
- 使用结构体存储学生信息(学号、姓名、多门课程成绩)。
- 实现从键盘输入学生信息并保存到数组或文件。
- 实现按学号查询学生信息。
- 实现计算每个学生的总分和平均分。
- 实现按总分从高到低排序并输出。
- (可选)实现删除和修改学生信息的功能。
- 涉及知识点:结构体、数组、函数、文件操作、指针、循环、选择。
项目2:简易计算器
- 功能要求:
- 提供一个菜单,让用户选择运算类型(加、减、乘、除、求幂、退出)。
- 根据用户选择,输入操作数。
- 调用对应的函数进行计算并输出结果。
- 处理除数为0等异常情况。
- 使用循环,直到用户选择退出。
- 涉及知识点:函数、循环、选择、指针(可选,用于传递结果)。
项目3:贪吃蛇游戏
- 功能要求:
- 使用控制台绘制游戏界面。
- 实现蛇的移动(通过键盘方向键控制)。
- 随机生成食物。
- 实现蛇吃到食物后身体变长,并得分。
- 实现蛇撞墙或咬到自己后游戏结束。
- 涉及知识点:数组(表示地图和蛇身)、循环、选择、键盘输入、时间函数(
<time.h>)、随机数函数(<stdlib.h>)。
第六部分:常见错误与调试技巧
- 语法错误:忘记分号、括号不匹配、拼写错误,编译器会提示。
- 逻辑错误:程序能运行,但结果不正确,这是调试的重点。
- 打印调试法:在关键位置使用
printf输出变量的值,跟踪程序执行流程。 - 单步调试:使用IDE的调试功能,逐行执行代码,观察变量变化。
- 断点调试:在可疑行设置断点,程序运行到此处会暂停。
- 打印调试法:在关键位置使用
- 运行时错误:程序崩溃或异常终止。
- 数组越界:访问数组下标超出其范围。
- 空指针解引用:对一个
NULL指针进行 操作。 - 内存泄漏:动态分配的内存没有释放(
malloc/free)。
