第一章:C 语言基础与数据


1. C 语言程序的最小结构

所有的 C 语言程序都始于一个核心结构。

代码行 作用 解释
#include <stdio.h> 头文件包含 引入标准输入输出库(Standard Input/Output)。printf 函数就定义在这个库中。没有它,你就不能在屏幕上打印任何东西。
int main() { ... } 主函数定义 main 是 C 程序的入口点。操作系统就是从这里开始执行你的程序的。int 表示这个函数执行完毕后会返回一个整数值。
printf("..."); 核心输出语句 调用 printf 函数,将括号内的字符串内容打印到屏幕上。\n 是一个转义字符,表示换行。
return 0; 程序返回 告诉操作系统程序已经成功执行完毕。在 C 语言中,return 0 通常表示程序正常退出。

习题 1 (对应:C 语言程序的最小结构)

题目: 请编写一个完整的 C 语言程序,在屏幕上打印输出字符串 Hello, World! 并换行。

要求: 包含必要的头文件,主函数结构完整,返回值正确。

预期输出结果

1
Hello, World!

答案:

1
2
3
4
5
6
#include <stdio.h>

int main() {
printf("Hello, World!\n");
return 0;
}

易错:

  1. 主函数最后要加上return 0;

  2. 输出语句和返回语句后面的分号;不能少


2. 标识符与命名规则

在定义变量(如 score, weight)时,名字不能随便起。

  1. 组成:只能包含字母 (A-Z, a-z)、数字 (0-9)、下划线 (_)。

  2. 禁忌不能以数字开头(如 1st 是错的)。

  3. 避雷:不能是关键字(如 int, return, if 等)。


习题 2 (对应:标识符与命名规则)

题目: 判断下列变量名是否合法。待判断变量名:

  1. 2nd_score

  2. total_sum

  3. float

  4. _user_id

要求: 将合法的变量写出来。

答案:

1
2
3
4
5
6
7
8
1. 2nd_score
错误,不能以数字开头
2. total_sum
正确
3. float
错误,是关键字
4. _user_id
正确

易错:

  1. 变量名不能包含减号 - (如 total-sum 是错的)。

  2. 即使是以 _ 开头也是合法的,但不能以数字开头。


3. 基本数据类型

数据类型决定了变量存储的数据种类和占用的内存空间大小。

类型 (Type) 存储内容 典型大小 格式控制符
int 整数 (Integer) 4 字节 %d
float 单精度浮点数 (小数) 4 字节 %f
double 双精度浮点数 (更精确的小数) 8 字节 %lf
char 字符 (Character) 1 字节 %c

补充考点:

  • sizeof 运算符:用于计算类型大小。例如 sizeof(int) 等于 4。

  • 变量定义:在使用任何变量前,必须先定义它。例如:int score;float price = 10.5;


习题 3 (对应:基本数据类型)

题目: 编写程序,定义以下 4 个变量并赋予初始值:

  1. 整型 age = 18

  2. 单精度浮点 height = 175.5

  3. 双精度浮点 pi = 3.1415926

  4. 字符型 level = ‘A’然后将它们依次打印出来(中间用空格隔开)。

要求: 必须使用正确的数据类型关键字和对应的格式控制符。

预期输出结果:

1
18 175.500000 3.141593 A

答案:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main() {
int age = 18;
float height = 175.5;
double pi = 3.1415926;
char level = 'A';

// %.6lf 是默认精度,题目未要求精度控制,默认即可
printf("%d %f %lf %c\n", age, height, pi, level);
return 0;
}

易错:

  1. 字符常量必须用单引号 ' ',不能用双引号。

  2. 定义变量时忘记初始化(虽不报错,但打印出来是乱码)。


4. 核心 I/O 函数 (输入/输出)

函数 作用 格式控制符 示例
printf() 输出数据到屏幕。 %d (整数), %f (浮点数), %c (字符), %s (字符串) printf("Age: %d", age);
scanf() 接收用户从键盘的输入。 %d, %f, %c, %s scanf("%d", &age);

重点提醒 : 使用 scanf 读取变量时,除了字符串之外,变量名前面必须加 & 符号(取地址符)。这是 C 语言中传址调用的基础。,

补充细节:

  • double 的读写

    • printf 输出时可以用 %f%lf

    • scanf 输入时必须用 %lf,否则数据会出错。


题 4 (对应:核心 I/O 函数)

