2000年度高级程序员级下午试题
| 从下列的3道试题(试题一至试题三)中任选2道解答。如果解答的试题数超过2道,则题号小的2道解答有效。 |
试题一 (15分)
阅读以下说明和流程图,回答问题 1 和问题 2 ,将解答写在答卷的对应栏内。
[说明]
本流程图实现从成绩文件生成学生成绩一览表。
某中学某年级的学生成绩数据(分数)登录在成绩文件 F0 中,其记录格式如下:
|
学
号 |
姓
名 |
课程1成绩 |
课程2成绩 |
…… |
课程6成绩 |
由该成绩文件生成如下表所示的学生成绩一览表。生成的学生成绩一览表按学号升序 排列。表中的名次是指该生相应课程在年级中的名次。
|
学 号 |
姓
名 |
课程1 |
课程2 |
...... |
课程6 |
||||
|
成绩 |
名次 |
成绩 |
名次 |
... |
... |
成绩 |
名次 |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
流程图中的顺序文件 F0 是学生成绩文件,F0 文件经处理 1 处理后产生顺序文件 F, 然后经过处理 2 至处理 4 对文件 F 进行处理和更新。在处理 5 中,仅对文件 F 的记录 进行学生成绩一览表的编排输出,不进行排序和增加名次等处理。 (问题1] 流程图中文件 F 的记录格式设定为如下形式:
| 学 号 | 姓 名 | 课程代码 | ① | ② |
其中的①、②应定义为何种数据项?
[问题2]
简述处理 2、处理 3 和处理 4 作何种处理,若有排序处理则需指明排序的键及序(升序
或降序)。
[流程图]
试题二 (15分)
阅读以下说明和流程图,回答问题 1 至问题 4 ,将解答写在答卷的对应栏内。
[说明]
本流程图是将中缀表示的算术表达式转换成后缀表示。如中缀表达式
(A-(B*C+D)*E)/(F+G)
的后缀表示为
ABC*D+E*-FG+/
为了方便,假定变量名为单个英文字母,运算符只有+,-,*,/(均为双目运算符,
左结合),并假定所提供的算术表达式非空且语法是正确的。另外,中缀表示形式中无空格
符,但整个算术表达式以空格符结束。流程图中使用的符号的意义如下:
数组 IN[] 存贮中缀表达式;
数组 POLISH[] 存贮其后缀表示;
数组 S[] 是一个后进先出栈;
函数 PRIOR(CHAR) 返回符号 CHAR 的优先级,各符号的优先级如下表所示:
| CHAR | PRIOR(CHAR) |
|
* / + - ( ) |
4 3 2 1 |
[问题1]
填充流程图中①的判断条件o
[问题2]
写出子程序 A 的功能,并顺序写出实现该功能的操作。
[问题3]
写出子程序 B 的功能,并顺序写出实现该功能的操作。
[问题4]
中缀表达式
(A+B-C*D)*(E-F)/G
经该流程图处理后的输出是什么?
[流程图 
试题三 (15分)
阅读以下说明和流程图,回答问题 1 和问题 2,将解答写在答卷的对应栏内。
[说明]
某供销系统接受顾客的订货单,当库存中某配件的数量小于订购量或库存量低于一定
数量时,向供应商发出采购单; 当某配件的库存量大于或等于订购量时,或者收到供应商
的送货单并更新了库存后,向顾客发出提货单。该系统还可随时向总经理提供销售和库存情
况表。该供销系统的分层数据流图中部分数据流和文件的组成如下:
文件
配件库存 = 配件号 + 配件名 + 规格 + 数量 + 允许的最低库存量
数据流
订货单 = 配件号 + 配件名 + 规格 + 数量 + 顾客名 + 地址
提货单 = 订货单 + 金额
采购单 = 配件号 + 配件名 + 规格 + 数量 + 供应商名 + 地址
送货单 = 配件号 + 配件名 + 规格 + 数量 + 金额
假定顶层图是正确的,“供应商”文件已由其它系统生成。
[问题1]
指出哪张图中的哪些文件可不必画出。
[问题2]
指出在哪些图中遗漏了哪些数据流。回答时用如下形式之一。
(1) X X 图中遗漏了 X X 加工 (或文件) 流向 X X 加工 (或文件) 的 x x 数据流;
(2) X X 图中 X X 加工遗漏了 X X 输入 (或输出) 数据流。
[流程图]
顶层图
![]()
![]()
![]()
试题四 (15分) 在 COMET 型计算机上可以使用试卷上所附的 CASL 汇编语言。阅读程序说明和 CASL 程序,将应填入 __(n)__ 处的字句,写在答卷的对应栏内 [程序4说明] (1)本子程序根据每位职工的基本工资(非负值)和他完成产品的超额数或不足数计算该 职工的应发工资。 (2)主程序调用时,GR1中给出子程序所需参数的起始地址,参数的存放次序如下表:
|
GR1→ |
a1 |
| b1 | |
| c1 | |
| a2 | |
| b2 | |
| c2 | |
| ... | |
| an | |
| bn | |
| cn | |
| -1(结束标志) |
其中 ai 为职工 i 的基本工资;bi 为职工 i 的完成产品的超额数或不足数;ci 为职工 i
的应发工资数(I = 1、2、…、n)。
bi 以原码形式存放(大于零为超额,小于零为不足),基本工资与计算所得的应发工
资以补码形式存放。
(3)应发工资的计算规则为:
·恰好完成定额数(此时 bi = 0),应发工资即为基本工资。
·每超额 4 件,在基本工资基础上增加 10 元(不到 4 件,以 4 计算,例如超额数
为 10 时,增加 30 元)。
·每不足 4 件,在基本工资基础上减 5 元(不到 4 件,以 4 计算,例如不足数为 5
时,减 10 元)。
[程序4]
START
BEG PUSH 0,GR1
PUSH 0,GR2
PUSH 0,GR3
L1 __ (1) __
LEA GR0,0,GR2
JMI FINISH
LD GR3,1,GR1
LEA GR2,0,GR3
AND GR2,C7FFF
JZE L3
SRL GR3,15
LEA GR2,-1,GR2
L2 __ (2) __
LEA GR2,-4,GR2
JPZ L2
L3 __ (3 __
__ (4) __
__ (5) __
FINISH POP GR3
POP GR2
POP GR1
RET
C7FFF DC #7FFF
BONUS DC 10
DC -5
END
试题五 (15分)
阅读下列程序说明和 C 代码,将应填人 __(n)__ 处的字句写在答卷的对应栏内。
[程序 5 说明]
下列文法可用来描述化学分子式的书写规则(例如,Al2(C03)、Cu(OH)2):
λ→β|βλ
β→δ|δn
δ→ξ|ξθλ
其中,λ是一个分子式;δ 或是一个元素,或是一个带括号的(子)分子式,元素或是一个
大写字母(记为ξ),或是一个大写字母和一个小写字母(记为ξθ);β或是一个δ,或是在
δ之后接上一个整数n,δn表示β有n个δ的元素或(子)分子式。一个完整的分子式由若干
个β组成。
当然一个正确的分子式除符合上述文法规则外,还应满足分子式本身的语义要求。
下面的程序输入分子式,按上述文法分析分子式,并计算出该分子式的分子量。例如:
元素 H 的原子量是 1 ,元素 O 的原子量是16。输入分子式 H2O ,程序计算出它的分子量
为重 8 (1×2+16)。程序中各元素的名及它的原子量从文件 atom.dat中读人。
[程序5]
#include <stdio.h>
#include <string.h>
#define MAXN 300
#define CMLEN 30
struct elem { char name[3]; /*元素名*/
double v; /*原子量*/
} nTbl [MAXN];
char cmStr[CMLEN], *pos;
int c; FILE *fp;
double factor ( );
double atom( ) /*处理文法符号δ*/
{ char w[3]; int i; double num;
while ((c = *pos++) == ' '|| c == '\t'); /* 掠过空白字符 */
if (c == '\n') return O.O;
if (c >= 'A' && c <= 'Z') { /* 将元素名存人 W */
w[i = O] = c; c = *pos++;
if (c >= 'a' && c <= 'z') w[++i] = c; else pos-- ;
w[++i] = '\O';
for(i = O; nTbl[i], v > O.O; i++)
if (strcmp(w, nTbl[i].name) == O) return nTbl[i].v ;
printf("\n 元素表中没有所输入的元素:\t%s\n", w); return -1.O ;
} else if (c == '(') {
if ((num = __(1)__ ) < O.O ) return -1.0 ; /* 包括可能为空的情况 */
if (*pos++ != ')') { printf (" 分子式中括号不匹配! \n"); return -1.O ; }
return num;
}
printf(" 分子式中存在非法字符:\t%c\n", c)
return -1.0;
}
double mAtom( ) /* 处理文法符号β*/
{ double num; int n = 1;
if ((num = __(2)__ ) < O.O) return -1.O ;
C = *pos++ ;
if (c >= '0' && c <= '9') {
n = O ; while(c >= '0' && c <= '9')
{ n = __(3)__ ;
c = *pos++ ;
}
}
pos-- ;
return num * n;
}
double factor( ) /* 处理文法符号λ*/
{ double num = O.O, d;
if ((num = mAtom()) < O.O) return -1.O;
while (*pos >= 'A' && *pos <= 'Z'||'pos == '(') {
if ((d = __(4)__ ) < O.O) return -1.O;
__(5)__ ;
} return num;
}
void main( )
{ char fname[ ] = "atom.dat"; /*元素名及其原子量文件*/
int i; double hum;
if ((fp = fopen(fname, "r")) == NULL) { /*以读方式打开正文文件*/
printf("Can not open %s file.\n", fname); return;/* 程序非正常结束 */
}
i = 0;
while(i < MAXN && fscanf(fp, "%s%lf", nTbl[i].name, &nTbl[i].v) == 2)
i++;
fclose(fp); nTbl[i].v = -1.O;
while (1) { /* 输入分子式和计算分子量循环,直至输入空行结束*/
printf ("\n 输入分子式!(空行结束) \n"); gets(cmStr);
pos = cmStr;
if ( cmStr[O] == '\O') break;
if ((num = factor ()) > O.O)
if (*pos != '\0') printf(" 分子式不完整!\n");
else printf(" 分子式的分子量为 %f\n", num);
}
}
试题六 (15分) :
阅读下列程序说明和 C 代码,将应填人 __(n)__ 处的字句写在答卷的对应栏内。
[程序 6 说明]
设某城市有 n 个车站,并有 m 条公交线路连接这些车站,设这些公交车都是单向
的,这 n 个车站被顺序编号为 0 至 n-1 。本程序,输入该城市的公交线路数、车站个
数,以及各公交线路上的各站编号,求得从站 0 出发乘公交车至站 n-1 的最少换车次数。
程序利用输入信息构建一张有向图 G (用邻接矩阵 g 表示),有向图的顶点是车站,
若有某条公交线路经 i 站能到达 j 站,就在顶点 i 到顶点 j 之间设置一条权为 1 的有向
边<i,j>。如是这样,从站点 x 至站点 y 的最少上车次数便对应图 G 中从点 x 至点 y 的
最短路径长度。而程序要求的换车次数就是上车次数减 1 。
[程序6]
#include <stdio.h>
#define M 20
#define N 50
int a[N+l]; /*用于存放一条线路上的各站编号*/
int g[N][N]; /*存储对应的邻接矩阵*/
int dist[N]; /*存储站 0 到各站的最短路径*/
int m, n;
void buildG( )
{ int i, j, k, sc, dd;
printf ("输入公交线路数,公交站数\n");
scanf ("%d%d", &m, &n);
for( i = O; i < n; i++) /* 邻接矩阵清0 */
for(j = O; j < n; j++) g[i][j] = O;
for( i = O; i < m; i++) {
printf (" 沿第 %d 条公交车线路前进方向的各站编号
( O <= 编号 <= %d, -1 结束):\n", i+l, n-1 );
sc = O; /* 当前线路站计数器 */
while (1) {
scanf ("%d", &dd);
if (dd == -1) break;
if (ad >= 0 && dd < n) ___(1)___
}
a[sc] = -1;
for(k = 1; a[k] >= O; k++) /* 处理第 i+l 条公交线路 */
for (j = 0; j < k; j++)
g __(2)__ = 1;
}
}
int minLen( )
{ int j, k;
for(j = O; j < n; j++) dist[j] = g[O][j];
dist[O] = 1;
do {
for(k = -1, j = 0 ; j < n; j++) /* 找下一个最少上车次数的站*/
if (dist[j] > 0 && (k == -1 || dist[j] < dist[k])) k = j;
if (k < 0 || k == n-l) break;
dist[k] = -dist[k]; /* 设置 k 站已求得上车次数的标记 */
for(j = 1; j < n; j++) /* 调整经过 k 站能到达的其余各站的上车次数 */
if ( __(3)__ && (dist[j] == 0 || -dist[k] + 1 < dist[j] ) )
dist[j] = __(4)__ ;
} while (1);
j = dist [n-l];
return __(5)__ ;
}
void main ( )
{ int t;
buildG ( );
if ((t = minLen()) < O) printf ("无解 ! \n"),
else printf ("从 0 号站到 %d 站需换车 %d 次\n , n-i, t);
}