
(图片来源网络,侵删)
- 理解优于记忆:请务必理解代码的逻辑和背后的原理,而不是简单地复制粘贴。
- 动手实践:亲自将这些代码输入到编译器(如 Dev-C++, Visual Studio Code, GCC 等)中运行、调试,观察结果,并尝试修改题目要求,进行扩展练习。
- 环境差异:不同编译器对C标准的支持可能略有不同,但基础语法是通用的。
第一章:C语言概述与环境
习题1:编写一个简单的C程序,在屏幕上打印 "Hello, World!"。
答案:
#include <stdio.h> // 引入标准输入输出库
int main() {
// printf函数用于向标准输出(通常是屏幕)打印字符串
printf("Hello, World!\n");
return 0; // main函数返回0,表示程序正常结束
}
解析:
#include <stdio.h>:这是一个预处理指令,告诉编译器在编译前将stdio.h文件(标准输入输出头文件)的内容包含进来,这个文件中包含了printf函数的声明。int main():这是C程序的入口函数。int表示这个函数会返回一个整数值, 表示它没有参数。- 花括号用于定义一个代码块,这里是
main函数的主体。 printf("Hello, World!\n");:printf是一个标准库函数,用于格式化输出。"Hello, World!\n"是要打印的字符串,\n是一个转义字符,代表“换行”。return 0;:表示main函数执行成功并返回0,在大多数操作系统中,返回0表示程序正常退出。
第二章:基本数据类型与运算符
习题2:从键盘输入两个整数,计算它们的和、差、积、商,并输出结果。
答案:
#include <stdio.h>
int main() {
int num1, num2; // 定义两个整型变量
printf("请输入两个整数,用空格隔开: ");
// scanf用于从键盘读取输入
// %d 表示读取一个整数
// &num1 和 &num2 是变量的地址,scanf需要知道把读入的数据存放在哪里
scanf("%d %d", &num1, &num2);
printf("和: %d\n", num1 + num2);
printf("差: %d\n", num1 - num2);
printf("积: %d\n", num1 * num2);
// 注意:除法运算,如果两个操作数都是整数,结果也是整数(小数部分被丢弃)
// 如果需要得到浮点数结果,至少有一个操作数应该是浮点数
printf("商: %d\n", num1 / num2); // 整数除法
printf("商 (浮点数): %f\n", (double)num1 / num2); // 强制类型转换,得到浮点数结果
return 0;
}
解析:

