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 &ltstdio.h>
  #include &ltstring.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, &ampnTbl[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 的有向
边&lti,j>。如是这样,从站点 x 至站点 y 的最少上车次数便对应图 G 中从点 x 至点 y 的
最短路径长度。而程序要求的换车次数就是上车次数减 1 。
[程序6]
  #include &ltstdio.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", &ampm, &ampn);
     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", &ampdd);
              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);
  }

  回目录      老顽童校对整理 2002年5月