题目: 编写一个程序,要求用户输入他的学号 (整数)体重 (浮点数),然后程序将这两项信息打印出来。

要求:

  1. 学号使用 int 类型,体重使用 double 类型。

  2. 使用 scanf 获取输入,使用 printf 打印输出。

  3. 输出体重时,要求保留两位小数

预期输出结果:

1
2
3
4
5
6
7
请输入你的学号: 
20251101
请输入你的体重 (kg):
72.5
---你的信息是---
学号: 20251101
体重: 72.50 kg

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main() {
int id;
double weight;

printf("请输入你的学号: \n");
scanf("%d", &id);

printf("请输入你的体重 (kg): \n");
scanf("%lf", &weight); // 重点:double 输入必须用 %lf

printf("---你的信息是---\n");
printf("学号: %d\n", id);
printf("体重: %.2lf kg\n", weight); // 重点:保留两位小数用 %.2lf

return 0;
}

易错:

  1. scanf 中变量名前忘记加 &

  2. scanf 读取 double 时错误使用了 %f(会导致数据全部读错)。


5. 运算符

5.1 算术运算符

用于数学计算。

运算符 描述 示例
+ a + b
- a - b
* a * b
/ a / b
% 取余 (模运算) a % b (只能用于整数)

重点陷阱:

C 语言中的整数除法 (int / int) 结果仍然是整数,会舍弃小数部分。

  • 例如:int result = 10 / 3; $\Rightarrow$ result 是 $3$ 而不是 $3.333$。

  • 若想得到浮点结果,至少一个操作数必须是浮点类型:10.0 / 3(float)10 / 3

5.2 关系运算符

用于比较两个值,结果是 真 (1)假 (0)

运算符 描述
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于 (注意是两个等号!)
!= 不等于

5.3 逻辑运算符

用于组合多个关系表达式。

运算符 描述
&& 逻辑与 (AND):两边都为真才为真。
`| `
! 逻辑非 (NOT):取反。

补充考点 (逻辑短路):

  • 对于 &&:如果左边是假 (0),右边不会执行

  • 对于 ||:如果左边是真 (非0),右边不会执行


习题 5.1 (对应:算术运算符)

题目: 计算 10 和 3 的和、差、积,以及 10 除以 3 的整数商浮点数商

要求:

  1. 必须使用 int, floatdouble 至少三种数据类型。

  2. 重点展示整数除法浮点数除法的区别。

预期输出结果:

1
2
3
4
5
10 + 3 = 13
10 - 3 = 7
10 * 3 = 30
10 / 3 的整数商是:3
10 / 3 的浮点数商是:3.333333

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main() {
int a = 10, b = 3;

int sum = a + b;
int diff = a - b;
int product = a * b;
int int_div = a / b; // 整数除法
double float_div = (double)a / b; // 浮点除法(强制转换)

printf("10 + 3 = %d\n", sum);
printf("10 - 3 = %d\n", diff);
printf("10 * 3 = %d\n", product);
printf("10 / 3 的整数商是:%d\n", int_div);
printf("10 / 3 的浮点数商是:%lf\n", float_div);

return 0;
}

易错:

  1. 整数除以整数 (10/3) 结果会直接截断小数部分变成 3

  2. 想要得到小数,必须让除号两边至少有一个是浮点数。


习题 5.2 (对应:关系运算符)

题目: 定义两个整数 a = 5b = 3。请分别打印 a > b, a < b, a == b 的运算结果。

要求: 理解关系运算的结果本质上是整数 1 (真) 或 0 (假)。

预期输出结果:

1
2
3
5 > 3 的结果是: 1
5 < 3 的结果是: 0
5 == 3 的结果是: 0

答案:

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main() {
int a = 5, b = 3;
printf("5 > 3 的结果是: %d\n", a > b);
printf("5 < 3 的结果是: %d\n", a < b);
printf("5 == 3 的结果是: %d\n", a == b);
return 0;
}

易错:

  1. 判断相等必须用双等号 ==,单等号 = 是赋值。

  2. 关系表达式的结果只有 0 和 1,不会输出 “True” 或 “False”。


习题 5.3 (对应:逻辑运算符)

题目: 验证逻辑运算的“短路”现象。定义 int a = 0int b = 10。执行表达式 (a != 0) && (b++ > 10) 后,打印 b 的值。

要求: 解释为什么 b 的值没有发生变化。

预期输出结果:

