跳转到内容

exam-86 试卷整理与详解

这份笔记是根据 86.pdf 整理出来的,原卷文件在本地路径:

/Users/wff/Downloads/86.pdf

因为原卷是 PDF 转文字,个别符号和排版有轻微 OCR 误差,我已经按常见 C 语言考试题的写法做了必要整理。对新手来说,你可以把这篇当成:

  • 一份试卷答案
  • 一份错题整理
  • 一份考点复习笔记

这套卷子虽然是综合卷,但高频考点很集中,主要是:

  • 数组和字符串
  • 函数调用、参数传递、递归
  • 二维数组与初始化
  • 指针与数组首地址
  • 结构体、共用体、枚举、宏
  • 位运算基础
  • 文件读写基础
  • 改错题与程序设计题

如果你是刚学 C 语言的新手,做这套卷子时最容易卡住的点往往不是“不会写代码”,而是:

  • 没分清“语法是否正确”和“逻辑是否正确”
  • 一看到数组、指针、函数嵌套就容易乱
  • 忽略了字符串结尾的 '\0'
  • 对“传值”和“传地址”还不够敏感

所以这篇详解会特别强调这些点。

题号答案
1D
2C
3D
4A
5A
6A
7A
8A
9A
10B
11A
12A
13C
14D
15A
16A
17B
18D
19D
20A
21D
22B
23A
24A
25B
题号答案
1220.000000
2getchar()c >= 'a' && c <= 'z'break
332
432767
5p = a
63
70
8gae
91
100
题号答案
1Y
2N
3N
4Y
5N
6Y
7Y
8Y
9Y
10N

题目整理:

long fun(int n)
{
long s;
if (n == 1 || n == 2)
s = 2;
else
s = n - fun(n - 1);
return s;
}
printf("%ld\n", fun(3));

答案:D

详细解析:

  • fun(1) = 2
  • fun(2) = 2
  • fun(3) = 3 - fun(2) = 3 - 2 = 1

所以输出结果是:

1

容易踩坑点:

  • 把递归题看复杂了,其实这里只要一步一步往下代。
  • 题面 OCR 中有 |,但这里按题意理解就是判断 n==1n==2

给新手的建议:

  • 递归题不要硬想“整体规律”,先手算 n=1n=2n=3
  • 只要有递归,一定先找“结束条件”。

题目整理:

char array[] = "China";

问:数组 array 占多少字节?

答案:C

详细解析:

  • "China" 有 5 个字符:C h i n a
  • 字符串常量最后还有一个结束标志 '\0'

所以数组里实际存了 6 个字符:

'C' 'h' 'i' 'n' 'a' '\0'

因此占 6 个字节。

容易踩坑点:

  • 只数可见字符,忘了 '\0'

给新手的建议:

  • 只要看到字符串初始化字符数组,就先自动在脑子里补一个 '\0'

题目整理:

exec((v1, v2), (v3, v4, v5), v6);

问:实参个数是多少?

答案:D

详细解析:

最外层由逗号分隔的实参有 3 个:

  1. (v1, v2)
  2. (v3, v4, v5)
  3. v6

括号里的逗号在这里是逗号运算符,不是“再多一个参数”。

所以实参个数是 3

容易踩坑点:

  • 看到所有逗号就乱数,结果把括号里的逗号也算成参数分隔符。

给新手的建议:

  • 数函数参数时,只看最外层逗号。

题目整理:

strcat(strcpy(str1, str2), str3)

答案:A

详细解析:

先执行里面的:

strcpy(str1, str2)

作用是:把 str2 复制到 str1

然后整体变成:

strcat(str1, str3)

作用是:把 str3 拼接到 str1 后面

所以整个功能就是:

  • 先把 str2 复制到 str1
  • 再把 str3 连接到 str1 后面

容易踩坑点:

  • 不熟悉 strcpystrcat 的返回值
  • 看见函数嵌套调用就慌

给新手的建议:

  • 字符串函数题,先把内层函数翻译成中文,再看外层。

题目整理:

题面初始化列表 OCR 有轻微误差,按题意可整理为一组非 0 整数,随后用:

while (k[i])
{
if (k[i] % 2 == 0 || k[i] % 5 == 0)
count++;
i++;
}

答案:A

详细解析:

这题的关键不是每个数字本身,而是两个统计量:

  • i:最后统计了多少个非 0 元素
  • count:其中多少个数能被 2 或 5 整除

按题面整理,这组数据共有 10 个非 0 元素,其中有 8 个满足条件。

所以输出:

8,10

容易踩坑点:

  • 忽略了 while(k[i]) 是“遇到 0 就停”
  • 把“能被 2 或 5 整除”错看成“同时被 2 和 5 整除”

给新手的建议:

  • 遇到这种统计题,最好手工列两列:一列记 i,一列记 count

题目整理:

int a[3][4];

问:哪个引用非法?

答案:A

详细解析:

二维数组 a[3][4] 表示:

  • 第一维下标:0 ~ 2
  • 第二维下标:0 ~ 3

所以:

  • a[0][4] 非法,因为第 2 维最大只能到 3
  • 其他几个都合法

容易踩坑点:

  • 只看见 [4] 就以为下标能到 4

给新手的建议:

  • 数组长度是 4,不代表最后一个下标是 4,最后一个下标是 4 - 1 = 3

问:下面说明不正确的是哪一个?

答案:A

详细解析:

A 类似于:

char a[10], *p;
p = a = "china";

这是错误的,因为:

  • 数组名 a 不是普通变量
  • 数组名不能作为赋值号左边

也就是说:

a = "china";

就是错的。

容易踩坑点:

  • 把数组名当成普通指针变量

给新手的建议:

  • 数组名可以“当地址用”,但它本身不是你能随便重新赋值的变量

题目整理:

int a[3][4] = {0};

答案:A

详细解析:

这种写法表示:

  • 第一个元素初始化为 0
  • 剩余元素自动补 0

所以整个二维数组的所有元素都变成 0。

容易踩坑点:

  • 以为只有 a[0][0] 是 0

给新手的建议:

  • = {0} 是数组初始化里非常常见的一种“全 0 初始化”写法

题目整理:

char c[] = "abc";
int i = 0;
do
;
while (c[i++] != '\0');
printf("%d", i - 1);

答案:A

详细解析:

字符串 "abc" 在内存里其实是:

'a' 'b' 'c' '\0'

循环检查过程:

  • 第 1 次:c[0] = 'a',不是 '\0'i 变成 1
  • 第 2 次:c[1] = 'b',不是 '\0'i 变成 2
  • 第 3 次:c[2] = 'c',不是 '\0'i 变成 3
  • 第 4 次:c[3] = '\0',条件不成立,但 i++ 已经执行,所以 i 变成 4

最后输出 i - 1 = 3

容易踩坑点:

  • 忘记 i++ 是后置自增
  • 忘记最后一次判断时虽然退出了,但 i 已经加了 1

给新手的建议:

  • 遇到 i++ 和循环一起出现时,最好一轮一轮手算

答案:B

详细解析:

B 类似于:

int y[5] = {0, 1, 3, 5, 7, 9};

数组长度是 5,但给了 6 个初值,所以错误。

容易踩坑点:

  • OCR 会把字符常量、十六进制转义写得有点乱,看花眼

给新手的建议:

  • 这种题先数“数组长度”和“初始化元素个数”是否匹配

题目整理:

int x[10] = {0, 2, 4};

已知 int 占 2 个字节,问数组 x 占多少字节?

答案:A

详细解析:

  • 数组有 10 个元素
  • 每个 int 2 字节

所以总共:

10 × 2 = 20

容易踩坑点:

  • 只看初始化了 3 个元素,就误以为数组长度是 3

给新手的建议:

  • 数组总空间看定义的长度,不看你写了几个初值

题目整理:

已定义:

char a[10];

问:哪句不能从键盘上给 a 数组的所有元素输入值?

答案:A

详细解析:

A 类似:

a = getchar();

