exam-88 试卷整理与详解
这份笔记是根据 88.pdf 整理出来的,原卷文件在本地路径:
/Users/wff/Downloads/88.pdf这套卷子和前两套一样,主要考数组、字符串、函数、指针、表达式、宏和程序改错。
需要特别注意:这套 PDF 里有几处红色标注疑似误标。我在下面的答案速查和详细解析中,按 C 语言规则给出更稳的答案,并在对应题目里说明原因。
容易被误标带偏的题:
- 选择题第 6 题:给
a[10]赋值1 ~ 10,正确应是a[i - 1] = i。 - 选择题第 8 题:如果问
a[i][j]前面的元素个数,应是i * m + j;i * m + j + 1是从 1 开始数的序号。 - 选择题第 9 题:问“字符数组长度”为 5,应选只含 5 个数组元素的写法。
- 选择题第 24 题:
static char str[10] = "China";的数组元素个数是10,不是6。 - 判断题第 8 题:
(a > b) == -c中1 == -1为假,所以应判错。
1. 答案速查
Section titled “1. 答案速查”1.1 选择题答案
Section titled “1.1 选择题答案”| 题号 | 答案 |
|---|---|
| 1 | A |
| 2 | C |
| 3 | A |
| 4 | C |
| 5 | B |
| 6 | D |
| 7 | B |
| 8 | D |
| 9 | A |
| 10 | A |
| 11 | B |
| 12 | B |
| 13 | B |
| 14 | D |
| 15 | C |
| 16 | C |
| 17 | C |
| 18 | D |
| 19 | B |
| 20 | D |
| 21 | D |
| 22 | B |
| 23 | C |
| 24 | C |
| 25 | C |
1.2 填空题答案
Section titled “1.2 填空题答案”| 题号 | 答案 |
|---|---|
| 1 | 6 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | *pmax = *px |
| 6 | 10 |
| 7 | 5 |
| 8 | 246 |
| 9 | 1 |
| 10 | main 或 主 |
1.3 判断题答案
Section titled “1.3 判断题答案”| 题号 | 答案 |
|---|---|
| 1 | N |
| 2 | N |
| 3 | Y |
| 4 | N |
| 5 | N |
| 6 | N |
| 7 | N |
| 8 | N |
| 9 | Y |
| 10 | N |
2. 选择题详解
Section titled “2. 选择题详解”选择题第 1 题
Section titled “选择题第 1 题”题目整理:
func((e1, e2), (e3, e4, e5));问:实参个数是多少?
答案:A
详细解析:
函数调用最外层只有两个实参:
(e1, e2)(e3, e4, e5)括号里的逗号是逗号表达式,不是函数参数分隔符。
所以实参个数是 2。
容易踩坑点:
- 看到逗号就直接数,结果把括号里的逗号也算进去了。
给新手的建议:
- 数函数实参个数,只看最外层逗号。
选择题第 2 题
Section titled “选择题第 2 题”题目问:下列对字符数组的初始化不正确的是哪一个?
答案:C
错误写法:
char s[5] = "abcde";详细解析:
字符串 "abcde" 有 5 个可见字符,但字符串末尾还需要 '\0'。
所以至少要 6 个字符空间:
char s[6] = "abcde";char s[] = "abcde";补充说明:
在更严格地讨论 C 标准时,char s[5] = "abcde"; 可以被看成只存 5 个字符、不存 '\0' 的字符数组。但这类入门考试通常按“字符串必须有结束符”来判,因此选 C。
容易踩坑点:
- 只数可见字符,忘记字符串结束符。
给新手的建议:
- 如果用字符串常量初始化字符数组,数组长度最好留出
'\0'的位置。
选择题第 3 题
Section titled “选择题第 3 题”题目整理:
func(rec1, rec2 + rec3, (rec4, rec5));问:实参个数是多少?
答案:A
详细解析:
最外层参数有三个:
rec1rec2 + rec3(rec4, rec5)所以实参个数是 3。
容易踩坑点:
- 把
(rec4, rec5)里的逗号也当成参数分隔符。
给新手的建议:
- 遇到函数参数题,先用括号层级把最外层参数圈出来。
选择题第 4 题
Section titled “选择题第 4 题”题目问:数组名作为实参传递给函数时,被处理为什么?
答案:C
详细解析:
数组名作为函数实参时,通常会转换为数组首元素地址。
例如:
int a[10];fun(a);这里传给函数的不是整个数组的副本,而是 &a[0]。
容易踩坑点:
- 以为数组名传参会把数组所有元素都复制一份。
给新手的建议:
- 数组名作参数,先理解成“把首地址传过去”。
选择题第 5 题
Section titled “选择题第 5 题”题目整理:
int a[10];问:对数组元素的正确引用是哪一个?
答案:B
正确写法:
a[10 - 10]详细解析:
a[10 - 10] 等价于:
a[0]这是合法下标。
数组 a[10] 的合法下标是:
0 1 2 3 4 5 6 7 8 9所以 a[10] 越界。
补充说明:
a[3,5] 在 C 语言里会被解释成 a[(3,5)],也就是 a[5]。但这种写法非常容易误导人,入门考试一般不会把它当成规范答案。
容易踩坑点:
- 数组长度是 10,不代表最大下标是 10。
给新手的建议:
- 数组最后一个下标永远是“长度 - 1”。
选择题第 6 题
Section titled “选择题第 6 题”题目问:给数组 a[10] 赋值为 1, 2, 3 ... 的语句是哪一个?
答案:D
正确写法:
for (i = 1; i < 11; i++) a[i - 1] = i;详细解析:
循环中 i 从 1 到 10,数组下标要从 0 到 9,所以应该写:
i = 1 -> a[0] = 1i = 2 -> a[1] = 2...i = 10 -> a[9] = 10卷面红字疑似误标为 C:
for (i = 1; i < 11; i++) a[i + 1] = i;这个写法会访问 a[11],明显越界,不能作为正确答案。
容易踩坑点:
- 忘记数组下标从
0开始。 - 循环变量从
1开始时,没有把下标减1。
给新手的建议:
- 如果值从
1开始,但下标从0开始,常见写法就是a[i - 1] = i。
选择题第 7 题
Section titled “选择题第 7 题”题目问:错误的定义语句是哪一个?
答案:B
错误写法:
int n = 5, a[n];详细解析:
按传统 C 语言教材和这类考试的口径,数组长度应使用常量表达式。
n 是变量,不是常量表达式,所以这题判错。
补充说明:
一些现代 C 编译器支持变长数组,也就是 VLA。但考试题通常按教材标准来答。
容易踩坑点:
- 把“某些编译器能运行”和“考试标准答案”混在一起。
给新手的建议:
- 做教材题时,数组长度先按常量表达式来判断。
选择题第 8 题
Section titled “选择题第 8 题”题目问:二维数组 a[i][j] 前的元素个数是多少?
答案:D
公式:
i * m + j详细解析:
假设二维数组每行有 m 个元素,C 语言按行优先存储。
a[i][j] 前面有:
前 i 行的元素个数:i * m当前第 i 行里,a[i][j] 前面的元素个数:j合起来就是:
i * m + j补充说明:
如果问的是“a[i][j] 是从 1 开始数的第几个元素”,那才是:
i * m + j + 1但本题问的是“前的元素个数”,所以应选 D。
容易踩坑点:
- 把“前面有几个元素”和“它是第几个元素”混在一起。
给新手的建议:
- 二维数组下标从
0开始,位置题一定先画一行一行的内存顺序。
选择题第 9 题
Section titled “选择题第 9 题”题目问:字符数组长度为 5 的是哪一个?
答案:A
正确写法:
char a[] = {'h', 'a', 'b', 'c', 'd'};详细解析:
这个数组里正好有 5 个字符元素,所以数组长度为 5。
注意:
char b[] = {'h', 'a', 'b', 'c', 'd', '\0'};这个数组长度是 6,只是它表示的字符串长度是 5。
容易踩坑点:
- 把“字符数组长度”和“字符串长度”混淆。
给新手的建议:
- 数组长度看数组里有几个元素。
- 字符串长度看
'\0'前面有几个有效字符。
选择题第 10 题
Section titled “选择题第 10 题”题目问:下列字符数组长度为 5 的是哪一个?
答案:A
正确写法:
char a[] = {'h', 'a', 'b', 'c', 'd'};详细解析:
数组长度由初始化列表中的元素个数决定,这里正好是 5 个。
容易踩坑点:
- 看到字符数组就自动当成字符串。
给新手的建议:
- 用
{}初始化字符数组时,里面写了几个字符,数组就有几个元素。
选择题第 11 题
Section titled “选择题第 11 题”题目整理:
int x[10] = {0, 2, 4};已知 int 类型占 2 个字节,问数组 x 占多少字节?
答案:B
详细解析:
数组有 10 个 int 元素,每个元素 2 字节:
10 * 2 = 20所以占 20 字节。
容易踩坑点:
- 只看初始化了 3 个元素,就以为数组长度是 3。
给新手的建议:
- 数组占用空间看定义长度,不看写了几个初值。
选择题第 12 题
Section titled “选择题第 12 题”题目整理:
char a[10];问:以下语句中不能从键盘给 a 数组所有元素输入值的是哪一个?
答案:B
错误写法:
a = getchar();详细解析:
a 是数组名,数组名不能作为赋值号左边整体赋值。
而且 getchar() 只读取一个字符,不可能直接给整个字符数组赋值。
容易踩坑点:
- 把字符数组当成一个普通字符变量。
给新手的建议:
char a[10]是数组;如果逐个输入,要写a[i] = getchar()。
选择题第 13 题
Section titled “选择题第 13 题”题目问:以下能正确定义数组并正确赋初值的是哪一个?
答案:B
正确写法:
int d[3][2] = {{1, 2}, {34}};详细解析:
这个二维数组有 3 行 2 列。
初始化后可理解为:
1 234 00 0没写到的元素会自动补 0。
其他选项的问题:
int N = 5, b[N][N];按传统教材环境,数组长度不能用变量。int c[2][]第二维省略,错误。int a[1][2] = {{1}, {3}};只有 1 行,却给了 2 行初值。
容易踩坑点:
- 二维数组第二维不能省略。
- 少写初值可以补 0,多写行数就不行。
给新手的建议:
- 二维数组初始化先看“行数有没有超、列数有没有明确”。
选择题第 14 题
Section titled “选择题第 14 题”题目问:以下能对二维数组 a 进行正确初始化的是哪一个?
答案:D
按原图题意,D 应理解为:
int a[][3] = {{1, 2, 3}, {4, 5, 6}};详细解析:
二维数组初始化时,第一维可以省略,第二维必须写出来。
这里第二维是 3,初值共有 2 行,所以编译器可以推出第一维是 2。
容易踩坑点:
- OCR 可能把
a[][3]识别成a[1][3]。 - 第一维可省略,第二维不能省略。
给新手的建议:
- 看到二维数组初始化,先盯住第二个
[]里面有没有数字。
选择题第 15 题
Section titled “选择题第 15 题”题目整理:
char str[13];scanf("%s", str);printf("%s\n", str);输入:
abcd1234 efgh答案:C
详细解析:
scanf("%s", str) 读取字符串时,遇到空白字符就停止。
所以它只读入:
abcd1234空格后面的 efgh 不会作为这次 %s 的内容。
容易踩坑点:
- 以为
%s会把整行都读进去。
给新手的建议:
scanf("%s")读到空格就停;想读一整行要用其他方法。
选择题第 16 题
Section titled “选择题第 16 题”题目问:下面叙述中错误的是哪一个?
答案:C
错误说法:
无 return 语句的函数不返回值详细解析:
函数有没有返回值,主要看函数定义时的返回类型。
例如:
int fun(void){ printf("hello\n");}这个函数声明自己返回 int,但函数体里没有 return,这不是“它不返回值”,而是写法有问题。
真正无返回值的函数应写成:
void fun(void){ printf("hello\n");}容易踩坑点:
- 只看有没有
return,不看函数名前面的返回类型。
给新手的建议:
- 判断函数返回值,先看函数名前面的类型。
选择题第 17 题
Section titled “选择题第 17 题”题目整理:
char s[12] = "a book!";printf("%d", strlen(s));答案:C
详细解析:
字符串 "a book!" 的有效字符是:
a空格b o o k!一共 7 个字符。
strlen 统计字符串长度,不包含 '\0'。
容易踩坑点:
- 把数组空间
12当成字符串长度。
给新手的建议:
sizeof看空间大小,strlen看字符串有效长度。
选择题第 18 题
Section titled “选择题第 18 题”题目问:调用函数时,实参是数组名,则向函数传送的是什么?
答案:D
详细解析:
数组名作为实参时,传递的是数组首地址,也就是首元素地址。
例如:
int a[10];fun(a);传过去的可以理解为:
&a[0]容易踩坑点:
- 以为传的是整个数组所有元素的值。
给新手的建议:
- 数组传参和普通变量传参不一样,数组名传的是地址。
选择题第 19 题
Section titled “选择题第 19 题”题目整理:
int a[3][4] = {0};答案:B
详细解析:
= {0} 会让整个二维数组所有元素初始化为 0。
可以理解成:
0 0 0 00 0 0 00 0 0 0容易踩坑点:
- 以为只有
a[0][0]是 0。
给新手的建议:
- 数组初始化中,
{0}是常见的全 0 初始化写法。
选择题第 20 题
Section titled “选择题第 20 题”题目整理:
int a = 1, b = 2, c = 3, d = 4, e = 5;printf("%d\n", func((a + b, b + c, c + a), (d + e)));
int func(int x, int y){ return x + y;}答案:D
详细解析:
第一个实参是逗号表达式:
(a + b, b + c, c + a)逗号表达式的值看最后一个表达式:
c + a = 3 + 1 = 4第二个实参:
d + e = 4 + 5 = 9所以:
func(4, 9) = 13容易踩坑点:
- 把逗号表达式里的三个值加起来。
给新手的建议:
- 逗号表达式记住一句话:整体值看最后一个表达式。
选择题第 21 题
Section titled “选择题第 21 题”题目整理:
int b;char c[10];问:正确的输入语句是哪一个?
答案:D
正确写法:
scanf("%d%s", &b, c);详细解析:
%d 读取整数,需要传变量地址:
&b%s 读取字符串,字符数组名 c 本身就表示首地址,不需要再写 &c。
容易踩坑点:
- 给字符数组输入字符串时多写了
&。
给新手的建议:
- 普通变量用
&变量名。 - 字符数组用数组名。
选择题第 22 题
Section titled “选择题第 22 题”题目整理:
char c[] = "abc";int i = 0;do ;while (c[i++] != '\0');printf("%d", i - 1);答案:B
详细解析:
字符串实际内容:
'a' 'b' 'c' '\0'循环检查过程:
| 次数 | 检查字符 | 检查后 i |
|---|---|---|
| 1 | c[0] | 1 |
| 2 | c[1] | 2 |
| 3 | c[2] | 3 |
| 4 | c[3] | 4 |
最后一次检查到 '\0' 时退出,但 i++ 已经执行,所以 i = 4。
输出:
i - 1 = 3容易踩坑点:
- 忘记后置自增在判断后也会执行。
给新手的建议:
i++和循环放在一起时,最好一轮一轮列出来。
选择题第 23 题
Section titled “选择题第 23 题”题目问:以下程序段中不能正确赋字符串的是哪一个?
答案:C
错误写法:
char s[10];s = "abcdefg";详细解析:
数组名不能作为赋值号左边整体赋值。
如果要给字符数组复制字符串,应写:
strcpy(s, "abcdefg");容易踩坑点:
- 把字符数组名当成普通指针变量。
给新手的建议:
- 字符数组初始化可以用
char s[10] = "abc";。 - 定义后再赋字符串,通常用
strcpy。
选择题第 24 题
Section titled “选择题第 24 题”题目整理:
static char str[10] = "China";问:数组元素个数是多少?
答案:C
详细解析:
数组元素个数由方括号里的 10 决定。
所以 str 的元素个数是:
10"China" 只占用前 6 个位置:
'C' 'h' 'i' 'n' 'a' '\0'但数组本身仍然有 10 个元素。
容易踩坑点:
- 把字符串占用空间
6当成数组元素个数。
给新手的建议:
- 题目问“数组元素个数”,优先看方括号。
选择题第 25 题
Section titled “选择题第 25 题”题目整理:
int func(int a, int b){ int c = a + b; return c;}
int x = 6, y = 7, z = 8, r;r = func((x--, y++, x + y), z--);printf("%d\n", r);答案:C
详细解析:
第一个实参:
(x--, y++, x + y)逐步看:
x--:表达式值为 6,然后 x 变成 5y++:表达式值为 7,然后 y 变成 8x + y:5 + 8 = 13所以第一个实参是 13。
第二个实参:
z--表达式值先取旧值 8,然后 z 变成 7。
所以:
func(13, 8) = 21容易踩坑点:
x--和y++的表达式值与变量最终值不同。- 逗号表达式的值看最后一个表达式。
给新手的建议:
- 这种题不要心算,按顺序写出每个变量变化。
3. 填空题详解
Section titled “3. 填空题详解”填空题第 1 题
Section titled “填空题第 1 题”题目整理:
char s[] = "china";答案:6
详细解析:
"china" 有 5 个可见字符,末尾还有一个 '\0'。
所以数组占:
5 + 1 = 6容易踩坑点:
- 忘记字符串结束符也占一个字符空间。
填空题第 2 题
Section titled “填空题第 2 题”题目整理:
int x = 2, y = 3, z = 4;x + y > !z答案:1
详细解析:
z = 4 是非 0,表示真,所以:
!z = 0再算:
x + y > !z2 + 3 > 05 > 0结果为真,即 1。
容易踩坑点:
- 把
!z当成-z。
填空题第 3 题
Section titled “填空题第 3 题”题目整理:
!(4 >= 6) && (3 <= 7)答案:1
详细解析:
4 >= 6 -> 假 -> 0!(4 >= 6) -> 真 -> 13 <= 7 -> 真 -> 11 && 1 -> 1容易踩坑点:
- 忘记
!会把真假反过来。
填空题第 4 题
Section titled “填空题第 4 题”题目整理:
func((e1, e2), (e3, e4, e5));答案:2
详细解析:
最外层只有两个实参:
(e1, e2)(e3, e4, e5)括号里的逗号属于逗号表达式。
填空题第 5 题
Section titled “填空题第 5 题”题目功能:通过指针找出 x、y、z 三个数中的最大值。
答案可写:
*pmax = *px;整理后的关键代码:
px = &x;py = &y;pz = &z;pmax = &max;
*pmax = *px;
if (*pmax < *py) *pmax = *py;if (*pmax < *pz) *pmax = *pz;详细解析:
pmax 指向 max,所以:
*pmax = *px;等价于:
max = x;先假设 x 最大,再分别和 y、z 比较。
容易踩坑点:
pmax = &max是让指针指向变量。*pmax = *px是把x的值放进max。
给新手的建议:
- 指针题先写清楚“谁指向谁”,再看
*p表示哪个变量的值。
填空题第 6 题
Section titled “填空题第 6 题”题目整理:
int a = 011;printf("%d\n", ++a);答案:10
详细解析:
在 C 语言中,以 0 开头的整数常量是八进制。
011(八进制) = 9(十进制)++a 先自增,所以:
a = 10输出 10。
容易踩坑点:
- 把
011当成十进制 11。
给新手的建议:
- 数字前面有
0,要警惕八进制。
填空题第 7 题
Section titled “填空题第 7 题”题目整理:
(k = a = 5, b = 3, a * b)问:k 的值是多少?
答案:5
详细解析:
逗号表达式从左到右执行:
k = a = 5b = 3a * b第一步已经把 k 赋值为 5。
最后的 a * b 是整个逗号表达式的值,但没有再赋给 k。
所以 k 仍然是 5。
容易踩坑点:
- 把逗号表达式最后的值
15当成k的值。
填空题第 8 题
Section titled “填空题第 8 题”题目整理:
void fun(void){ static int a = 0; a += 2; printf("%d", a);}
for (cc = 1; cc < 4; cc++) fun();答案:246
详细解析:
static int a = 0; 只初始化一次,而且函数调用结束后值不会丢失。
三次调用过程:
| 调用次数 | a 的变化 | 输出 |
|---|---|---|
| 1 | 0 -> 2 | 2 |
| 2 | 2 -> 4 | 4 |
| 3 | 4 -> 6 | 6 |
所以输出:
246容易踩坑点:
- 以为
static局部变量每次进函数都会重新变成 0。
给新手的建议:
static局部变量有“记忆能力”。
填空题第 9 题
Section titled “填空题第 9 题”题目整理:
int x = 2;z = x++ - 1;答案:1
详细解析:
x++ 是后置自增,表达式先使用旧值 2,然后 x 才变成 3。
所以:
z = 2 - 1 = 1容易踩坑点:
- 把
x++当成先加 1 再使用。
填空题第 10 题
Section titled “填空题第 10 题”题目问:一个 C 源程序中至少应包括一个什么函数?
答案:main 或 主
详细解析:
C 程序从 main 函数开始执行。
最基本结构:
int main(void){ return 0;}容易踩坑点:
main是程序入口,不是普通可有可无的函数。
4. 判断题详解
Section titled “4. 判断题详解”判断题第 1 题
Section titled “判断题第 1 题”题目:进行宏定义时,宏名必须使用大写字母表示。
答案:N
解析:
宏名常用大写是编程习惯,不是语法强制要求。
判断题第 2 题
Section titled “判断题第 2 题”题目:
7 & 8 & 3 + 12判断:值是 13。
答案:N
解析:
加法优先级高于按位与,所以先算:
3 + 12 = 15再算:
7 & 8 & 157 & 8 的结果是 0,所以整体不是 13。
易错点:位运算符优先级比加法低。
判断题第 3 题
Section titled “判断题第 3 题”题目:
int i, *p = &i;判断:这是正确的 C 说明。
答案:Y
解析:
这句定义了一个整型变量 i,又定义了一个指向 int 的指针 p,并让 p 指向 i。
判断题第 4 题
Section titled “判断题第 4 题”题目:
printf("%f%%", 1.0 / 3);判断:输出为 0.333333。
答案:N
解析:
%f 输出小数,%% 输出一个百分号。
所以实际输出类似:
0.333333%不是只有 0.333333。
判断题第 5 题
Section titled “判断题第 5 题”题目:C 语言的函数可以嵌套定义。
答案:N
解析:
标准 C 语言中,函数不能嵌套定义。
但函数可以嵌套调用,例如:
r = func(func(x, y), z);判断题第 6 题
Section titled “判断题第 6 题”题目:
strlen("ASDFG\n")判断:值是 7。
答案:N
解析:
字符串中有效字符是:
A S D F G \n一共 6 个字符。
strlen 不统计结尾的 '\0'。
判断题第 7 题
Section titled “判断题第 7 题”题目:
file *fp;fp = fopen("a.txt", "r");判断:在 Turbo C 中是合法的。
答案:N
解析:
文件指针类型应写成大写:
FILE *fp;file 不是标准写法。
判断题第 8 题
Section titled “判断题第 8 题”题目整理:
a = 3;b = 2;c = 1;(a > b) == -c判断:结果为真。
答案:N
详细解析:
先算:
a > b -> 3 > 2 -> 真 -> 1再算:
-c -> -1最后比较:
1 == -1结果是假,即 0。
卷面红字疑似误标为 Y,但按 C 语言表达式求值规则应为 N。
判断题第 9 题
Section titled “判断题第 9 题”题目:整数 -32100 可以赋值给 int 型和 long int 型变量。
答案:Y
解析:
按传统 16 位有符号 int 环境,范围是:
-32768 ~ 32767-32100 在这个范围内,所以可以赋给 int,也可以赋给 long int。
判断题第 10 题
Section titled “判断题第 10 题”题目:
#define S(a, b) t = a; a = b; b = t;判断:该宏定义用于变量 t 的定义。
答案:N
解析:
宏定义只是文本替换规则,不会定义变量 t。
如果使用这个宏时没有提前定义 t,展开后的代码会因为 t 未定义而出错。
5. 改错题详解
Section titled “5. 改错题详解”功能:输入字符序列,直到遇到 # 结束。规则是:
- 如果当前字符是数字字符,设它的面值为
n,则读入它后面的一个字符,并把这个后面的字符重复输出n + 1次。 - 如果当前字符不是数字字符,则直接输出该字符。
- 每次翻译结果之间用一个空格隔开。
整理后的正确代码:
#include <stdio.h>
int main(void){ char ch, nch; int count; int k;
printf("Enter string.\n"); scanf("%c", &ch);
while (ch != '#') { if (ch >= '0' && ch <= '9') { count = ch - '0' + 1; scanf("%c", &nch);
for (k = 0; k < count; k++) printf("%c", nch); } else { printf("%c", ch); }
printf(" "); scanf("%c", &ch); }
printf("#\n"); return 0;}三处错误说明:
第一处:
while (ch = '#')应改为:
while (ch != '#')原因:= 是赋值,!= 才是不等于。
第二处:
count = ch - '0' - 1;应改为:
count = ch - '0' + 1;原因:题目要求重复输出 n + 1 次。
第三处:
printf("%f", ch);应改为:
printf("%c", ch);原因:ch 是字符,应该用 %c 输出。
容易踩坑点:
=、==、!=三个符号容易混。- 字符数字转整数要写
ch - '0'。 - 字符输出用
%c,不是%f。
给新手的建议:
- 看到字符
'3'想变成数字3,就用'3' - '0'。
功能:求由 0 ~ 7 这 8 个数字能组成的奇数个数。
整理后的正确代码:
#include <stdio.h>
int main(void){ long sum = 4, s = 4; int j;
for (j = 2; j <= 8; j++) { printf("\n%ld", sum);
if (j <= 2) s *= 7; else s *= 8;
sum += s; }
printf("\nsum=%ld", sum); return 0;}三处错误说明:
第一处:
long sum = 4; s = 4;应改为:
long sum = 4, s = 4;原因:s 也需要声明类型。
第二处:
printf("\n%d", sum);应改为:
printf("\n%ld", sum);原因:sum 是 long 类型,应该用 %ld。
第三处:
if (j < 2)应改为:
if (j <= 2)原因:当统计两位奇数时,最高位不能是 0,可选数比后续普通位少。
容易踩坑点:
- 多个变量同类型声明时,可以用逗号连接。
long输出用%ld。- 计数题里边界条件非常容易错。
给新手的建议:
- 这类题先不要急着看代码,先想清楚“个位有几种选择、最高位有几种选择、中间位有几种选择”。
6. 程序设计题详解
Section titled “6. 程序设计题详解”程序设计 1
Section titled “程序设计 1”题目:求一批数中最大值和最小值的积。
参考答案:
#include <stdio.h>#include <stdlib.h>
#define N 30
int max_min(int a[], int n){ int i; int max = a[0]; int min = a[0];
for (i = 1; i < n; i++) { if (a[i] > max) max = a[i];
if (a[i] < min) min = a[i]; }
return max * min;}
int main(void){ int a[N], i, k;
for (i = 0; i < N; i++) a[i] = rand() % 51 + 10;
for (i = 0; i < N; i++) { printf("%5d", a[i]);
if ((i + 1) % 5 == 0) printf("\n"); }
k = max_min(a, N); printf("the result is:%d\n", k);
return 0;}详细解题过程:
第一步,先假设第一个数既是最大值,也是最小值:
int max = a[0];int min = a[0];第二步,从第二个元素开始比较:
for (i = 1; i < n; i++)第三步,遇到更大的更新 max,遇到更小的更新 min:
if (a[i] > max) max = a[i];
if (a[i] < min) min = a[i];第四步,返回乘积:
return max * min;容易踩坑点:
max和min没有先初始化。- 循环从
0开始,又重复和自己比较。 - 只求了最大值,忘记最小值。
给新手的建议:
- 最大值、最小值题的模板一定要背熟:先用第一个元素初始化,再从第二个元素开始比较。
程序设计 2
Section titled “程序设计 2”题目:输入一个字符串,把大写字母转换成小写字母,小写字母转换成大写字母,非字母字符不变,并输出。
参考答案:
#include <stdio.h>#include <string.h>
#define N 80
char *fun(char a[]){ int i;
for (i = 0; a[i] != '\0'; i++) { if (a[i] >= 'A' && a[i] <= 'Z') a[i] = a[i] + 32; else if (a[i] >= 'a' && a[i] <= 'z') a[i] = a[i] - 32; }
return a;}
int main(void){ char a[N];
if (fgets(a, N, stdin) == NULL) return 1;
a[strcspn(a, "\n")] = '\0';
fun(a); puts(a);
return 0;}详细解题过程:
第一步,遍历字符串:
for (i = 0; a[i] != '\0'; i++)第二步,判断是否是大写字母:
if (a[i] >= 'A' && a[i] <= 'Z') a[i] = a[i] + 32;大写字母和小写字母的 ASCII 码相差 32,所以大写转小写要加 32。
第三步,判断是否是小写字母:
else if (a[i] >= 'a' && a[i] <= 'z') a[i] = a[i] - 32;小写转大写要减 32。
第四步,非字母不处理,保持原样。
原卷程序中容易出错的位置:
for (i = 0; i < strlen(a); i + +)应写成:
for (i = 0; a[i] != '\0'; i++)这一句:
return a[i];也不合适,因为函数返回类型是 char *,应返回字符串首地址:
return a;容易踩坑点:
<=写成< =会变成错误语法。- 中文分号
;不能当 C 语言分号。 - 函数返回类型是
char *,不能返回单个字符。
给新手的建议:
- 字符大小写转换题,先记住 ASCII 差值
32。 - 遍历字符串最稳的条件是
a[i] != '\0'。
7. 这套卷子最容易暴露的问题
Section titled “7. 这套卷子最容易暴露的问题”这套 exam-88 很适合检查下面这些基础是否扎实:
- 函数实参个数能不能按最外层逗号数清楚。
- 字符数组长度和字符串长度能不能分清。
- 数组下标从
0开始是否真正掌握。 - 二维数组行优先存储和下标位置公式是否理解。
scanf("%s")、strlen、strcpy的基础用法是否熟。x++、x--、逗号表达式能不能按顺序手算。- 宏、位运算、文件指针这些基础概念是否会判断。
8. 给新手的复习建议
Section titled “8. 给新手的复习建议”- 把选择题第 1、3、20、25 题放在一起复习,它们都是逗号表达式。
- 把选择题第 2、9、10、17、23、24 题放在一起复习,它们都是字符数组和字符串。
- 把选择题第 5、6、8、13、14、19 题放在一起复习,它们都是数组下标和二维数组。
- 把填空题第 5 题单独画图,写清楚
px、py、pz、pmax分别指向谁。 - 程序设计题 1 要背熟“最大值最小值模板”,程序设计题 2 要背熟“遍历字符串模板”。
9. 最后总结
Section titled “9. 最后总结”第 88 套卷子的难点不在新知识,而在基础细节特别密:
- 字符串要不要
'\0' - 数组下标有没有越界
- 函数参数到底有几个
- 表达式到底先算哪一步
- 指针里
p和*p分别是什么意思
如果你能把这套卷子里“红字疑似误标”的几题也解释清楚,说明你已经不是只背答案了,而是在按 C 语言规则真正理解题目。