由于市面上有非常多的《C语言程序设计教程》(例如谭浩强、苏小红、C Primer Plus等),我无法提供某一特定教材的逐页答案,我可以为你提供一个系统性的、覆盖了C语言核心知识点的习题解答框架和范例,你可以根据这个框架,对照自己的教材和练习题,来理解和寻找解决方案。

这个解答框架将按照C语言学习的逻辑顺序展开,每个部分都包含:
- 核心知识点回顾
- 典型习题
- 习题解答与分析
- 常见错误与注意事项
第一部分:C语言基础入门
知识点回顾
- 程序结构:
#include预处理指令、main函数、代码块 。 - 基本数据类型:
int(整型),float(单精度浮点型),double(双精度浮点型),char(字符型)。 - 变量与常量:变量的定义、初始化、命名规则;
const关键字定义常量。 - 运算符:算术运算符 (, , , , )、赋值运算符 ()、自增/自减 (, )。
- 输入输出:
printf()函数、scanf()函数的格式化使用。
习题1:Hello World 与基本计算编写一个C程序,打印 "Hello, World!",修改程序,让用户输入两个整数,程序计算并输出它们的和、差、积、商和余数。
解答与分析
#include <stdio.h> // 1. 包含标准输入输出库,以便使用 printf 和 scanf
// 2. 定义 main 函数,C程序的入口点
int main() {
// --- 第一部分:打印 "Hello, World!" ---
printf("Hello, World!\n"); // 3. 使用 printf 函数打印字符串,\n 表示换行
// --- 第二部分:基本计算 ---
int num1, num2; // 4. 定义两个整型变量,用于存储用户输入的数字
int sum, difference, product, quotient, remainder;
// 5. 提示用户输入
printf("请输入两个整数,用空格隔开: ");
// 6. 使用 scanf 读取用户输入
// &num1 表示获取 num1 变量的内存地址,scanf 需要通过地址来存储值
// %d 是格式说明符,表示读取一个十进制整数
scanf("%d %d", &num1, &num2);
// 7. 进行计算
sum = num1 + num2;
difference = num1 - num2;
product = num1 * num2;
// 注意:整数除法会直接丢弃小数部分
quotient = num1 / num2;
remainder = num1 % num2; // % 是取模运算符,用于求余数
// 8. 输出计算结果
// \t 制表符,可以使输出对齐,更美观
printf("和: %d\n", sum);
printf("差: %d\n", difference);
printf("积: %d\n", product);
printf("商: %d\n", quotient);
printf("余数: %d\n", remainder);
return 0; // 9. 程序正常结束,返回 0
}
常见错误:
- 忘记
#include <stdio.h>:编译器不认识printf和scanf。 scanf中忘记使用&:例如写成scanf("%d %d", num1, num2);,这是初学者最常犯的错误之一,会导致程序崩溃或结果错误。- 整数除法陷阱:
5 / 2的结果是2,而不是5,如果需要浮点数结果,必须将操作数至少一个转换为浮点数(0 / 2)。 - 变量未定义:直接使用未定义的变量进行计算。
习题2:字符与ASCII码编写一个程序,接收用户输入的一个字符,然后输出该字符的ASCII码值,以及ASCII码值对应的字符。
解答与分析

#include <stdio.h>
int main() {
char ch; // 定义一个字符型变量
int ascii_value; // 定义一个整型变量来存储ASCII码
printf("请输入一个字符: ");
// scanf("%c", &ch); // 也可以这样用
ch = getchar(); // 使用 getchar() 函数从键盘缓冲区读取一个字符
// 在C语言中,char类型本质上可以当作小整数处理
// 所以可以直接将字符变量赋值给整型变量
ascii_value = ch;
printf("字符 '%c' 的ASCII码是: %d\n", ch, ascii_value);
printf("ASCII码 %d 对应的字符是: %c\n", ascii_value, ascii_value);
return 0;
}
常见错误:
- 混淆
char和int的概念,不理解char在内存中存储的就是其ASCII码值(一个0-127的整数)。
第二部分:流程控制
知识点回顾
- 选择结构:
if-else,switch语句。 - 循环结构:
for循环,while循环,do-while循环。 - 跳转语句:
break,continue,return。
习题3:判断奇偶数编写一个程序,输入一个整数,判断它是奇数还是偶数。
解答与分析
#include <stdio.h>
int main() {
int num;
printf("请输入一个整数: ");
scanf("%d", &num);
// 使用取模运算符 %
// 如果一个数除以2的余数为0,则是偶数
if (num % 2 == 0) {
printf("%d 是一个偶数,\n", num);
} else {
// 否则(余数不为0),就是奇数
printf("%d 是一个奇数,\n", num);
}
return 0;
}
进阶习题:判断一个年份是否为闰年。(闰年规则:能被4整除但不能被100整除,或者能被400整除)
#include <stdio.h>
int main() {
int year;
printf("请输入一个年份: ");
scanf("%d", &year);
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
printf("%d 是闰年,\n", year);
} else {
printf("%d 不是闰年,\n", year);
}
return 0;
}
习题4:打印九九乘法表使用嵌套循环,打印标准的九九乘法表。
解答与分析

