2010 上半年程序员考试真题及答案-下午卷
试题一
【说明】
下面的流程图旨在统计指定关键词在某一篇文章中出现的次数。设这篇文章由字符
A(0),…,A(n-l)依次组成,指定关键词由字符 B(0),…,B(m-l) 依次组成,其中 n>m>=l。
注意,关键词的各次出现不允许有交叉重叠。例如,在“aaaa” 中只出现两次“aa”。
该流程图采用的算法是:在字符串 A 中,从左到右寻找与字符串 B 相匹配的并且没有交叉重
叠的所有子串。流程图中,i 为字符串 A 中当前正在进行比较的动态子串首字符的下标,j
为字符串 B 的下标,k 为指定关键词出现的次数。
【流程图】
(1) 0—>k
(2) i+j
(3) i+m
(4) i+1
(5) i
本题考查用流程图描述算法的能力。
在文章中查找某关键词出现的次数是经常碰的问题。例如,为了给文章建立搜索关键词,
确定近期的流行语,迅速定位文章的某个待修改的段落,判断文章的用词风格,甚至判断后
半本书是否与前半本书是同一作者所写(用词风格是否一致)等,都采用了这种方法。
流程图最终输出的计算结果就是文章字符串 A 中出现关键词字符串 B 的次数。显然,流程图
开始时应将赋值 0,以后每找到一处出现该关键词,就执行增 1 操作 k=k+1. 因此(1)处应填
0—>K。
字符串 A 和 B 的下标都是从 0 开始的。所以在流程图执行的开始处,需要给它们赋值 0。
接下来执行的第一个小循环就是判断 A(i),A(i+l),…,A(i+j-1)是否完全等于 B(0),
B(1),…,B(m-l),其循环变量 j=0,1,…,m-1。只要发现其中对应的字符有一个不相等
时,该小循环就结束,不必再继续执行该循环。因此,该循环中继续执行的判断条件应该是
A(i+j)=B(j)且 j
个,所以这是正确的。也可以用例子来检查次数是否正确。检查次数是程序员的基本功,数
目的计算很容易少一个或多一个。
既然最后一次判断关键词应该是对 A(n-m),A(n-m+1),…,A(n-l)的判断,即对 i=n-m
进行的小循环判断,所以当 i>n-m 时就应该停止大循环,停止再查找关键词了。
试题二
阅读以下问题说明、C 程序和函数,将解答填入答题纸的对应栏内。
【问题 1】
分析下面的 C 程序,指出错误代码(或运行异常代码)所在的行号。
【C 程序】
5,或 arrChar = "test"
7,或*P='0’
本题考查 C 程序编写和调试中常见错误的识别和改正。
在 C 语言中,指针表示内存单元的地址,指针变量可用于存储指针类型的值,即内存单
元的地址值。变量的值在程序运行过程中允许修改,而常量则不允许修改。可以令指针指向
一个变量或常量,但若指针指向一个常量,则不允许通过指针修改该常量。
第 5 行代码有错,即对数组名 arrChar 的赋值处理是错误的。在 C 语言中,数组名是表示数
组空间首地址的指针常量,程序中不允许对常量赋值。
第 7 行代码有错,在第 6 行中,通过 p = "testing"使指针变量指向了一个字符串常量,
此后可以再令指针 p 指向其他字符或字符串,但不能通过指针修改字符串常量的内容。
【问题 2】
函数 inputArr(int a[], int n)的功能是输入一组整数(输入 0 或输入的整数个数迖
到 n 时结束)存入数组 a,并返回实际输入的整数个数。函数 inputArr 可以成功编译。但
测试函数调用 inputArr 后,发现运行结果不正确。
请指出错误所在的代码行号,并在不增加和删除代码行的情况下进行修改,写出修改正
确后的完整代码行,使之符合上述设计意图。
【C 函数】
该函数中出现的错误是编写 C 程序时的常见错误。scanf 是 C 标准库函数中的格式化输
入函数,其原型如下: .
int scanf(char *format,...);
使用时,第一个实参是格式控制串,之后的实参是地址 1,地址 2,……
在本题中,要求以十进制整数格式输入一个整数并存入 a[k],数组元素 a[k]实质上一
个整型变量,必须用“&”求得 a[k]的地址作为实参调用 scanf 函数,因此,第 4 行出错,
正确代码应为“scanf("%d",&a[k]);”。
C 程序中将相等运算符“==”误用为赋值运算符“=”也是常见的一个错误,由于“=”
也是合法的运算符并且 C 语言中用 0 和非 0 来表示逻辑假和逻辑真,因此在应产生逻辑值的
地方产生了其他数值也可以,因此该错误通常只能用人工检查和排除。第 6 行的正确代码应
为“if(k=n)break;”。
在该程序中,结束循环的一个条件是 k 等于 n,另一个条件是输入的整数为 0。另外,
do-while 的循环条件为真(非 0)时要继续循环,因此,循环条件应该是判断输入的值不等
于 0。观察循环体中与数组元素有关的部分,如下所示:
scanf("%d", &a[k]);
k++;
也就是说输入为 0 时存入了 a[k],而循环判断条件“a[k]=0”中的 a[k]相对于刚存入
了 0 的数组元素来说已经是 a[k+l]了,.因此正确的条件为“a[k-l]!=0”。
试题三
【说明】
基于管理的需要,每本正式出版的图书都有一个 ISBN 号。例如,某图书的 ISBN 号为
“978-7-5606-2348-1”。
ISBN 号由 13 位数字组成:前三位数字代表该出版物是图书(前缀号),中间的 9 个数
字分为三组,分别表示组号、出版者号和书名号,最后一个数字是校验码。其中,前缀号由
国际 EAN 提供,已经采用的前缀号为 978 和 979;组号用以区别出版者国家、地区或者语言
区,其长度可为 1〜5 位;出版者号为各出版者的代码,其长度与出版者的计划出书量直接
相关;书名号代表该出版者该出版物的特定版次;校验码采用模 10 加权的算法计算得出。
校验码的计算方法如下:
第一步:前 12 位数字中的奇数位数字用 1 相乘,偶数位数字用 3 相乘(位编号从左到
右依次为 13 到 2)。
第二步:将各乘积相加,求出总和 5。
第三步:将总和 S 除以 10,得出余数 R。
第四步:将 10 减去余数 R 后即为校验码 V。若相减后的数值为 10,则校验码为 0。
例如,对于 ISBN 号“978-7-5606-2348-1”,其校验码为 1,计算过程为:
S=9X1+7X3+8X1+7X3+5X1+6X3+0X1+6X3+2X1+3X3+4X1+8X3=139
R=139mod10=9
V=10-9= 1
函数 check(char code[])用来检查保存在 code 中的一个 ISBN 号的校验码是否正确,
若正确则返回 true,否则返回 false。例如,ISBN 号“978-7-5606-2348-1”在 code 中的存
储布局如表 3-1 所示(书号的各组成部分之间用分隔):
(1) k++,或 temp++
(2) i<12,或 i