(图片来源网络,侵删)
int num1, num2;:定义了两个整型变量,用于存储用户输入的数字。scanf("%d %d", &num1, &num2);:scanf函数用于读取用户输入。%d是格式说明符,表示期望读取一个十进制整数。&是取地址运算符,&num1表示变量num1在内存中的地址,scanf会将读取到的值存放到这个地址。printf("和: %d\n", num1 + num2);:在printf中,%d会被后面的表达式的值替换,这里直接计算和并输出。(double)num1 / num2:这是强制类型转换,它将num1的临时值转换为double类型(双精度浮点数),然后再进行除法运算,因为其中一个操作数是浮点数,所以整个运算会按照浮点数规则进行,保留小数部分。
第三章:流程控制语句
习题3:判断一个整数是奇数还是偶数。
答案:
#include <stdio.h>
int main() {
int number;
printf("请输入一个整数: ");
scanf("%d", &number);
// 使用取模运算符 % 判断余数
// 如果一个数对2取余等于0,说明它能被2整除,就是偶数
if (number % 2 == 0) {
printf("%d 是偶数,\n", number);
} else {
printf("%d 是奇数,\n", number);
}
return 0;
}
解析:
if (number % 2 == 0):这是if-else条件语句。number % 2计算的是number除以2的余数。- 是关系运算符,用于判断“是否等于”,注意不要和赋值运算符 混淆。
- 如果条件
(number % 2 == 0)为真(非0),则执行if后面的代码块;否则,执行else后面的代码块。
习题4:使用 for 循环打印1到100之间所有能被7整除的整数。
答案:
#include <stdio.h>
int main() {
printf("1到100之间能被7整除的整数有:\n");
for (int i = 1; i <= 100; i++) {
// 使用 continue 跳过不符合条件的循环
if (i % 7 != 0) {
continue; // 跳过本次循环的剩余部分,直接进入下一次循环
}
printf("%d ", i);
}
printf("\n"); // 循环结束后打印一个换行
return 0;
}
解析:
for (int i = 1; i <= 100; i++):for循环由三部分组成:int i = 1;:循环初始化部分,在循环开始前执行,定义并初始化循环变量i。i <= 100;:循环条件部分,在每次循环开始前判断,如果为真,则执行循环体;如果为假,则循环结束。i++:循环后处理部分,在每次循环体执行完毕后执行,这里是将i的值加1。
if (i % 7 != 0) { continue; }:continue语句会立即终止当前次的循环,不再执行continue之后的代码,直接跳转到for循环的条件判断部分,进行下一次循环,这是一种优化,可以避免不必要的printf调用。
第四章:数组
习题5:定义一个包含10个整数的数组,找出其中的最大值和最小值。
答案:
#include <stdio.h>
int main() {
int arr[10]; // 定义一个包含10个元素的整型数组
int i, max, min;
printf("请输入10个整数,用空格隔开: ");
for (i = 0; i < 10; i++) {
scanf("%d", &arr[i]); // 为数组的每个元素赋值
}
// 假设第一个元素既是最大值也是最小值
max = arr[0];
min = arr[0];
// 遍历数组进行比较
for (i = 1; i < 10; i++) {
if (arr[i] > max) {
max = arr[i]; // 如果找到更大的,更新max
}
if (arr[i] < min) {
min = arr[i]; // 如果找到更小的,更新min
}
}
printf("最大值是: %d\n", max);
printf("最小值是: %d\n", min);
return 0;
}
解析:
int arr[10];:定义了一个可以存放10个int类型数据的数组,数组的下标(索引)从0开始,所以第一个元素是arr[0],最后一个元素是arr[9]。for (i = 0; i < 10; i++):使用循环遍历数组,为每个元素arr[i]从键盘读取数据。max = arr[0]; min = arr[0];:寻找最值的一个常用技巧是先将第一个元素(或一个已知的值)作为初始的最大值和最小值。for (i = 1; i < 10; i++):从第二个元素开始遍历,与当前的最大值和最小值进行比较。if (arr[i] > max) { max = arr[i]; }:如果当前元素比max大,就用当前元素的值更新max。
第五章:函数
习题6:编写一个函数,判断一个数是否为素数(质数),并在 main 函数中调用它来测试。
答案:
#include <stdio.h>
#include <stdbool.h> // 引入 bool, true, false 的头文件 (C99标准)
// 函数声明:判断一个整数是否为素数
// 参数: int num - 要判断的数
// 返回值: bool - 如果是素数返回 true,否则返回 false
bool isPrime(int num) {
// 处理特殊情况
if (num <= 1) {
return false;
}
// 从2开始遍历到 num/2,看是否有能整除 num 的数
for (int i = 2; i <= num / 2; i++) {
if (num % i == 0) {
return false; // 如果找到能整除的数,说明不是素数
}
}
// 如果循环结束都没有找到,说明是素数
return true;
}
int main() {
int number;
printf("请输入一个正整数: ");
scanf("%d", &number);
if (isPrime(number)) {
printf("%d 是一个素数,\n", number);
} else {
printf("%d 不是一个素数,\n", number);
}
return 0;
}
解析:
bool isPrime(int num):函数定义。bool是返回值类型,表示这个函数会返回一个布尔值(真或假)。isPrime是函数名。(int num)是参数列表,表示这个函数接受一个int类型的参数num。
if (num <= 1) { return false; }:素数的定义是大于1的自然数,所以小于等于1的数直接返回false。for (int i = 2; i <= num / 2; i++):一个优化,一个数num的因子不可能大于num/2(除了它本身),所以循环只需要到num/2即可。return false;和return true;:在函数中,return语句会立即终止函数的执行,并返回一个值给调用者。if (isPrime(number)):在main函数中调用isPrime函数,并将number作为实参传递,函数调用会返回一个bool值,直接用于if判断。
第六章:指针
习题7:使用指针交换两个变量的值。
答案:
#include <stdio.h>
// 函数声明:通过指针交换两个整数的值
void swap(int *a, int *b) {
int temp;
temp = *a; // 将 a 指向的值(即num1的值)存入临时变量
*a = *b; // 将 b 指向的值(即num2的值)赋给 a 指向的变量
*b = temp; // 将临时变量的值(原来的num1的值)赋给 b 指向的变量
}
int main() {
int num1, num2;
printf("请输入两个整数: ");
scanf("%d %d", &num1, &num2);
printf("交换前: num1 = %d, num2 = %d\n", num1, num2);
// 传递变量的地址给函数
swap(&num1, &num2);
printf("交换后: num1 = %d, num2 = %d\n", num1, num2);
return 0;
}
解析:
void swap(int *a, int *b):函数定义。void表示这个函数不返回任何值。int *a和int *b是指针类型的参数,它们可以接收一个int类型变量的地址。
&num1和&num2:在main函数中调用swap时,使用&运算符获取num1和num2的地址,并传递给函数。*a和*b:在swap函数内部, 是解引用(或称间接寻址)运算符。*a表示“访问a所指向的内存地址中的值”。- 核心逻辑:交换的是指针所指向的内存地址中的值,而不是指针本身。
main函数中的num1和num2的值被成功修改。
第七章:结构体
习题8:定义一个表示学生的结构体,包含姓名、学号和成绩,然后创建一个结构体变量并为其赋值,最后输出信息。
答案:
#include <stdio.h>
#include <string.h> // 用于 strcpy 函数
// 1. 定义学生结构体
struct Student {
char name[50]; // 姓名,用字符数组存储
int id; // 学号
float score; // 成绩
};
int main() {
// 2. 创建一个结构体变量
struct Student student1;
// 3. 为结构体成员赋值
// 注意:不能用 student1.name = "张三"; 来直接给字符数组赋值
// 应该使用 strcpy 函数
strcpy(student1.name, "张三");
student1.id = 2025001;
student1.score = 95.5;
// 4. 输出结构体成员信息
printf("学生信息:\n");
printf("姓名: %s\n", student1.name);
printf("学号: %d\n", student1.id);
printf("成绩: %.2f\n", student1.score); // %.2f 表示输出两位小数的浮点数
return 0;
}
解析:
struct Student { ... };:这是一个结构体类型定义,它定义了一个名为Student的模板,模板中包含了name,id,score三个不同类型的成员。struct Student student1;:使用定义好的结构体类型struct Student来创建一个具体的变量student1,这个过程被称为实例化。student1.name:使用点号 运算符来访问结构体变量的成员。strcpy(student1.name, "张三");:name是一个字符数组(C风格字符串),不能直接用 赋值。strcpy(string copy) 函数用于将一个字符串复制到字符数组中,使用它需要包含string.h头文件。
总结与进阶建议
是C语言学习中的基石,掌握了它们,你就可以处理更复杂的问题,
- 文件操作:使用
fopen,fprintf,fscanf,fclose等函数读写文件。 - 动态内存分配:使用
malloc,calloc,free等函数在程序运行时动态地分配和释放内存。 - 链表:结合结构体和指针,实现动态数据结构。
- 预处理和宏:学习
#define,#ifdef等高级预处理功能。
希望这些答案和解析对你的学习有所帮助!祝你学习顺利!