这显然不对,因为:

  • a 是数组名
  • 数组名不能整体赋值
  • getchar() 只读一个字符,也不可能给整个数组赋值

容易踩坑点:

  • 把字符数组和字符变量混成一回事

给新手的建议:

  • char a[10] 是一个字符数组,不是一个单独字符

题目整理:

char s[12] = "a book!";
printf("%d", strlen(s));

答案:C

详细解析:

字符串 "a book!" 的长度是:

  • a 1
  • 空格 1
  • book 4
  • ! 1

总共 7

strlen() 统计的是字符串长度,不包括 '\0'

容易踩坑点:

  • 把数组长度 12 当成字符串长度
  • '\0' 也算进 strlen

给新手的建议:

  • sizeof 看空间
  • strlen 看字符串实际长度

答案:D

详细解析:

传统 C 语言教材和考试里,一维数组定义时方括号里应写“常量表达式”:

int a[10];

所以答案是:

[常量表达式]

容易踩坑点:

  • 现代编译器里有些支持 VLA(变长数组),但教材题不按这个考

给新手的建议:

  • 做考试题时,优先按教材语法标准来答

答案:A

详细解析:

二维数组定义时,除了第一维可以省略,后面的维数通常不能省略。

所以:

int a[2][];

是错误的。

而:

int a[][2] = {1, 2, 3, 4};

是对的,因为第一维可以由初始化个数推断出来。

容易踩坑点:

  • 不知道“第一维可以省略,第二维不能省略”这个规则

给新手的建议:

  • 二维数组初始化题,先盯住“列数是否明确”

答案:A

详细解析:

void 类型函数没有返回值,所以不能把它当成一个有值的表达式来用。

比如:

int x = fun();

如果 funvoid 函数,就不行。

但把它单独当一条语句调用:

fun();

是可以的。

容易踩坑点:

  • 把“能调用”误以为“能当表达式”

给新手的建议:

  • 一看到 void,就先提醒自己:它不返回结果

题目整理:

int a[][3] = {1, 2, 3, 4, 5, 6, 7};

问:数组第一维大小是多少?

答案:B

详细解析:

每一行 3 个元素。

把 7 个初值按每行 3 个分组:

  • 第 1 行:1, 2, 3
  • 第 2 行:4, 5, 6
  • 第 3 行:7, 0, 0

所以总共是 3 行。

第一维大小就是 3

容易踩坑点:

  • 以为 7 个元素就要 7 行

给新手的建议:

  • 二维数组省略第一维时,先按“每行多少个”分组

答案:D

详细解析:

长度为 5 的字符数组,最直接的就是:

char a[] = {'h', 'a', 'b', 'c', 'd'};

这里只有 5 个元素,所以数组长度就是 5。

其他选项要么显式给了更大长度,要么因为含有 '\0' 变成 6 个元素。

容易踩坑点:

  • 把“字符个数”和“数组长度”混淆

给新手的建议:

  • 题目问数组长度,就数元素个数,不要先脑补成字符串

答案:D

详细解析:

函数 max(x, y) 返回较大值。

调用:

max(45, 27)

结果自然是 45

容易踩坑点:

  • 这题本身不难,但要先忽略 OCR 里的标点小错误

给新手的建议:

  • 题目排版有点乱时,先提炼“核心逻辑”

答案:A

详细解析:

int a[][3] = {1, 2, 3, 4, 5};

这是合法的。

它会按每行 3 个元素去填:

  • 第 1 行:1, 2, 3
  • 第 2 行:4, 5, 0

而:

  • B 初值太多
  • C 两维都省略,错误
  • D 第二维省略,错误

容易踩坑点:

  • 以为少写几个初值就不合法

给新手的建议:

  • 数组初始化时,少写可以自动补 0,多写才是大问题

答案:D

详细解析:

题目要“输出前 5 个字符”。

最直接的写法就是:

printf("%.5s", a);

%.5s 表示:

  • 按字符串输出
  • 最多输出 5 个字符

容易踩坑点:

  • puts(a) 会把整个字符串都输出
  • printf("%s", a) 也是整个输出

