1996年高级程序员级下午试题
|
从以下的 3 道试题(试题一至试题三)中任选 2 道解答。如果解答的试题数超过2 道,则解答的前2道有效。 |
试题一
阅读下列说明和流程图,回答问题
1 至问题 3,把解答写在答卷的对应栏内。
【说明】
本流程图描述了某行业分类电话号码簿(简称号簿)出版系统的处理流程。全市所有电话的基本信息均存放在营业库中。系统输入工单,工单中包括电话的新装、拆除、移机、更改(更改户名、地址、电话号码等)等信息。为确保输入工单的正确性,每张工单均由两个录入员分别录入,由处理 1 进行输入和校对,然后更新营业库。系统根据待出版号簿的行业类型从营业库中选取该类用户的电话信息,存放在号簿中。同时向每个电话用户发布用户函,用户函上记录着将刊登在号簿上的该用户的户名、地址、电话号码等信息,用户函上的序号标志着该用户信息在号簿库中的位置。用户收到用户函后自行校对,并将修改内容和印刷要求(字体大小和是否套红)填写在用户回执中,系统按收到用户回函的先后顺序依次输入用户回函,然后更新号簿库。最后通过排版输出经用户校对并符合其印刷要求的号簿清样。
系统中部分单据和文件的格式如下:
工单=工单类型+原户名+新户名+原地址+新地址+原电话号码+新电话号码
营业库纪录=户名+地址+电话号码+分类信息
用户函=序号+户名+地址+电话号码
用户回函=序号+户名+地址+电话号码+套红标记+字体大小
【流程图】

