exam-85 试卷整理与详解
这份笔记是根据 85.pdf 整理出来的,原卷文件在本地路径:
/Users/wff/Downloads/85.pdf这套题主要复习函数调用、数组和字符串、二维数组、指针、static 局部变量、结构体、宏、字符串库函数、改错题和程序设计题。
PDF 的 OCR 对代码符号有一些误差,比如 '\0'、==、[]、{}、getchar()、FILE、||、a[i][i] 等容易识别错。我整理时按原卷红色答案、题意和 C 语言语法做了校对。
特别提醒:
- 本卷有传统 C 教材/考试口径,比如函数没有显式说明返回类型时,默认按
int理解。现代 C 不建议这样写,实际代码请明确写返回类型。 gets()在旧教材里常出现,但现代 C 已不推荐使用,真实写程序优先用fgets()。int n = 5, a[n];在传统基础卷中通常判错;部分现代编译器支持变长数组,不影响本卷答案。- 第 6 题的
a[3,5]按严格 C 语法会被解释为逗号表达式a[5],但基础卷常按“错误数组引用形式”处理。做考试先按原卷答案记,理解时知道逗号表达式这个细节即可。 - 程序设计第 1 题红字里出现了
a[i][j],但题目要求“主对角线元素的积”,正确逻辑应是a[i][i]。我在程序设计解析中按题意修正。
1. 答案速查
Section titled “1. 答案速查”1.1 选择题答案
Section titled “1.1 选择题答案”| 题号 | 答案 |
|---|---|
| 1 | B |
| 2 | D |
| 3 | A |
| 4 | C |
| 5 | C |
| 6 | B |
| 7 | B |
| 8 | D |
| 9 | A |
| 10 | B |
| 11 | B |
| 12 | B |
| 13 | C |
| 14 | C |
| 15 | D |
| 16 | B |
| 17 | D |
| 18 | B |
| 19 | B |
| 20 | B |
| 21 | D |
| 22 | A |
| 23 | A |
| 24 | B |
| 25 | C |
1.2 填空题答案
Section titled “1.2 填空题答案”| 题号 | 答案 |
|---|---|
| 1 | 1217 |
| 2 | 10 |
| 3 | 1 |
| 4 | p=a |
| 5 | How does she |
| 6 | 主 或 main |
| 7 | 1 |
| 8 | 9 |
| 9 | 20 |
| 10 | x%2==0 等合法写法 |
1.3 判断题答案
Section titled “1.3 判断题答案”| 题号 | 答案 |
|---|---|
| 1 | N |
| 2 | Y |
| 3 | N |
| 4 | N |
| 5 | N |
| 6 | Y |
| 7 | Y |
| 8 | N |
| 9 | N |
| 10 | Y |
2. 选择题详解
Section titled “2. 选择题详解”选择题第 1 题
Section titled “选择题第 1 题”题目问:若已定义的函数有返回值,则以下关于该函数调用的叙述中错误的是哪一个?
答案:B
错误说法:
函数调用可以作为一个函数的形参。详细解析:
有返回值的函数调用可以像一个值一样使用。
例如可以作为独立语句:
fun();可以出现在表达式中:
x = fun() + 3;也可以作为另一个函数的实参:
printf("%d\n", fun());但“形参”是函数定义或函数声明里的参数名,不是函数调用结果能充当的东西。
例如:
int add(int a, int b){ return a + b;}这里 a、b 是形参,add(1, 2) 是函数调用。
容易踩坑点:
- 把“形参”和“实参”混在一起。函数调用可以当实参,不能当形参。
给新手的建议:
- 形参在函数定义处,实参在函数调用处。
选择题第 2 题
Section titled “选择题第 2 题”题目问:下列说法中错误的是哪一个?
答案:D
错误说法:
如果数组初始化时给定的数据元素个数比数组元素个数少,多余的数组元素会被自动初始化为最后一个给定元素的值。详细解析:
数组部分初始化时,没写到的元素会自动初始化为 0,不是初始化为最后一个给定元素。
例如:
int a[5] = {6, 7};实际结果是:
a[0] = 6a[1] = 7a[2] = 0a[3] = 0a[4] = 0不是:
6 7 7 7 7容易踩坑点:
- 把“补 0”误记成“补最后一个值”。
给新手的建议:
- 数组部分初始化口诀:写几个算几个,没写到的补
0。
选择题第 3 题
Section titled “选择题第 3 题”题目问:C 语言中,每个字符串末尾的字符串结束符是哪一个?
答案:A
答案:
'\0'详细解析:
C 字符串以空字符 '\0' 作为结束标志。
例如:
char s[] = "abc";内存中实际是:
'a' 'b' 'c' '\0'其他选项区别:
'0'是字符数字 0,它的 ASCII 值不是 0。"0"是字符串,里面有字符'0'和结尾'\0'。"\0"是字符串字面量,不是一个字符常量。
容易踩坑点:
'\0'和'0'不是一个东西。
给新手的建议:
- 字符串结束符一定记成反斜杠零:
'\0'。
选择题第 4 题
Section titled “选择题第 4 题”题目问:与实际参数为实型数组名相对应的形式参数不可以定义为什么?
答案:C
错误选项:
float a;详细解析:
数组名作为函数实参传递时,传递的是数组首地址。因此形参通常要写成数组形式或指针形式。
一维实型数组常见写法:
void fun(float a[]){ ...}或者:
void fun(float *a){ ...}但:
float a;只是一个普通 float 变量,不能接收数组首地址。
容易踩坑点:
- 把数组参数当成单个普通变量。
给新手的建议:
- 数组传参时,形参一般写
类型名 数组名[]或类型名 *指针名。
选择题第 5 题
Section titled “选择题第 5 题”题目整理:
int fun3(int x){ static int a = 3; a += x; return a;}
int main(void){ int k = 2, m = 1, n; n = fun3(k); n = fun3(m); printf("%d\n", n); return 0;}答案:C
输出:
6详细解析:
static int a = 3; 只初始化一次,并且函数调用结束后值不会丢失。
第一次调用:
fun3(k) -> fun3(2)a = 3 + 2 = 5返回 5第二次调用:
fun3(m) -> fun3(1)a 不是重新变成 3,而是保留上次的 5a = 5 + 1 = 6返回 6所以最终 n = 6。
容易踩坑点:
- 以为
static int a = 3;每次调用都会重新执行初始化。
给新手的建议:
static局部变量记住:只初始化一次,值会保留。
选择题第 6 题
Section titled “选择题第 6 题”题目整理:
int a[10];问:对 a 数组元素的正确引用是哪一个?
答案:B
正确选项:
a[10 - 10]详细解析:
计算下标:
10 - 10 = 0所以:
a[10 - 10]等价于:
a[0]这是合法元素。
其他选项:
a[10]越界,长度为 10 的数组合法下标是0 ~ 9。a(5)不是数组元素引用语法。a[3,5]在基础考试口径中不作为正确数组引用形式。
补充理解:
严格 C 语法里,a[3,5] 会被解释为:
a[(3, 5)]逗号表达式 (3, 5) 的值是 5,所以它等价于 a[5]。但这类写法非常不推荐,也不是基础题期望你使用的数组引用形式。
容易踩坑点:
- 长度为
10的数组不能访问a[10]。
给新手的建议:
- 正常写数组下标时,不要在
[]里乱写逗号,按清晰的整数下标写。
选择题第 7 题
Section titled “选择题第 7 题”题目整理:
int a[4][5];问:对 a 中数组元素的正确引用是哪一个?
答案:B
正确选项:
a[4 - 1][5 - 5]详细解析:
计算下标:
4 - 1 = 35 - 5 = 0所以:
a[4 - 1][5 - 5]等价于:
a[3][0]数组 a[4][5] 的合法行下标是 0 ~ 3,合法列下标是 0 ~ 4,所以 a[3][0] 合法。
其他选项:
a[4][1]行下标4越界。a[4][5]行和列都越界。a[2,1]不是二维数组元素的正常引用形式。
容易踩坑点:
- 二维数组
a[4][5]不是最大下标4和5,而是行数 4、列数 5。
给新手的建议:
- 二维数组下标范围:第一维
0 ~ 行数-1,第二维0 ~ 列数-1。
选择题第 8 题
Section titled “选择题第 8 题”题目整理:
int a[10] = {6, 7, 8, 9, 10};问:正确理解是哪一个?
答案:D
正确理解:
将 5 个初值依次赋给 a[0] 至 a[4]。详细解析:
数组初始化从下标 0 开始:
a[0] = 6a[1] = 7a[2] = 8a[3] = 9a[4] = 10其余元素自动补 0:
a[5] ~ a[9] = 0容易踩坑点:
- 以为第一个初值赋给
a[1]。 - 以为初值
6对应a[6]。
给新手的建议:
- 初始化列表永远从数组第一个元素开始放,也就是从下标
0开始。
选择题第 9 题
Section titled “选择题第 9 题”题目整理:
char a[] = "This is a program.";问:输出前 5 个字符的语句是哪一个?
答案:A
正确选项:
printf("%.5s", a);详细解析:
%s 用于输出字符串,.5 表示最多输出 5 个字符。
所以:
printf("%.5s", a);会输出:
This注意第 5 个字符是空格。
容易踩坑点:
printf("%s", a)会输出整个字符串。puts(a)也会输出整个字符串并自动换行。
给新手的建议:
- 想限制字符串输出长度,可以使用
printf的精度格式:%.Ns。
选择题第 10 题
Section titled “选择题第 10 题”题目问:以下不能正确定义二维数组的选项是哪一个?
答案:B
错误选项按题意整理为:
int a[2][] = {{1, 2}, {3, 4}};详细解析:
二维数组定义时,第二维不能省略。
错误点在:
a[2][]编译器必须知道每一行有多少列,才能计算 a[i][j] 的地址。
正确写法:
int a[2][2] = {{1, 2}, {3, 4}};容易踩坑点:
- 以为初始化列表已经写了两列,第二维就可以省略。C 语言不允许这样。
给新手的建议:
- 二维数组口诀:第一维可以省,第二维必须写。
选择题第 11 题
Section titled “选择题第 11 题”题目整理:
int a[][4] = {0, 0};问:下面不正确的叙述是哪一个?
答案:B
错误说法:
有元素 a[0][0] 和 a[0][1] 可得到初值 0,其余元素均得不到初值 0。详细解析:
a[][4] 表示每行 4 个元素。初始化列表有两个 0,所以第一维推断为 1。
等价于:
int a[1][4] = {0, 0};数组实际是:
0 0 0 0没有显式写到的元素也会自动补 0。
容易踩坑点:
- 以为只有写出来的两个元素有初值。
给新手的建议:
- 数组一旦部分初始化,后面没写到的元素会自动补
0。
选择题第 12 题
Section titled “选择题第 12 题”题目整理:
char a[10];问:以下语句中不能从键盘上给 a 数组的所有元素输入值的是哪一个?
答案:B
错误选项按题意整理为:
a = getchar();详细解析:
a 是数组名,不能被整体赋值。
而且 getchar() 一次只读取一个字符,不能直接给整个数组赋值。
其他写法:
gets(a);旧教材中认为可以读入一行字符串。
for (i = 0; i < 10; i++) a[i] = getchar();可以逐个字符读入。
scanf("%s", a);可以读入一个不含空白字符的字符串。
容易踩坑点:
- 数组名不能出现在赋值号左边表示“整个数组接收一个值”。
给新手的建议:
- 给数组元素赋值,用下标;给字符数组读字符串,用数组名作为地址。
选择题第 13 题
Section titled “选择题第 13 题”题目整理:
#include <stdio.h>
int main(void){ int i; int x[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (i = 0; i < 3; i++) printf("%d,", x[i][2 - i]);
return 0;}答案:C
输出:
3,5,7,详细解析:
数组按行填充:
x[0]: 1 2 3x[1]: 4 5 6x[2]: 7 8 9循环访问:
| i | 2 - i | 访问元素 | 值 |
|---|---|---|---|
| 0 | 2 | x[0][2] | 3 |
| 1 | 1 | x[1][1] | 5 |
| 2 | 0 | x[2][0] | 7 |
所以输出:
3,5,7,容易踩坑点:
- 没有先把二维数组画成表格。
给新手的建议:
- 二维数组输出题先画行列表,再代入下标。
选择题第 14 题
Section titled “选择题第 14 题”题目问:以下能对一维数组 a 进行正确初始化的语句是哪一个?
答案:C
正确选项:
int a[10] = {0};详细解析:
{0} 会让第一个元素显式初始化为 0,其余元素自动补 0。
所以整个数组都是 0:
0 0 0 0 0 0 0 0 0 0其他选项的问题:
- 初始化数组要用花括号
{},不能用圆括号()。 - 传统 C 考试中数组长度不能用普通变量
n。 int a[10] = 0;不是数组初始化的正确形式。
容易踩坑点:
- 误以为
= 0可以初始化整个数组。数组初始化要写= {0}。
给新手的建议:
- 数组清零模板:
int a[10] = {0};。
选择题第 15 题
Section titled “选择题第 15 题”题目整理:
int b;char c[10];问:正确的输入语句是哪一个?
答案:D
正确写法:
scanf("%d%s", &b, c);详细解析:
%d 要读入一个整数,需要传入变量地址:
&b%s 要读入字符串,字符数组名 c 本身就代表数组首地址,所以写:
c不需要写 &c。
容易踩坑点:
%d忘记写&。%s对字符数组名又多写一个&。
给新手的建议:
- 普通变量输入一般加
&,字符数组用%s输入时直接写数组名。
选择题第 16 题
Section titled “选择题第 16 题”题目问:以下数组定义中不正确的是哪一个?
答案:B
错误选项按题意整理为:
int d[3][] = {{1, 2}, {1, 2, 3}, {1, 2, 3, 4}};详细解析:
二维数组定义时,第二维不能省略。
错误点:
d[3][]编译器不知道每行有多少个元素,就无法计算元素地址。
可以改成:
int d[3][4] = {{1, 2}, {1, 2, 3}, {1, 2, 3, 4}};容易踩坑点:
- 第一维可以省略,第二维不能省略。
给新手的建议:
- 看到二维数组
[][列数]可以,看到[行数][]要警惕。
选择题第 17 题
Section titled “选择题第 17 题”题目问:下列不能正确进行字符串赋值的语句是哪一个?
答案:D
错误选项:
char s[5] = {'a', 'b', 'c', 'd', 'e'};详细解析:
这句作为“字符数组初始化”是可以的,它定义了 5 个字符:
a b c d e但它不是一个正确的 C 字符串,因为没有结尾的 '\0'。
如果要作为字符串 "abcde",至少需要 6 个位置:
char s[6] = "abcde";或者:
char s[] = "abcde";容易踩坑点:
- 字符数组合法,不代表它一定是合法字符串。
给新手的建议:
- 只要题目说“字符串”,就要检查有没有空间放
'\0'。
选择题第 18 题
Section titled “选择题第 18 题”题目整理:
int func(int a, int b){ return a + b;}
int main(void){ int x = 2, y = 5, z = 8, r; r = func(func(x, y), z); printf("%d\n", r); return 0;}答案:B
输出:
15详细解析:
先算内层:
func(x, y) = func(2, 5) = 7再算外层:
func(7, z) = func(7, 8) = 15所以输出 15。
容易踩坑点:
- 看到函数嵌套调用就乱,其实从最里面开始算就行。
给新手的建议:
- 函数嵌套调用题,用“由内向外”的顺序计算。
选择题第 19 题
Section titled “选择题第 19 题”题目问:以下定义语句中,错误的是哪一个?
答案:B
错误选项:
int n = 5, a[n];详细解析:
按传统 C 基础考试口径,数组长度要使用常量表达式,不能使用普通变量。
所以本题判:
int n = 5, a[n]; // 错误补充提醒:
部分现代 C 编译器可能支持变长数组,但考试题按传统教材答案处理。
容易踩坑点:
- 把“某些编译器能跑”和“基础考试标准答案”混在一起。
给新手的建议:
- 做这类卷子时,数组长度优先写成明确数字,比如
int a[5];。
选择题第 20 题
Section titled “选择题第 20 题”题目问:对于 void 类型函数,调用时不可作为哪一种形式?
答案:B
答案:
表达式详细解析:
void 函数没有返回值,所以不能把它当成一个值来参与表达式。
例如:
void show(void){ printf("hello\n");}可以这样调用:
show();不能这样写:
int x = show() + 1; // 错误因为 show() 没有值。
容易踩坑点:
- 以为所有函数调用都能拿来计算。
给新手的建议:
void表示“没有返回值”,只能做动作,不能当值用。
选择题第 21 题
Section titled “选择题第 21 题”题目问:若二维数组 a 有 m 列,则在 a[i][j] 前的元素个数是多少?
答案:D
答案:
i * m + j详细解析:
C 语言二维数组按行存储。
在 a[i][j] 前面有:
- 前面完整的
i行,每行m个元素,共i * m个。 - 当前第
i行中,a[i][j]前面还有j个元素。
所以总数是:
i * m + j容易踩坑点:
- 忘记下标从
0开始。 - 把
i和j写反。
给新手的建议:
- 二维数组位置题就想:前面几整行,加上本行前面几个。
选择题第 22 题
Section titled “选择题第 22 题”题目整理:
int max(int x, int y){ int z;
if (x > y) z = x; else z = y;
return z;}
int main(void){ int a = 45, b = 27, c = 0; c = max(a, b); printf("%d\n", c); return 0;}答案:A
输出:
45详细解析:
调用:
max(45, 27)因为:
45 > 27所以 z = 45,返回 45。
容易踩坑点:
- 原卷 OCR 中
main和变量声明有缺失,按题意应理解为比较两个数取较大值。
给新手的建议:
- 函数返回题先看函数体最终
return什么。
选择题第 23 题
Section titled “选择题第 23 题”题目整理:
char a1[] = "abc";char a2[80] = "1234";问:将 a1 串连接到 a2 串后面的语句是哪一个?
答案:A
正确写法:
strcat(a2, a1);详细解析:
strcat(目标字符串, 追加的字符串) 会把第二个字符串连接到第一个字符串后面。
执行后:
a2 = "1234abc"容易踩坑点:
strcpy是复制,会覆盖原字符串。strcat(a1, a2)是把a2追加到a1后面,方向反了。
给新手的建议:
strcat(a2, a1)可以读成:把a1接到a2后面。
选择题第 24 题
Section titled “选择题第 24 题”题目整理:
static char str[10] = "China";问:数组元素个数是多少?
答案:B
答案:
10详细解析:
数组定义中已经写明:
str[10]所以数组元素个数就是 10。
字符串 "China" 有 5 个有效字符,加上 '\0' 占 6 个位置,但数组整体仍然有 10 个元素。
容易踩坑点:
- 把字符串长度
5或字符串占用空间6当成数组元素个数。
给新手的建议:
- 问数组元素个数,看方括号里的长度。
选择题第 25 题
Section titled “选择题第 25 题”题目问:C 语言程序中,若对函数类型未加显式说明,则函数的隐含说明类型是什么?
答案:C
答案:
int详细解析:
按传统 C 教材口径,函数未显式写返回类型时,默认返回 int。
例如老式写法:
fun(void){ return 1;}会按:
int fun(void)理解。
现代 C 不推荐这样写,实际代码应明确写返回类型:
int fun(void){ return 1;}容易踩坑点:
- 以为 C 会根据
return自动推断函数返回类型。
给新手的建议:
- 实际写代码时,函数名前面一定明确写
int、void、double等返回类型。
3. 填空题详解
Section titled “3. 填空题详解”填空题第 1 题
Section titled “填空题第 1 题”题目整理:
int x;scanf("%d", &x);
if (x > 15) printf("%d", x - 5);if (x > 10) printf("%d", x);if (x > 5) printf("%d", x + 5);输入:
12答案:
1217详细解析:
x = 12。
三个 if 是彼此独立的,不是 else if。
依次判断:
12 > 15 假,不输出12 > 10 真,输出 1212 > 5 真,输出 17所以连在一起输出:
1217容易踩坑点:
- 把三个独立
if当成if...else if...else。
给新手的建议:
- 没有
else的多个if会一个一个独立判断。
填空题第 2 题
Section titled “填空题第 2 题”题目整理:
for (i = 0, j = 10; i <= j; i++, j--) k = i + j;答案:
10详细解析:
每轮循环中:
i + j始终是 10。
变化过程:
| i | j | i <= j | k = i + j |
|---|---|---|---|
| 0 | 10 | 真 | 10 |
| 1 | 9 | 真 | 10 |
| 2 | 8 | 真 | 10 |
| 3 | 7 | 真 | 10 |
| 4 | 6 | 真 | 10 |
| 5 | 5 | 真 | 10 |
| 6 | 4 | 假 | 停止 |
最终 k = 10。
容易踩坑点:
- 忘记
i = 5, j = 5时条件仍然成立。
给新手的建议:
- 双变量
for循环题,画表最稳。
填空题第 3 题
Section titled “填空题第 3 题”题目整理:
int a = 3, b = 2, c = 1;
if (a > b) a = b;if (b > c) b = c;else c = b;答案:
1详细解析:
初始:
a = 3b = 2c = 1第一个 if:
a > b -> 3 > 2 为真a = b -> a = 2第二个 if:
b > c -> 2 > 1 为真b = c -> b = 1所以最终:
b = 1容易踩坑点:
else只和离它最近、尚未匹配的if配对。
给新手的建议:
- 变量变化题每执行一条赋值语句,就立刻更新变量值。
填空题第 4 题
Section titled “填空题第 4 题”题目问:将数组 a 的首地址赋给指针变量 p 的语句是什么?
答案:
p = a;详细解析:
数组名 a 在表达式中通常代表数组首元素地址,也就是:
&a[0]所以可以写:
p = a;等价理解为:
p = &a[0];容易踩坑点:
- 写成
*p = a,这是给p指向的变量赋值,不是让p指向数组。
给新手的建议:
- 指针保存地址,数组名可以当首地址用。
填空题第 5 题
Section titled “填空题第 5 题”题目整理:
#include <string.h>
int main(void){ char str1[] = "How do you do", *p1 = str1; strcpy(str1 + strlen(str1) / 2, "es she"); printf("%s\n", p1); return 0;}答案:
How does she详细解析:
原字符串:
How do you do长度是 13,所以:
strlen(str1) / 2 = 13 / 2 = 6str1 + 6 指向下标 6 的位置。
原字符串下标:
0:H 1:o 2:w 3:' ' 4:d 5:o 6:' ' 7:y 8:o 9:u 10:' ' 11:d 12:o从下标 6 开始复制 "es she",会把后面的内容覆盖掉:
How do + es she -> How does she容易踩坑点:
strcpy会从目标位置开始覆盖原内容。strlen(str1) / 2是整数除法。
给新手的建议:
- 字符串指针偏移题,一定把每个字符的下标标出来。
填空题第 6 题
Section titled “填空题第 6 题”题目问:一个 C 源程序中至少应包括一个什么函数?
答案:
main或:
主函数详细解析:
C 程序从 main 函数开始执行。
标准写法:
int main(void){ return 0;}容易踩坑点:
- 把
main当成普通函数名随便改。程序入口必须是main。
填空题第 7 题
Section titled “填空题第 7 题”题目整理:
int x = 72;x = (x >= 60);答案:
1详细解析:
关系表达式:
x >= 60 -> 72 >= 60 -> 真在 C 语言中,关系表达式为真时值为 1,为假时值为 0。
所以:
x = 1表达式的值也是 1。
容易踩坑点:
- 以为
x仍然是72。赋值后x已经变成1。
填空题第 8 题
Section titled “填空题第 8 题”题目整理:
int f(int x, int y){ return (y - x) * x;}
int main(void){ int a = 3, b = 4, c = 5, d; d = f(f(3, 4), f(3, 5)); printf("%d\n", d); return 0;}答案:
9详细解析:
先算内层:
f(3, 4) = (4 - 3) * 3 = 3f(3, 5) = (5 - 3) * 3 = 6再算外层:
f(3, 6) = (6 - 3) * 3 = 9所以输出 9。
容易踩坑点:
- 函数嵌套调用时,没有先从最里面开始算。
给新手的建议:
- 遇到
f(f(...), f(...)),先把两个内层函数分别算出来。
填空题第 9 题
Section titled “填空题第 9 题”题目问:逗号表达式 (a=3*5,a*4),a+5 的值是多少?
答案:
20详细解析:
先看前半部分:
(a = 3 * 5, a * 4)执行后:
a = 15a * 4 = 60但整个题目后面还有:
, a + 5逗号表达式的值是最后一个表达式的值,所以最终值是:
a + 5 = 15 + 5 = 20容易踩坑点:
- 只算到
a * 4 = 60就停了。
给新手的建议:
- 逗号表达式从左到右执行,但最终值看最后一个表达式。
填空题第 10 题
Section titled “填空题第 10 题”题目问:设 x 为 int 型变量,描述“x 是偶数”的表达式是什么?
答案示例:
x % 2 == 0详细解析:
偶数除以 2 的余数为 0,所以用求余运算:
x % 2判断余数是否等于 0:
x % 2 == 0容易踩坑点:
- 判断相等要写
==,不能写=。
给新手的建议:
- 整除判断固定模板:
x % n == 0。
4. 判断题详解
Section titled “4. 判断题详解”判断题第 1 题
Section titled “判断题第 1 题”题目整理:
int i = 10, j = 0;if (j = 0) i++;else i--;题目说执行后 i 的值为 11。
答案:N
详细解析:
j = 0 是赋值表达式,不是判断相等。
赋值表达式的值是被赋的值,也就是 0。
所以 if 条件为假,执行:
i--;最终:
i = 9容易踩坑点:
- 把
=看成==。
判断题第 2 题
Section titled “判断题第 2 题”题目:整数 -32100 可以赋值给 int 型和 long int 型变量。
答案:Y
详细解析:
按传统教材常见环境,int 可以表示到 -32768,所以 -32100 在范围内;long int 范围更大,也可以保存。
容易踩坑点:
- 只记正数范围,忘记有符号整数还有负数范围。
判断题第 3 题
Section titled “判断题第 3 题”题目整理:
int i = 3;printf("%d", -i++);题目说输出值为 -4。
答案:N
详细解析:
后置自增 i++ 先使用原值,再自增。
表达式:
-i++按优先级理解为:
-(i++)所以输出的是:
-3输出之后,i 才变成 4。
容易踩坑点:
- 把后置自增当成先加后用。
判断题第 4 题
Section titled “判断题第 4 题”题目整理:
file *fp;fp = fopen("a.txt", "r");题目说在 Turbo C 中合法。
答案:N
详细解析:
文件指针类型应该写成大写:
FILE *fp;并且需要包含头文件:
#include <stdio.h>file 不是标准文件类型名。
容易踩坑点:
- C 语言大小写敏感,
FILE和file不是同一个东西。
判断题第 5 题
Section titled “判断题第 5 题”题目:
char *p = "girl";题目说它的含义是定义字符型指针变量 p,p 的值是字符串 "girl"。
答案:N
详细解析:
p 是字符指针,它保存的是字符串常量首字符的地址。
更准确地说:
p 的值是地址,不是字符串本身。*p 才是这个地址处的第一个字符:
*p == 'g'容易踩坑点:
- 指针变量里存的是地址,不是整段字符串内容。
判断题第 6 题
Section titled “判断题第 6 题”题目整理:
int a[3][4] = {{1}, {5}, {9}};题目说:它的作用是将数组各行第一列的元素赋初值,其余元素值为 0。
答案:Y
详细解析:
初始化结果是:
1 0 0 05 0 0 09 0 0 0每个内部花括号只给该行第一个元素赋值,其余自动补 0。
容易踩坑点:
- 忘记部分初始化时其余元素会自动补
0。
判断题第 7 题
Section titled “判断题第 7 题”题目:若 a = 3, b = 2, c = 1,则关系表达式 (a>b)==c 的值为真,即为 1。
答案:Y
详细解析:
先算:
a > b -> 3 > 2 -> 1再算:
1 == c -> 1 == 1 -> 1所以为真。
容易踩坑点:
- 关系表达式成立时值为
1,不成立时值为0。
判断题第 8 题
Section titled “判断题第 8 题”题目整理:
#define S(a,b) t=a; a=b; b=t题目说:由于变量 t 没定义,所以此宏定义是错误的。
答案:N
详细解析:
宏定义本身只是文本替换,不要求在宏定义处就已经定义 t。
只要使用宏时当前作用域里有 t,就可能通过。
例如:
int a = 1, b = 2, t;S(a, b);不过这个宏写法并不安全,真实代码中不推荐这样写。
容易踩坑点:
- 把宏当成普通函数。宏更像预处理阶段的文本替换。
判断题第 9 题
Section titled “判断题第 9 题”题目:结构体类型只有一种。
答案:N
详细解析:
程序里可以定义很多种结构体类型。
例如:
struct Date{ int year; int month; int day;};
struct Student{ char name[20]; int age;};这就是两个不同的结构体类型。
容易踩坑点:
- 把“结构体这种语法形式”误解成“结构体类型只能有一个”。
判断题第 10 题
Section titled “判断题第 10 题”题目:
char c[] = "Very Good";题目说这是一个合法的为字符数组赋值的语句。
答案:Y
详细解析:
这是一条字符数组初始化语句,合法。
编译器会自动根据字符串长度分配空间:
V e r y 空格 G o o d \0容易踩坑点:
- 定义时可以用字符串初始化字符数组;定义之后不能用数组名整体赋值。
5. 改错题详解
Section titled “5. 改错题详解”改错题 1:提取长整数中的偶数字位
Section titled “改错题 1:提取长整数中的偶数字位”题目功能:将长整型数中每一位上为偶数的数字取出,构成一个新的数。高位仍在高位,低位仍在低位。
例如:
s = 87654t = 864原题主要错误点:
if (d % 2 = 0)错,判断相等要写==。*t = d * s1 + t;错,t是指针地址,应使用*t取得结果变量的值。S /= 10;错,C 语言大小写敏感,应该更新小写变量s。
完整修正代码:
#include <stdio.h>
void fun(long s, long *t){ int d; long s1 = 1;
*t = 0;
while (s > 0) { d = s % 10;
if (d % 2 == 0) { *t = d * s1 + *t; s1 *= 10; }
s /= 10; }}
int main(void){ long s, t;
printf("Please enter s: "); scanf("%ld", &s);
fun(s, &t); printf("The result is: %ld\n", t);
return 0;}过程解释:
以 87654 为例,从低位开始取:
| s 当前值 | d = s % 10 | 是否偶数 | 新 t | s1 |
|---|---|---|---|---|
| 87654 | 4 | 是 | 4 | 10 |
| 8765 | 5 | 否 | 4 | 10 |
| 876 | 6 | 是 | 64 | 100 |
| 87 | 7 | 否 | 64 | 100 |
| 8 | 8 | 是 | 864 | 1000 |
最终得到:
864为什么要用 s1:
每找到一个偶数字位,就要把它放到当前结果的更高一位,所以 s1 从 1、10、100 这样逐步变大。
容易踩坑点:
=是赋值,==才是判断相等。t是指针,*t才是它指向的那个变量。- C 语言区分大小写,
S和s是两个不同标识符。
给新手的建议:
- 指针改错题先问自己:这里要操作“地址”还是“地址里的值”?如果要改外面的变量,就通常要写
*t。
改错题 2:按 ASCII 值合并两个字符串
Section titled “改错题 2:按 ASCII 值合并两个字符串”题目功能:逐个比较 a、b 两个字符串对应位置中的字符,把 ASCII 值大或相等的字符依次存放到 c 数组中,形成一个新字符串。
例如:
a = "aBCDeFgH"b = "ABcd"c = "aBcdeFgH"原题主要错误点:
k=1;错,应从c[0]开始存,所以k=0;。while(*p!=*q)错,不能只在两个字符不相等时循环,应在两个字符串还没都结束时循环。fun(a[10], b[10], c[10]);错,数组传参应传数组名a, b, c,不是传越界元素。
完整修正代码:
#include <stdio.h>#include <string.h>
void fun(char *p, char *q, char *c){ int k = 0;
while (*p != '\0' || *q != '\0') { if (*p < *q) c[k] = *q; else c[k] = *p;
if (*p) p++; if (*q) q++;
k++; }
c[k] = '\0';}
int main(void){ char a[10] = "aBCDeFgH"; char b[10] = "ABcd"; char c[10] = {'\0'};
fun(a, b, c);
printf("The string a: "); puts(a); printf("The string b: "); puts(b); printf("The result: "); puts(c);
return 0;}过程解释:
逐位比较:
| 位置 | a 字符 | b 字符 | 取较大者 |
|---|---|---|---|
| 0 | a | A | a |
| 1 | B | B | B |
| 2 | C | c | c |
| 3 | D | d | d |
| 4 | e | \0 | e |
| 5 | F | \0 | F |
| 6 | g | \0 | g |
| 7 | H | \0 | H |
所以结果是:
aBcdeFgH为什么循环条件是 ||:
while (*p != '\0' || *q != '\0')意思是:只要两个字符串中还有一个没结束,就继续处理。
容易踩坑点:
- 数组下标从
0开始,所以k应从0开始。 - 字符串结束符是
'\0',不是字符'0'。 - 数组名传参写
fun(a, b, c),不要写a[10]。 ||是逻辑或,OCR 里容易看成II。
给新手的建议:
- 字符串处理题一定要考虑两个问题:循环什么时候结束、结果字符串最后有没有
'\0'。
6. 程序设计题详解
Section titled “6. 程序设计题详解”程序设计 1:求 3x3 矩阵主对角线元素的积
Section titled “程序设计 1:求 3x3 矩阵主对角线元素的积”题目功能:输入一个 3 行 3 列矩阵的各个元素值,然后输出主对角线元素的积,并在 fun() 函数中求出。
主对角线位置:
a[0][0]a[1][1]a[2][2]参考答案:
#include <stdio.h>
int fun(int a[3][3]){ int sum = 1; int i;
for (i = 0; i < 3; i++) sum = sum * a[i][i];
return sum;}
int main(void){ int i, j, s; int a[3][3];
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) scanf("%d", &a[i][j]);
s = fun(a); printf("sum=%d\n", s);
return 0;}示例:
输入矩阵:1 2 34 5 67 8 9主对角线是:
1, 5, 9乘积:
1 * 5 * 9 = 45关于原卷红字:
原卷红色代码里能看到类似:
sum = sum * a[i][j];但 fun() 函数里只控制了 i,并没有正确控制 j;而且题目明确要求“主对角线元素的积”,所以正确写法应是:
sum = sum * a[i][i];容易踩坑点:
- 主对角线不是每一行所有元素,而是行下标和列下标相等的元素。
- 求乘积时初值应为
1,不是0。如果初值为0,乘出来永远是0。 - 输入二维数组元素时要写
&a[i][j]。
给新手的建议:
- 矩阵题先画表,主对角线就是左上到右下那条线。
程序设计 2:计算 1 + 12 + 123 + … 的前 n 项和
Section titled “程序设计 2:计算 1 + 12 + 123 + … 的前 n 项和”题目功能:计算并输出:
1 + 12 + 123 + 1234 + ...的前 n 项和,其中 0 < n < 10,n 从键盘输入。
例如:
n = 3sum = 1 + 12 + 123 = 136参考答案:
#include <stdio.h>
long sum(int n){ int i; long k, sum;
sum = 0; k = 0;
for (i = 1; i <= n; i++) { k = 10 * k + i; sum += k; }
return sum;}
int main(void){ int n;
printf("Input n: "); scanf("%d", &n); printf("sum=%ld\n", sum(n));
return 0;}过程解释:
变量 k 表示当前项:
| i | k = 10 * k + i | 当前项 k | sum |
|---|---|---|---|
| 1 | 10*0+1 | 1 | 1 |
| 2 | 10*1+2 | 12 | 13 |
| 3 | 10*12+3 | 123 | 136 |
| 4 | 10*123+4 | 1234 | 1370 |
如果 n = 6:
1 + 12 + 123 + 1234 + 12345 + 123456 = 137171容易踩坑点:
k和sum不是同一个变量。k是当前项,sum是累计和。- 每一项不是简单的
i,而是上一项乘 10 再加当前数字。 %ld用来输出long类型。
给新手的建议:
- 这种“1、12、123”题目固定套路是:
k = k * 10 + i。
7. 本卷复盘建议
Section titled “7. 本卷复盘建议”这套卷最容易丢分的点集中在数组、字符串和函数调用上。建议你复盘时重点抓住下面这些:
- 有返回值的函数调用可以当表达式、实参或独立语句,但不能当形参。
- 数组部分初始化时,没写到的元素补
0。 - 字符串结尾是
'\0',不是'0'。 - 数组名传参传的是首地址,函数里可能修改原数组元素。
- 二维数组第二维不能省略。
- 字符数组不一定是字符串,能作为字符串使用必须有
'\0'。 void函数没有返回值,不能放进需要值的表达式中。- 字符串连接用
strcat,字符串复制用strcpy,字符串比较用strcmp。 - 判断相等用
==,赋值用=。 - 指针变量保存地址,
*p才表示地址里的值。
如果只练三类题,建议优先练:
- 字符数组和字符串结束符题。
- 二维数组下标、初始化和主对角线题。
- 函数调用、返回值、
static局部变量和指针传参题。