给新手的建议:

  • printf 的格式控制里,.5 这种精度写法要熟悉

答案:B

详细解析:

函数:

void fun(int a, int b, int c)
{
a = 456;
b = 567;
c = 678;
}

调用时:

fun(x, y, z);

这是值传递,所以函数里改的是副本,不是原变量。

因此 xyz 还是原来的:

10,20,30

容易踩坑点:

  • 以为函数里改了参数,外面变量也会跟着变

给新手的建议:

  • 只要不是传地址,就默认“外面不会被直接改到”

答案:A

详细解析:

A

int n = 5, a[n];

按传统教材和这类考试标准来看,数组长度应是常量表达式,所以这里视为错误。

补充说明:

  • 在一些较新的 C 标准和部分编译器里,变长数组(VLA)是允许的
  • 但这类教材题一般按“数组长度必须是常量表达式”来判

容易踩坑点:

  • 把“现代编译器能跑”和“教材标准答案”混为一谈

给新手的建议:

  • 做卷子时,先按老师和教材讲的版本答题

题目整理:

static char str[10] = "China";

问:数组元素个数为多少?

答案:A

详细解析:

这里数组长度在定义时已经写死为 10,所以元素个数就是 10

字符串 "China" 只占用前 6 个位置:

'C' 'h' 'i' 'n' 'a' '\0'

剩下的位置自动补 0

容易踩坑点:

  • 只数 "China" 的字符个数

给新手的建议:

  • 只要数组长度显式给出,就以定义长度为准

答案:B

详细解析:

先看:

for(i = 0; i < 10; i++) a[i] = i;

所以数组 a 变成:

a = {0,1,2,3,4,5,6,7,8,9}

再看:

for(i = 0; i < 3; i++) p[i] = a[i * (i + 1)];

逐个算:

  • i=0p[0] = a[0] = 0
  • i=1p[1] = a[2] = 2
  • i=2p[2] = a[6] = 6

所以:

p = {0, 2, 6}

最后:

k = 5;
k += p[0] * 2; // +0
k += p[1] * 2; // +4
k += p[2] * 2; // +12

所以:

k = 5 + 0 + 4 + 12 = 21

答案是 B

容易踩坑点:

  • 没先把数组真正写出来
  • i*(i+1) 心算出错

给新手的建议:

  • 这种题一定要把 ap 的每个元素列出来,别硬算

题目整理:

char c;
int n = 100;
float f = 10;
double x;
x = f *= n /= (c = 50);
printf("%d%f\n", n, x);

答案:220.000000

详细解析:

先算最右边:

c = 50

然后:

n /= 50

因为 n = 100,所以:

n = 2

接着:

f *= n

此时 f = 10n = 2,所以:

f = 20

最后:

x = 20

所以输出:

220.000000

容易踩坑点:

  • 没看出复合赋值是从右往左结合
  • 忘了 printf("%d%f") 中间没有空格

给新手的建议:

  • 一看到一长串赋值,先拆成三步四步来算

答案:

c = getchar();
if (c >= 'a' && c <= 'z')
putchar(c - 'a' + 'A');
else
break;

详细解析:

这题功能是:

  • 一直输入字符
  • 如果是小写字母,就转成大写输出
  • 如果不是小写字母,就结束

核心判断条件就是:

c >= 'a' && c <= 'z'

容易踩坑点:

  • 忘了用 &&
  • 条件写反
  • 写成一个不完整区间判断

给新手的建议:

  • 判断字母范围时,直接写成“下限 <= 字符 <= 上限”的拆开版

题目整理:

x = (i = 4, j = 6, k = 32);

答案:32

详细解析:

逗号表达式的值是最后一个表达式的值。

所以:

(i = 4, j = 6, k = 32)

整体值就是 32

因此:

x = 32;

容易踩坑点:

  • 以为会把三个值加起来

给新手的建议:

  • 逗号表达式就记一句:值看最后一个

答案:32767

详细解析:

按传统 16 位 int 的教材环境,最大 int 是:

32767