【问题 1】
流程图中哪些处理能发现工单的哪些错误,并举例说明。
【问题 2】
指出号簿库文件的纪录至少应包括哪些数据项。
【问题3】
为提高处理速度,流程图需作何改进。
试题二
阅读下列说明和流程图,回答问题 1 至问题 2,把解答写在答卷的对应栏内。
【说明】
本流程图将数字 1,2,…,N2(N≥2)按逆时针方向依次写在 N*N 矩阵中,下图给出了 N=4 和 N=5时的情况:
| 1 | 12 | 11 | 10 | 1 | 16 | 15 | 14 | 13 | |
| 2 | 13 | 16 | 9 | 2 | 17 | 24 | 23 | 12 | |
| 3 | 14 | 15 | 8 | 3 | 18 | 25 | 22 | 11 | |
| 4 | 5 | 6 | 7 | 4 | 19 | 20 | 21 | 10 | |
| 5 | 6 | 7 | 8 | 9 | |||||
| N=4时 | N=5时 | ||||||||
【问题 1】
填充流程图中的 ①~⑥ 使之成为完整的流程图。
【问题 2】
若将数字 1,2,…,N2 按顺时针方向依次写在 N*N 矩阵中,则只需将上述流程图中的__⑦__改成__⑧__即可。
【流程图】 
注:图中[N/2]表示不大于 N/2 的最大整数。
试题三
阅读以下说明和 E-R 图,回答问题,讲解答写在答卷的对应栏内。
【说明】
设有下列关于运动会管理系统的 E-R 图。图中矩形表示实体,圆表示属性,双圆表示关键字属性,菱形表示实体之间的关系。假定已通过下列 SQL 语言建立了基本表:
CREATE TABLE ATHLETE
(ANO CHAR(6) NOT NULL,
ANAME CHAR(20),
ASEX CHAR(1),
ATEAM CHAR(20));
CREATE TABLE ITEM
(INO CHAR(6) NOT NULL,
INAME CHAR(20),
ITIME CHAR(10),
IPLACE CHAR(20));
CREATE TABLE GAMES
(ANO CHAR(6) NOT NULL,
INO CHAR(6) NOT NULL,
SCORRE CHAR(10));
为了答题的方便,图中的实体和属性同时给出了中英文两种名字,回答问题时只需写出英文名即可。
【E-R图】
【问题】
填充下列 SQL 程序 3.1~3.4 中的 ①~⑦,使它们分别完成相应的功能:
程序 3.1:统计参加比赛时运动员人数
SELECT __①__
FROM ATHLETE
WHERE ASEX='M';
程序 3.2:查100872号运动员参加的所有项目及其比赛时间和地点
SELECT ITEM,INO,INAME,ITIME,IPLACE
FROM GAMES,ITEM
WHERE __②__
AND __③__;
程序 3.3:查参加 100035 项目的所有运动员名单
SELSECT ANO,ANAME,ATEAM
FROM ATHLETE
WHERE __④__
(SELECT __⑤__
FROM GAMES
WHERE GAMES.ANO=ATHLETE.ANO
AND INO='100035');
程序3.4:建立运动员成绩视图
__⑥__ ATHLETE_SCORE
AS SELECT ATHLETE,ANO,ANAME,ATEAM,INAME,SCORE
FORM __⑦__
WHERE ATHLETE,ANO=GAMES,ANO
AND GAMES.INO=ITEM.INO;
| 试题四为必答题。 |
试题四
在 COMET 型计算机上可以使用试卷上所附的 CASL 汇编语言。阅读下列程序说明和
CASL 程序,将应填入程序中__?__处的字句,写在答卷的对应栏内。
【程序说明】
子程序 OFFSET 用二分法,查找无符号整数 M 在一个长度为 N 的有序(升序)无符号整数列表NTABLE 中的位置。
程序中标号为 LOW 和 UP 的两个存储字分别用作存放查找区间的上下限。
进入子程序时,在GR1中给出存放子程序所需参数的起始地址。参数的存放次序如下:
|
(GR1)+0 |
M |
|
1 |
N |
|
2 |
NTABLE的首址 |
从子程序返回时,GR0 中存放查找结果,即 M 在此有序表中的位置序数,如表中找不到
M,则 GR0 中返回 0,其它寄存器的内容保持不变。
[程序]
START
OFFSET
PUSH
0,GR2
PUSH
0,GR3
LD
GR0,0,GR1
LEA
GR2,0
ST
GR2,LOW
___(1)___
___(2)___
ST
GR2,UP
LOOP
ADD
GR2,LOW
SRL
GR2,1
LEA
GR3,0,GR2
___(3)___
___(4)___
JZE
FOUND
JPZ
INCLOW
LEA
GR2,-1,GR2
;M<NTABLE(K)
ST
GR2,UP
JMP
CMPLU
INCLOW
LEA
GR2,1,GR2
;M> NTABLE(K)
ST
GR2,LOW
;K+1→LOW
___(5)___
CMPLU
CPL
GR2,LOW
___(6)___
___(7)___
FOUND
LEA
GR0,1,GR2
POP
GR3
POP
GR2
RET
LOW
DS
1
UP
DS
1
END
|
从下列的 2 道试题(试题五至试题六)中任选 1 道解答。如果解答的试题数超过 1 道,则解答的前 1 道有效。 |
试题五
阅读以下程序说明和 C 程序,将应填入程序中__?__处的字句,写在答卷的对应栏内。
【程序说明】
本程序是一个简单的计算器模拟程序。对任意给定的正确四则运算表达式,程序计算其结果值并输出。表达式中运算分量为无正负号整数,运算符为 +、_、*、/,圆括号按常规配对,表达式以字符 "=" 结束。
函数 getach()
为获取表达式的一个合法字符,并将字符存入变量 curch;函数指针数组
func[] 是为了统一加减乘除计算而设置的。
【程序】
#include <stdio.h>
int add(int x,int y){return x+y;}
int sub(int x,int y){return x-y;}
int mul(int x,int y){return x*y;}
int div(int x,int y){return x/y;}
int (*func[])()={add,sub,mul,div};
int num,curch;
char chtbl[]="+-*/()=";
char corch[]="+-*/()=0123456789";
int getach()
{ int i;
while(1)
{ curch = getchar();
if(curch == EOF) return -1;
for (i = 0;corch[i] && curch != corch[i];i++);
if (i<strlen(corch)) break;
}
return curch;
}
int getid()
{ int i;
if(curch >= '0' && curch <= '9')
{ for(num = 0;curch >= '0' && curch <= '9';getach())
num = __①__;
return -1;
}
else { for( i = 0;chtbl[i];i++)
if (chtbl[i] == curch) break;
if ( i <= 5) getach();
return i;
}
}
int cal()
{ int x1,x2,x3,op1,op2,i;
i = getid();
if ( i == 4) x1 = cal(); else x1 = um;
op1 = getid();
if ( op1 >= 5) return x1;
i = getid();
if ( i == 4) x2 = cal(); else x2 = num;
op2 = getid();
while (__②__)
{ i = getid();
if ( i == 4) x3 = cal(); else x3 = num;
if (( op1/2 == 0) && (op2/2 == 1))
x2 = ( *func[op2](x2,x3));
else { x1 = __③__;
x2 = x3;
__④__;
}
op2=getid();
}
return __⑤__(x1,x2);
}
void main()
{ int value;
printf("Please input an expression:\n");
getach();
while (curch != '=')
{ value = cal();
printf("The result is : %d\n",value);
printf("Please input an expression:\n");
getach();
}
}
试题六
阅读下列程序说明和 FORTRAN 程序,将应填入程序中__?__处的字句,写在答卷纸的对应栏内。
【程序说明】
子程序 SUM 计算数列
1,1/2,1/3,…,1/n,…
的前 n 项和,并以 M 位小数形式输出(M≤60)。
为提高计算结果的精度,用分数形式计算并存放数列的部分和,求和结果记为
A+U/V
其中 U/V 是不可约真分数,A 为整数。
例如:n = 5,M = 10 时,子程序输出为
1+1/2+1/3+1/4+1/5 = 2+17/60
2.283333333
整型函数 GCD 用辗转相除法计算 U 和 V 的最大公约数。
【程序】
SUBROUTINE SUM(N,M)
INTEGER A,U,V,G,D(60),GCD
A=1
U=0
V=1
DO 20 K=2,N
U=__①__
V=__②__
A=__③__
U=MOD(U,V)
__④__
U=U/G
V=V/G
20 CONTINUE
WRITE(*,100)N,A,U,V
100 FORMAT(1X,'1+1/2+1/3+…+1/',I2,'=',I2,'+'I10,'/',I10)
DO 40 I=1,M
D(I)=__⑤__
__⑥__
40 CONTINUE
WRITE(*,200)A,(D(I),I=1,M)
200 FORMAT(1X,I2,'.',60I1)
END
INTEGER FUNCTION GCD(U,V)
INTEGER U,V
K=V
L=U
10 IF(MOD(K,L).GT.0) THEN
J=MOD(K,L)
K=L
L=J
GOTO 10
ENDIF
__⑦__
END
|
从下列的 2 道试题(试题七至试题八)中任选 1 道解答。如果解答的试题数超过 1 道,则解答的前 1 道有效。 |
试题七
阅读下列程序说明和 C 程序,将应填入程序中__?__处的字句,写在答卷纸的对应栏内。
【程序说明】
本程序先从文件读入各考生的准考证号(设为整型数)及成绩,并将其存放在一棵检索二叉树上,二
叉树的结点的键值是成绩,二叉树每个节点带一链表,链表结点存放取得该成绩的考生的准考证号。然后,程序按中序遍历检索二叉树,从高到底分输出结果,使每行输出某成绩及其取得该成绩的各考生的准考证号。
【程序】
#include <stdio.h>
typedef struct idnode{
int id;
struct idnode *next;
} IdNode;
typedef struct marknode{
int mark;
IdNode *head;
struct marknode left,right;
} MarkNode;
char fname[] = "sp07.dat"'
main()
{ int id,mark;
MarkNode *root = null;
FILE *fp = fopen(fname,"r");
if (!fp) {
printf("file %s open error.\n",fname);
exit(0);
}
while (!feof(fp)) {
fscanf(fp,"%d%d",&id,&mark);
btree(&root,id,mark);
}
fclose(fp);
print(root);
}
btree(MarkNode **mpptr,int id,int mark)
{ IdNode *ip;
MarkNode *mp = mpptr;
if(__①__){
if(mark == mp->mark) addIdNode(__②__,id);
else if(mark>mp->mark) btree(&mp->left,id,mark);
else btree(&mp->right,id,mark);
}else
{ mp = (MarkNode *)malloc(sizeof(MarkNode));
mp->mark=mark;
mp->left = mp->right = NULL;
__③__
addIdNode(&mp->head,id);
__④__
}
}
addIdNode(IdNode **ipp,int id)
{ IdNode *ip = ipp;
if (__⑤__) addIdNode(__⑥__,id);
else{
ip = (IdNode *)malloc(sizeof(IdNode));
sp->id = id;
ip->next = NULL;
__⑦__
}
}
print(MarkNode *mp)
{ IdNode *ip,ip0;
if (mp){
print(mp->left);
printf("%6d: \t",mp->mark);
ip=mp->head;
while(ip){
printf("%6d: \t",ip->id);
ip0 = ip;
ip = ip->next;
free(ip0);
}
printf("\n"); print(mp->right); free(mp);
}
}
试题八
阅读下列程序说明和 FORTRAN 程序,将应填入程序中__?__处的字句,写在答卷纸的对应栏内。
【程序说明】
某公司招聘 M 个工种(编号为 1~M )的工作人员,每个工种有各自的计划招工数。共有 N 位应聘者,每位应聘者有一报名号,且必须申报两个工种志愿,并参加公司组织的笔试和面试。公司为每位应聘者评定一个综合考试成绩(0~100分)。然后从高分到低分(分数相同者报名号小的优先)依次对每个应聘者进行录用。录用的原则如下:
(1) 对同一应聘者,第一志愿优于第二志愿。
(2) 若应聘者的第一志愿工种已录满,则将其成绩减去 5 分后,立即参加第二志愿录用。
(3) 在一个工种录取时,按申报该工种的应聘者"录用成绩"(第一志愿为考试成绩,第二志愿为考试成绩减5分)从高到底次序录用,"录用成绩"相同者,按报名号从小到大顺序优先录用。
(4) 允许某工种未招满计划招工数。
程序中数组 NO、MARK、ZY1、ZY2 分别存放应聘者的报名号、考试成绩、第一志愿工种遍号和第二志愿工种编号,并假定它们已先按考试成绩降序、后按报名号升序的顺序排列,数组 GZ 存放各工种的计划招工数。
子程序 RY 按上述录用原则完成录用工作。录用过程中使用了三维数组 RYNO,数组的最终值即为各工种的录取顺序名单。数组元素 RYNO(K,J,1)和 RYNO(K,J,2) 分别存放第 K 个工种准备录用的第 1 名应聘者的报名号和"录用成绩"。数组元素 TOP(K) 存放录用过程中第 K 个工种已存入数组 RYNO 的人数。
子程序 INSERT 将报名号 NOI 和成绩 MARKI 按"录用成绩"降序顺序插入到数组 RYNO 第 K 个工种的相应位置中。
【程序】
SUBROUTINE RY(NO,MARK,ZY1,ZY2,GZ,RYNO,TOP,M,N)
INTEGER NO(N),MARK(N),ZY1(N),ZY2(N),GZ(N)
INTEGER RYNO(M,N,2),TOP(,M)
DO 10 I=__①__
10 TOP(I)=0
DO 20 I=1,N
K1=ZY1(I)
K2=ZY2(I)
IF(TOP(K1).LT.GZ(K1)) THEN
__②__
CALL INSERT(RYNO,M,N,K1,TOP(K1),NO(I),MARK(I))
CALL INSERT(RYNO,M,N,K1,TOP(K1),NO(I),MARK(I))
ELSEIF(TOP(K20.LT.GZ(K2)) THEN
TOP(K2)= __③__
RYNO(K2,TOP(K2),1)=NO(I)
RYNO(K2,TOP(K2),2)=__④__
ENDIF
20 CONTINUE
END
SUBROUTINE INSERT(RYNO,M,N,K,TOPK,NOI,MARKI)
INTEGER RYNO(M,N,2),TOPK
10 IF(J.EQ.0) THEN
RYNO(K,1,1)=NOI
RYNO(K,1,2)=MARKI
ELSEIF(MARKI__⑤__RYNO(K,J,2)) THEN
RYNO(K,J+1,1)=NOI
RYNO(K,J+1,2)=MARKI
ELSE
__⑥__
__⑦__
J=J-1
GOTO 10
ENDIF
END