1
执行后 b 的值: 10

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int main() {
int a = 0;
int b = 10;

// 逻辑与短路:因为 (a != 0) 为假,电脑直接判定结果为假
// 后面的 (b++ > 10) 根本不会被执行
if ((a != 0) && (b++ > 10)) {
// 这里不会执行
}

printf("执行后 b 的值: %d\n", b);
return 0;
}

易错:

  1. 误以为表达式里的代码一定会执行。

  2. && 运算中,一旦左边为假 (0),右边立即停止执行。


6. ASCII 码与类型转换

  1. 关键 ASCII 码值

    • 'A' = 65

    • 'a' = 97 (小写 = 大写 + 32)

    • '0' = 48

  2. 自动类型转换

    • intdouble 运算时,结果会自动变成 double

习题 6 (对应:ASCII 码与字符计算)

题目: 编写程序,输入一个小写字母(如 ‘a’),将其转换为大写字母并输出。同时输出转换后的字符对应的 ASCII 码整数值。

要求: 利用 'a''A' 之间的差值 (32) 进行计算。

预期输出结果:

1
2
3
输入小写字母: a
转换后的大写字母: A
对应的 ASCII 码: 65

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main() {
char small;
printf("输入小写字母: ");
scanf("%c", &small);

// 小写转大写:减去 32
char big = small - 32;

printf("转换后的大写字母: %c\n", big);
printf("对应的 ASCII 码: %d\n", big);
return 0;
}

易错:

  1. 混淆大小写转换的加减方向(小转大是减,大转小是加)。
  2. 忘记 'A' 的 ASCII 码是 65,'a' 是 97。

7. 字符与字符串的区别 (单引号 vs 双引号) [必考]

C 语言中,单引号和双引号绝对不能混用,它们的本质完全不同。

7.1 核心对比表

特性 单引号 ‘ ‘ 双引号 “ “
对象 字符常量 (Character) 字符串字面量 (String)
本质 是一个整数 (ASCII 码值) 是一个地址 (指向内存中的数组)
大小 (以 ‘A’ 为例) 1 个字节 (存的是 65) 2 个字节 (存的是 ‘A’ 和 ‘\0’)
示例 char c = 'A'; char str[] = "A";
能做加减法吗? ('A' + 1 等于 66) 不能 ("A" + 1 是非法指针运算)

7.2 经典陷阱:’A’ 和 “A” 的区别

这是选择题最爱考的题目:

  • 'A'

    • 它是单个字符。

    • 在内存里就是数字 65

  • "A"

    • 它是字符串。

    • 虽然看起来只有一个字母,但 C 语言会自动在后面加一个结束符 \0

    • 所以在内存里它是:'A' + \0'

错误写法:

char c = “A”; // 错!不能把一个“字符串地址”硬塞给一个“字符变量”。

char str[] = ‘A’; // 错!不能用单个字符去初始化数组(除非用花括号)。


习题 7 (对应:单引号与双引号的区别)

题目: 编写程序,定义字符变量 c = ‘A’ 和字符串数组 str = “A”。

请通过 sizeof 运算符,分别打印它们在内存中占用的字节数,以验证 “A” 确实比 ‘A’ 多一个 \0。

要求:

  1. 使用 sizeof 运算符。

  2. 理解为什么字符串的大小是 2。

预期输出结果:

1
2
字符 'A' 的大小: 1
字符串 "A" 的大小: 2

(注:在某些编译器下,sizeof(‘A’) 可能会显示 4,因为 C 语言将字符常量视为 int,但这里我们要验证的是它作为 char 存储时的概念,或者可以直接对比 sizeof(char变量) 和 sizeof(“A”)。为了不让你混淆,我们对比变量和字符串字面量)

修正后的严谨答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main() {
char c = 'A'; // 单引号:单个字符
// char str[] = "A"; // 双引号:字符串 (包含 'A' 和 '\0')

// sizeof(c) 计算变量 c 占用的空间 -> 1 字节
// sizeof("A") 计算字符串 "A" 占用的空间 -> 2 字节 ('A' + '\0')

printf("字符变量 c 的大小: %lu\n", sizeof(c));
printf("字符串 \"A\" 的大小: %lu\n", sizeof("A"));

return 0;
}

易错:

  1. 混淆概念,以为 "A" 也只占 1 个字节。

  2. 试图写 char c = "A"; 导致编译报错(类型不匹配)。

  3. printf 里打印双引号需要转义:\"