补充提醒:

  • 现代大多数电脑上,int 常常是 4 字节,最大值一般是 2147483647
  • 但考试题要按题目和教材背景来答

给新手的建议:

  • 只要题目是老教材环境,像 Turbo C、16 位 int 这种背景就要跟着题目走

答案:p = a

详细解析:

数组名 a 在很多表达式中可看成首元素地址,所以:

p = a;

就等价于:

p = &a[0];

容易踩坑点:

  • 以为一定要写 &a

给新手的建议:

  • 一维数组首地址最常见两种写法:a&a[0]

题目整理:

n = i = 2, ++i, i++;

答案:3

详细解析:

按逗号表达式来看:

  1. n = i = 2
  2. ++ii 变成 3
  3. i++ 的表达式值是 3,然后 i 才变成 4

整个表达式的值取最后一个子表达式的值,也就是 3

容易踩坑点:

  • 把最终值错看成 4

给新手的建议:

  • i++ 的“返回值”和“变量最终值”不是一回事

题目整理:

int x, y = 4, z = 2;
x = y == z;

答案:0

详细解析:

先算:

y == z

也就是:

4 == 2

结果是假,即 0

所以:

x = 0;

容易踩坑点:

  • 误以为是 x = y

给新手的建议:

  • 比较运算 == 的结果只有 0 或 1

答案:gae

详细解析:

程序比较两个字符串同一位置上的字符,如果相同就输出。

Language
Programe

同位置相同的字符是:

  • g
  • a
  • e

所以输出:

gae

容易踩坑点:

  • 没看出是在“同一位置比较”

给新手的建议:

  • 字符串比较题,最稳的办法是把下标和字符一个一个对齐写出来

答案:1

详细解析:

题面 OCR 有轻微误差,按常见写法可理解为:

x = 2 && 2 || 15 > 1;

先算:

  • 2 && 2 为真,结果 1
  • 15 > 1 为真,结果 1
  • 1 || 1 结果还是 1

所以 x = 1

容易踩坑点:

  • 对逻辑运算优先级不熟

给新手的建议:

  • 逻辑题不会时就手动加括号

答案:0

详细解析:

C 语言数组下标从 0 开始。

例如:

int a[5];

合法下标是:

0 1 2 3 4

给新手的建议:

  • “数组下标从 0 开始”是 C 语言最基础也最容易反复出错的点之一

题目:共用体变量所占内存长度等于最长成员长度。

答案:Y

解析:

按教材和考试标准,这样判断是对的。共用体各成员共用同一块存储空间,所以空间大小通常按最长成员来确定。

容易踩坑点:

  • 标准实现里还可能受对齐影响,但考试一般不深究

新手建议:

  • 做卷子按教材口径答:结构体“各成员分开存”,共用体“共用一块存”

题目:宏定义 #define S(a,b) t=a; a=b; b=t 因为 t 未定义,所以宏定义错误。

答案:N

解析:

宏定义本身只是替换规则,不会在定义时检查 t 是否定义。

所以“宏定义本身错误”这个说法不对。

但真正使用时,如果展开后 t 没定义,程序当然会出错。

题目:宏名必须使用大写字母表示。

答案:N

解析:

大写只是习惯,不是语法强制要求。

题目:在 Turbo C 中,long int 占 4 个字节。

答案:Y

解析:

按传统 Turbo C 环境,这是正确的。

题目:char array[] = "hello"; 数组占 5 个字节。

答案:N

解析:

还要加结尾的 '\0',所以是 6 个字节。

题目:被调用函数定义在主调函数之前时,可以不声明。

答案:Y

解析:

如果函数定义已经出现在前面,那么编译器已经知道它了,就不必再额外声明。

题目:

int a[3][3] = {{3,5},{8,9},{12,35}}, i, sum = 0;
for(i = 0; i < 3; i++) sum += a[i][2 - i];

判断 sum == 21

答案:Y

解析:

数组补全后:

{3, 5, 0}
{8, 9, 0}
{12, 35, 0}

求的是:

  • a[0][2] = 0
  • a[1][1] = 9
  • a[2][0] = 12