#include <stdio.h>
int main() {
int i, j; // i 控制行,j 控制列
// 外层循环控制行数,从1到9
for (i = 1; i <= 9; i++) {
// 内层循环控制每行的列数,从1到当前行数i
for (j = 1; j <= i; j++) {
// printf的格式化输出,%-2d表示左对齐,占2个字符宽度
// 这样可以让结果对齐,看起来更整齐
printf("%d*%d=%-2d ", j, i, i * j);
}
// 每行结束后打印一个换行符
printf("\n");
}
return 0;
}
常见错误:
- 循环的边界条件设置错误(
i < 9而不是i <= 9)。 - 内外层循环混淆,导致打印出的表格是错乱的。
- 忘记在每行结束后换行 (
\n)。
第三部分:函数
知识点回顾
- 函数定义:返回值类型 函数名(参数列表) { 函数体 }
- 函数声明:
返回值类型 函数名(参数列表);(通常放在文件开头) - 函数调用:
函数名(实际参数); - 参数传递:值传递(C语言中函数参数传递都是值传递)。
习题5:使用函数判断素数编写一个函数 is_prime(int num),用于判断一个数是否为素数(质数),然后在 main 函数中调用该函数,判断用户输入的数字。
解答与分析
#include <stdio.h>
#include <math.h> // 为了使用 sqrt 函数
// 函数声明
int is_prime(int num);
int main() {
int number;
printf("请输入一个正整数: ");
scanf("%d", &number);
if (number <= 1) {
printf("%d 不是素数,\n", number);
} else if (is_prime(number)) {
// 调用函数,并根据返回值判断
printf("%d 是素数,\n", number);
} else {
printf("%d 不是素数,\n", number);
}
return 0;
}
// 函数定义
int is_prime(int num) {
// 1. 处理特殊情况
if (num <= 1) {
return 0; // 不是素数
}
// 2. 从2到sqrt(num)进行遍历
// 如果一个数有因数,其中一个必然小于等于它的平方根
for (int i = 2; i <= sqrt(num); i++) {
if (num % i == 0) {
return 0; // 发现因数,不是素数
}
}
// 3. 如果循环结束都没有发现因数,则是素数
return 1;
}
常见错误:
- 函数未声明或未定义:在
main函数之后定义的函数,需要在main之前进行声明。 - 逻辑错误:素数判断的循环条件写错(
i < num而不是i <= sqrt(num)),导致效率低下或判断错误。 - 忘记
return:忘记在函数末尾返回值。
第四部分:数组
知识点回顾
- 一维数组:定义、初始化、元素访问 (
array[index])。 - 二维数组:定义、初始化、元素访问 (
array[row][col])。 - 字符串:以
\0(空字符) 结尾的字符数组。
习题6:数组元素排序(冒泡排序)定义一个包含10个整数的数组,使用冒泡排序算法将其按从小到大的顺序排序,并输出排序前后的数组。
解答与分析
#include <stdio.h>
#define SIZE 10 // 使用宏定义数组大小,方便修改
int main() {
int arr[SIZE] = {64, 34, 25, 12, 22, 11, 90, 88, 76, 50};
int i, j, temp;
// 打印排序前的数组
printf("排序前的数组: ");
for (i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 冒泡排序算法
// 外层循环控制排序的轮数
for (i = 0; i < SIZE - 1; i++) {
// 内层循环进行相邻元素比较和交换
// 每一轮结束后,最大的元素会"冒泡"到最后,所以内层循环可以减少 j-i 次
for (j = 0; j < SIZE - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 交换 arr[j] 和 arr[j+1]
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
// 打印排序后的数组
printf("排序后的数组: ");
for (i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
常见错误:
- 数组越界访问,循环条件写成
i <= SIZE。 - 排序算法的逻辑错误,例如比较符号写反 (
<而不是>)。 - 交换元素时,忘记使用临时变量
temp,导致数据丢失(经典错误:a = b; b = a;)。
第五部分:指针
知识点回顾
- 指针变量:存储内存地址的变量。
&(取地址运算符):获取变量的内存地址。- (解引用/间接寻址运算符):通过指针访问其指向的内存中的值。
- 指针与数组:数组名在大多数情况下会“退化”为其首元素的地址。
- 函数指针:指向函数的指针。
习题7:使用指针交换两个变量的值编写一个函数 swap(int *a, int *b),该函数通过指针交换两个整数的值,在 main 函数中调用它。
解答与分析
#include <stdio.h>
// 函数声明,参数是指针类型
void swap(int *a, int *b);
int main() {
int x = 10, y = 20;
printf("交换前: x = %d, y = %d\n", x, y);
// 调用 swap 函数,传递的是 x 和 y 的地址
swap(&x, &y);
printf("交换后: x = %d, y = %d\n", x, y);
return 0;
}
// 函数定义
void swap(int *a, int *b) {
int temp;
// *a 是 a 指针所指向的值(即 main 函数中的 x)
// *b 是 b 指针所指向的值(即 main 函数中的 y)
temp = *a;
*a = *b;
*b = temp;
}
常见错误:
- 传值而非传址:在
main函数中直接写swap(x, y);,函数内部交换的是x和y的副本,不会影响main函数中的x和y。 - 指针未初始化:定义指针后没有让它指向一个有效的地址,直接解引用会导致程序崩溃。
- 忘记解引用:在函数内部写成
a = b;,这会改变指针a本身的指向,而不是它指向的值。
如何有效利用这些解答?
- 先自己思考:拿到题目后,不要立刻看答案,先自己动手写,尝试解决,即使写不出来,思考的过程也能加深你对知识点的理解。
- 对比分析:当你卡住或完成后,对照上面的解答进行分析,思考:
- 我的代码和标准答案有什么不同?
- 为什么标准答案要这样写?(为什么冒泡排序的内层循环要
j < SIZE - 1 - i?) - 解答中提到的“知识点回顾”是否和我理解的一致?
- 动手调试:将标准答案输入到编译器中,运行它,尝试修改一些代码(比如把
>改成<,把&去掉),观察程序行为的变化,这会让你对错误有更直观的认识。 - 举一反三:做完一道题,思考它的变体,判断奇偶数后,可以扩展为判断正负数;打印九九乘法表后,可以尝试打印一个三角形或菱形。
希望这个系统性的框架能对你的C语言学习有所帮助!祝你学习顺利!