和为:

0 + 9 + 12 = 21

题目:整数 -32100 可以赋给 intlong int

答案:Y

解析:

在 16 位有符号 int 环境下,范围是 -32768 ~ 32767,所以 -32100 能放下。

题目:a = (b = 4) + (c = 6) 是合法赋值表达式。

答案:Y

解析:

赋值表达式本身有值,所以当然可以参与更大的表达式。

题目:有调用关系的所有函数必须放在同一个源程序文件中。

答案:N

解析:

函数可以分布在多个源文件中,只要声明和链接正确就行。

功能:输入 10 个学生成绩,求最高分、最低分、平均分。

题目给出的 3 处错误分别是:

  1. 数组长度写成了 8,应该是 10
  2. scanf("%f", a); 应该改成 scanf("%f", &a[i]);
  3. 最小值判断方向写反了

我给你一份整理后的完整正确代码:

#include <stdio.h>
int main(void)
{
int i;
float a[10], min, max, avg;
printf("input 10 score:\n");
for (i = 0; i < 10; i++)
{
printf("input a score of student: ");
scanf("%f", &a[i]);
}
max = min = avg = a[0];
for (i = 1; i < 10; i++)
{
if (min > a[i])
min = a[i];
if (max < a[i])
max = a[i];
avg += a[i];
}
avg /= 10;
printf("max:%f\nmin:%f\navg:%f\n", max, min, avg);
return 0;
}

详细解析:

  • float a[10]:题目要求输入 10 个成绩,所以数组长度必须是 10
  • scanf("%f", &a[i]):要把每次输入读到第 i 个元素中
  • 求最小值时应该是:
if (min > a[i])

而不是反过来

容易踩坑点:

  • scanf 忘记写地址符号 &
  • 最值题里 >< 写反
  • 平均值累加时忘记把第一个元素算进去

给新手的建议:

  • 最值和平均值题是最典型的入门题,建议你自己手写一遍模板

功能:利用级数求圆周率近似值

题意:

π / 4 = 1 - 1/3 + 1/5 - 1/7 + ...

题目给出的 4 处错误分别是:

  1. #include <stdlib.h> 应改为 #include <math.h>
  2. s、t、p 应为浮点型
  3. 循环条件写反了
  4. printf 的格式说明符写错了

整理后的正确代码:

#include <stdio.h>
#include <math.h>
void fun(void)
{
int i = 1;
double s = 0, t = 1, p = 1;
while (fabs(t) > 1e-4)
{
s += t;
p = -p;
i += 2;
t = p / i;
}
printf("pi=%f\n", s * 4);
}
int main(void)
{
fun();
return 0;
}

详细解析:

  • fabs() 是浮点绝对值函数,头文件应该是 math.h
  • 级数求和是小数运算,所以 stp 不能用 int
  • 题目要求“直到最后一项绝对值小于等于 0.0001 为止”,所以当它还大于 1e-4 时就继续循环
  • 最终输出是浮点数,所以要用 %f

容易踩坑点:

  • 用整型存小数,结果全部被截断
  • 把循环终止条件写反
  • 忘了 fabs() 对应 math.h

给新手的建议:

  • 级数题先别急着看 π,先看“每一项怎么变”
  • 1 - 1/3 + 1/5 - 1/7 这种交错正负的题,最好单独拿个变量 p 控制符号

题目要求:

  1. 输入 10 个学生成绩
  2. 计算平均成绩 ave
  3. 统计及格人数 pass
  4. 统计高于平均分的人数 better
  5. 对 10 个成绩进行排名

一份完整可运行的参考答案:

#include <stdio.h>
#define N 10
int main(void)
{
int i, j, a[N], ave, sum = 0, pass = 0, better = 0, t;
printf("请输入 10 个学生成绩:\n");
for (i = 0; i < N; i++)
{
scanf("%d", &a[i]);
sum += a[i];
}
ave = sum / N;
for (i = 0; i < N; i++)
{
if (a[i] >= 60)
pass++;
if (a[i] > ave)
better++;
}
for (i = 0; i < N - 1; i++)
{
for (j = i + 1; j < N; j++)
{
if (a[i] < a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
printf("平均分:%d\n", ave);
printf("及格人数:%d\n", pass);
printf("高于平均分人数:%d\n", better);
printf("成绩从高到低排序:");
for (i = 0; i < N; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}

详细解题过程:

第一步,输入并求总分:

for (i = 0; i < N; i++)
{
scanf("%d", &a[i]);
sum += a[i];
}

第二步,求平均分:

ave = sum / N;

第三步,统计及格人数和高于平均分人数:

for (i = 0; i < N; i++)
{
if (a[i] >= 60)
pass++;
if (a[i] > ave)
better++;
}

第四步,排序:

这里用的是最直接的交换排序思想,让分数从高到低排列。

容易踩坑点:

  • for(j=i+1;j<N,j++) 这种地方原卷 OCR 容易把分号识别成逗号
  • 排序时交换语句漏写
  • 统计完平均分前就先比较 a[i] > ave

给新手的建议:

  • 综合题一定拆成小步骤做,不要想一口气写完
  • 输入、统计、排序、输出,这四块分开写最稳

题目要求:

求一个大于 10 的 n 位整数的后 n-1 位的数,并作为函数值返回。

通俗一点说,就是:

  • 输入一个整数
  • 去掉最高位
  • 把剩下的数返回

例如:

  • 1234 -> 234
  • 56789 -> 6789

参考答案:

#include <stdio.h>
int fun(int w)
{
int n = 0;
int i = 1;
while (w > 10)
{
n = n + i * (w % 10);
w /= 10;
i *= 10;
}
return n;
}
int main(void)
{
int w;
printf("请输入一个大于 10 的整数:");
scanf("%d", &w);
printf("结果是:%d\n", fun(w));
return 0;
}

详细解题过程:

比如输入:

1234

循环过程:

  1. 取个位 4,放入 n
  2. 去掉个位,剩下 123
  3. 再取个位 3,拼到前面结果后
  4. 再取 2
  5. 当只剩最高位 1 时停止

于是最后得到:

234

为什么 while (w > 10)

因为题目要求去掉最高位,只保留后 n-1 位,所以当 w 还不止一位时就继续拆。

容易踩坑点:

  • 把条件写成 w >= 10 会影响边界
  • i *= 10 忘写,结果数字拼接位置不对
  • w % 10w / 10 的作用混淆

给新手的建议:

  • 这种数字拆位题,建议你先拿 12345607 这种例子手工模拟
  • 如果以后想保留前导 0,比如 1005 -> 005,那就要换成字符串思路,单纯整数返回会丢掉前导 0

如果你现在是刚学 C 语言的新手,这套卷子做下来,最容易暴露出下面这些问题:

  • 字符串长度和数组长度分不清
  • 数组初始化规则不熟
  • 函数传值和传地址分不清
  • 递归题不会手推
  • scanfgetcharstrlenstrcpystrcat 这些常见函数还不够熟
  • 排序题能看懂但自己写不出来
  • OCR 或卷面稍微乱一点,就容易被格式干扰
  • 先把这套卷子里的数组题、字符串题、函数题各挑 3 题重新手写一遍。
  • 选择题不要只背答案,要会说“为什么其他选项错”。
  • 填空题尤其要自己手敲,像 getchar()breakp=a 这种都是高频基础。
  • 改错题很值得反复看,因为它正好对应新手最常犯的真实错误。
  • 程序设计题不要怕长,把题目拆成输入、处理、输出三个阶段就会好很多。

这套 exam-86 卷子本质上考的不是“特别难的新知识”,而是你对 C 语言基础有没有真正掌握:

  • 基本语法稳不稳
  • 数组和字符串熟不熟
  • 函数和参数传递清不清楚
  • 能不能把一个完整小题拆开做

如果你能把这篇详解看懂,并且自己再手写一遍里面的改错题和程序设计题,那你对前面 C 语言基础章节的理解会扎实很多。