1998年度高级程序员级下午试卷

  从下列的3道试题(试题一至试题三)中任选2道解答。如果解答的试题数超过2道,则题号小的2道解答有效。

 

试题一

  阅读以下说明和流程图,回答问题 1至问题3,将解答写在答卷的对应栏

[说明]

  本流程图描述某超市销售数据的部分处理流程。超市中有若干台收款机和若干名收款员。这里,我们把一个收款员开始使用一台收款机到离开这台收款机称为该收款员的一次作业。作业开始时,收款员先在收款机上输入收款员号和作业前金额。作业前金额是为了销售时的找零而在作业前预先放入钱箱的金额数。作业结束时,收款员要打开钱柜,取走全部现金,并把这些现金的金额数(称为作业后金额)输入收款机。当

    作业前金额+本次作业售货总金额-本次作业退货总金额≠作业后金额

时,表示这次作业存在金额差错。

  本流程图已作简化,并作以下假定;该超市只有现金交易(不用信用卡和礼券);一个收款员因某种原因(如吃饭)在一天中可以有多个作业;销售方式只有售货和退货两种。

  整个超市分成若干部门(如食品部、服装部),系统按部门统计一个月中各类货物的销售数量和金额,最后根据月销售计划文件分析各部门完成销售计划的情况。系统还统计每个收款员的差错情况和退货情况。

  图中处理 4 和处理 8 每月的最后一天执行一次(营业结束后),其它处理每天执行一次。

  图中部分数据、文件的记录格式如下:

  日销售数据:收款机号十收款员号 + 作业前金额 +

       {(售货标记|退货标记) + 货号 + 数量 + 单价 + 金额}+作业后金额

  日销售文件记录:(作业开始标记 + 收款机号 + 收款员号 + 作业前金额 )

          |(售货标记|退货标记) + 货号 + 数量 + 金额) )

          |(作业结束标记 + 收款机号 + 收款员号 + 作业后金额

  部门日销售文件记录:部门号 + (售货标记|退货标记) + 货号 + 数量+金额

  部门月销售计划文件记录;部门号 + 月计划金额

  收款员差错月报:月份 + 收款员号 + 差错作业数 + 差错总金额

  收款员退货月报:月份 + 收款员号 + 退货次数 + 退货总金额

  其中 {w} 表示 w 重复出现多次; a|b 表示 a 或 b; a+b 表示 a 与 b。

[问题1]

  分别写出收款员日销售文件、商品文件、部门日销售汇总文件至少应包含哪些数据项。

[问题2]

  处理 1 能检查出日销售数据中的哪些错误。

[问题3]

  处理 4 对收款员月销售文件作何种操作。

[流程图]

    

 

试题二

  阅读以下说明和流程图,回答问题,将解答写在答卷的对应栏内。

[说明]

  本流程图描述了某子程序的处理流程,现要求用白盒测试法为该子程序设计测试数据。

[问题]

  根据判定覆盖、条件覆盖、判定—条件覆盖、条件组合覆盖(即多重条件覆盖)、路径覆盖等五种覆盖标准,从供选择的答案中分别找出满足相应覆盖标准的最小测试数据组(用(1)~(12)回答)。

供选择的答案

(1)x=90,y=90

(2)x=90,y=70

(3)x=90,y=90 (4)x=90,y=75
  x=70,y=70    x=70,y=90    x=90,y=75    x=75,y=90
   x=75,v=90     x=70,y=70
(5)x=90,y=90 (6)x=80,y=80 (7)x=80,y=80 (8)x=80,y=80
  x=90,y=75   x=90,y=70   x=90,y=75   x=90,y=70
  x=75,y=90   x=70,y=90   x=90,y=90   x=70,y=90
  x=70,y=70   x=70,y=70   x=75,y=90   x=70,y=70
  x=70,y=70   x=70,y=75
(9)x=80,y=80 (10)x=90,y=90 (11)x=80,y=80 (12)x=80,y=80
   x=90,y=75   x=90,y=75    x=90,y=75    x=80,y=70
  x=90,y=70   x=90,y=70   x=90,y=70   x=70,y=80
  x=70,y=80   x=75,y=90   x=70,y=80   x=70,y=70
  x=70,y=75    x=70,y=70   x=70,y=75   x=90,y=75
  x=70,y=70   x=70,y=90   x=70,y=70   x=90,y=70
  x=70,y=90   x=70,y=75
  x=75,y=90
  x=75,y=80
  x=70,y=90

[流程图]

        

试题三

  阅读以下说明和流程图,回答问题1至问题2,将解答写在答卷的对应栏内。

[说明]

  本流程图描述了某种字符序列的变换过程。变换前的字符序列以字符“#”结尾,它存放在数组 old 中,变换后的字符序列存放在数组 new 中,它不包含结束标志“#”。流程图按下列规则进行变换:

         1.删除字符序列中的注解。注解用一对“!”字符分隔,注解中可出现除“#”外的任何字符。

     2.字符常数完整地保留。字符常数用一对“&”字符分隔,字符常数中可出现除“#”外的任何字符。值得注意的是:当字符“&”需要出现在字符常数中时,通常用二个连续的“&”表示,在保留字符常数时,这二个连续的“&”都被保留。此外,作为字符常数分隔符的一对“&”也被保留。

        3.除字符常数和注解外,出现在其它地方的连续多个空格压缩成一个空格,但字符序列中先导的空格则全部删除。

     4.注解和字符常数之外的非空格字符均保持不变。

  本流程图对原字符序列从左到右扫描,根据遇到的当前字符来搜索连续空格、注解或字符常数,然后按上述变换规则变换。若遇到的当前字符是“!”,则寻找下一个“!”字符(若找不到则作出错处理),这二个“!”间的字符全部看作为注解。若当前字符是“&”字符则寻找与之配对的下一个“&”字符(若找不到则作出错处理),其间的字符全部看作为字符常数。

  例如:

  原字符序列: ㄩㄩaㄩㄩㄩb&cd&&ㄩㄩ!e&fㄩㄩg!h& ㄩㄩ!ㄩㄩj#

  变换后的字符序列:aㄩbdcd&&ㄩㄩ!e&fㄩgㄩj

  本流程图假定在数组 old 中一定存在“#”字符。

[问题1]

  填充流程图中的 ①~⑤,把解答写在答卷的相应位置上。

[问题2]

  当原字符序列中汪解的前后均是连续空格时,本流程图将注解前后的连续空格分别压缩成一个空格,删除注解后,将导致变换后的新字符序列出现二个连续的空格。如;

           gㄩㄩ!h&ㄩㄩi!ㄩㄩj

本流程图将变换成:gㄩㄩj。

  为使变换后的新序列中除字符常数外没有连续的空格,图中的虚线框需作何改动(只需画出修改后的流程图)。

[流程图]

  

试题四

  在 COMET 型计算机上可以使用试卷上所附的 CASL 汇编语言。阅读以下程序说明和CASL 程序,将应填入_(n)_处的字句,写在答卷的对应栏内。

[程序说明]

  本程序是统计字符串中数字字符“0”至“9”的出现次数。

  字符串中的每个字符是用 ASCII 码存贮。一个存贮单元存放两个字符,每个字符占 8 位二进位。

  程序中,被统计的字符串从左至右存放在 STR 开始的连续单元中,并假定其长度不超过 200,字符串以‘·’符作为结束。NCH 开始的 10 个单元存放统计结果。

   START MIN

MIN  LEA GR2,9

   LEA GR0,0

L1  _(1)_

   LEA GR2,-1,GR2

      JPZ L1

   LEA GR4,0

   LEA GR1,0

L2  LD GR2,STR,GR1

   EOR GR4,C1

   JNZ RL

   _(2)_

RL  SRL GR2,8

   LEA GR3,0,GR2

   SUB BR3,C9

   JM1 L3

   JNZ L4

L3  LEA GR3,0,GR2

   SUB GR3,CO

   JM1 L5

   LEA GR2,1

   _(3)_

   _(4)_

L4  LEA GR4 0,GR4

   JNZ L2

   _(5)_

   JMP L2

L5  SUB GR2,C

   JNZ L4

   EXIT

C1  DC 1

C   DC '·'

C0  DC '0'

C9  DC 9

STR  DS 200

NCH  DS 10

   END

  从下列的2道试题(试题五至试题六)中任选1道解答。如果解答的试题数超过1道,则题号小的1道解答有效。

 

试题五

  阅读以下程序说明和 C 程序,将应填入_(n)_处的字句,写在答卷的对应栏内。

[程序说明]

  这里给出的程序逐一从指定课程成绩文件中读入学生的学号和成绩,对同一学生汇总他的总成绩,并按以下格式输出名次(按总成绩由高到低的顺序)、总成绩、同一名次的学生人数、同一名次学生的学号(按学号由小到大的顺序)。

  程序约定学生学习课程不超过 30 种,课程成绩文件的第一个数字就是课程号,统计过程中,同一课程号的成绩文件不能重复输入。

  程序采用链表结构存储学生有关信息,链表中的每个表元对应一位学生。程序在数据输入过程中,形成一个按学生学号从小到大顺序链接的有序链表。当数据输入结束后,程序按总成绩从高到低,学号从小到大的顺序对链表排序。程序最后按指定格式输出链表中的信息。程序的输出格式如下例所示:

名次

总成绩

人数

学号

 

 

1

470

2

12

25

 

3

450

3

15

24

50

6

430

1

14

 

 

7

401

3

13

18

45

 

 

 

 

 

[程序]

#include 〈stdio.h〉

#define M 30

#define NLEN 10

typedef struct node { int cur_s;  /*最近输入成绩的科目 */

            char no[NLEN]; int score;

            stuction node *next;

          }NODE;

N0DE *bubblesort(N0DE *head)

{ NODE *q,*tail,*p =(MODE *)malloc(sizeof(NODE);

 p->next = head; head = p; tail = NULL;

 while (tail != ___(1)___)

 { p = head; q = p->next;

  while (q->enxt!= tail)

  { if (p->next->score < q->next->score||

     p->next->score == q->next->score &&

     strcmp(p->next->no,q->next->no) > 0)

   { p->next=__(2)__; /*两相邻表元链接关系前后颠倒*/

    __(3)__ = q->next->next; p->next->next = q;

   }

   p = p->next; /*调整 p 和 q */    q =__(4)__;

  }

  tail = q;

 }

 p = head->next; free(head); return p; 

}

int s[M],sp;

main()

{ FILE *fp;

 NODE *h,*u,*v*p;

 int ss,i,mark,order,c;

 char fname[80],no[NLEN],ans;

 for(h = NULL,sp = 0; ;)

 { print( "输入科目成绩文件名(输入 aaaa 表示强行结束)。\n");

  while (1)

  { scanf("% s",fname);

   if (strcmp(fname,"aaaa") == 0) break;

   if ((fp = fopen(fname,"r")) == NULL)

    printf("不能打开文件 %s,请重新输入科目文件名。\n" ,fname);

   else break;

  }

  if(strcmp(fname,"aaaa") == 0) break;

  fscanf(fp,"% d",&ss);   /* 输入科目号 */   s[sp] = ss;

  for(i = 0;s[i] != ss; i++);

  if (i < sp)

  { printf("该科目的成绩已输入,请输入别的科目成绩文件。\n");

   continue;

  }

  sp++;

  while (fscanf(fp,"%s%d",no,&mark) == 2)

  { /*在链表中寻找最近输入的学号*/

   for(v = h;v != NULL, && strcmp(v->no,no) < 0;u = v,v = v->next);

   if(v != NULL && strcmp(v->no,no) == 0)

   { if (v->cur_s != ss)

    { v->score += mark; v->cur_s = ss;

    } /*同一科目成绩的重复输入,后输入成绩被忽略*/

   } else { p = (NODE *)malloc(sizeof(NODE);  /*一位新的学生*/

        strcpy(p->no,no); p->score = mark; p->cur_s = ss;

        p->next = v;

        if ( v == h)  h = p;else u->next = p;

       }

  } fclose(fp);

  printf("还有科目成绩文件要输入吗?(Y/N)"); scanf("%c", &ans);

  if( ans == 'N'|| ans == 'n') break;

 }

 h = bubblesort(h);

 printf("名次 总成绩 人数 学号\n");  /*以下按格式要求输出*/

 v = h; order = 1;

 while(v != NULL)

 { for (c=1,u = v->next; u!NULL && u->score==v->score; c++, u=u->next);

  printf("$4d%7d%8d ",order,v->score,c);

  for(order += c,i = 1;__(5)__;v = v->next,i++)

  { if (i>1 && i%5 == 1) printf("\n% 23c",' ');

   printf("%s",v->no);

  }printf("\n");

 }

试题六

  阅读以下程序说明和 FORTRAN 程序,将应填入_(n)_处的字句,写在答卷的对应栏内。

[程序说明]

  本程序用以将 m+n 个元素的数组 A 中的前 m 个元素 (A(1)-A(m)) 与后 n 个元素 (A(m+l)-A(m+n)) 互换位置,并保持其各自原有的内部顺序。

  程序中把数组的各元素看成首尾相连的序列,并将数组元素分成 G 组( G 为 m 和 n 的最大公因子),每组中的元素序列是从数组某元素起由间隔为 m 的元素组成,再将每组元素依次循环向左传送,即得所需结果。

  例如原数组 A 为:

7 9 6 2 8 4

m

n

由 m=4,n=2,求得 G=2,将A中的元数分成两组。按上述说明,第一组元素序列依次为 A(1)、A(5)、A(3),将它们循环向左传送后的结果为

8

9

7

2

6

4

  第二组元素序列依次为以 A(2)、A(6)、A(4),将它们循环向左传送后的结果为

8

4

7

9

6

2

即得所需结果。

[程序]

   INTEGET A(1000), G,H

   READ(*,*)M,N

   READ(*,*)(A(1),1=1,M+N)

   G=M

   H=N

20  IF (G,NE,H)THEN

    IF(G,GT,T)THEN

     G=G-H

    ELSE

     H=H-G

    ENDIF

    GOTO 20

   ENDIF

   DO 100 I=_(1)_

    TEMP=A(1)

    K=1

30   J=_(2)_

    IF(J,NE,1)THEN

     A(K)=_(3)_

     K=J

     _(4)_

    ELSE

     A=K=_(5)_

    ENDIF

100  CONTINUE

   WRITE(*,200)(A(I),I=1,M+N)

200  FORMANT(1016)

   END

  从下列的2道试题(试题七至试题八)中任选1道解答。如果解答的试题数超过1道,则题号小的1道解答有效。

 

试题七

  阅读以下程序说明和 C 程序,将应填入_(n)_处的字句,写在答卷的对应栏内。

[程序说明]

  本程序的函数

     sum(int,i int total,int sigma,int rear,int d[],int n)

用来从已知数组 d 的前 n 个元素中找出所有部分元素序列之和等于 total 的元素序列,约定数组 d 的元素都是正整数,且都小于等于 total。

  函数 sum 使用递归方法找出全部解答。参数 i 表示递归函数当前考虑元素 d[i],参数 sigma 是调用前已选取的部分序列的元素和,参数 rear 是后面还未考虑的那部分元素的元素和。

  函数对元素 d[i] 有两种可能的选择方案:

  1.考虑元素 d[i] 被包含在新的部分元素序列中的可能性。如果在当前部分元素序列之后接上 d[i],新序列的元素和不超过 total,则函数将 d[i]包含在当前部分元素序列中。如果新的部分元素序列的元素和等于 total时,新的部分元素序列就是一个解答,函数将其输出;否则,若继续考虑后面的元素还有可能找到解答时,函数就递归去考虑后面的元素,寻找解答。最后,函数应恢复原来部分元素序列中不包含 d[i]的状态。

  2.考虑元素 d[i] 不被包含在新的部分元素序列中的可能性。如果继续向 d[i] 之后考虑还是有希望能得到和为 total 的部分元素序列时,函数将新序列不包含 d[i] 也作为一种可能的选择,并递归去考虑后面的元素,寻找解答。

[程序]

#include 〈stdio.h〉

#define N 100

int a[N];

int flg[N];

sum (int i,int total,int sigma,int rear,int d[],int t)

{ int j;

 /* 考虑元素d[i]被包含在新的部分元素序列中的可能性 */

 if (sigma + d[i] <= total  /* 如果d[i]与当前序列的和不超过total*/

 { flg[i] = 1; /* d[i]被考虑在被部分元素序列中 */

   if(__(1)__ == total)

   { /* 输出解 */

    for (j = 0; flg[j] == 0; j++);

    printf("%4d = %d",total,d[j]);

    for(j++; j <= i; j++)

     if (flg[j])

       printf("+%d",d[j]);

   printf("\");

  }

  else /* 并且继续考虑后面的元素有可能找到解答时 */

  if(i < n-1 && rear+sigma >= total)

    sum(i+1,total,__(2)__,rear-d[i],d,n);

  __(3)__;

 /* 考虑元素d[i]不被包含在新的部分元素序列中的可能性。*/

 if (i < n-1 && rear-d[i]+tigma >= total)

     sum(i+1,total,__(4)__ ,rear-d[i],d,n);

}

main()

{ int i,j,n,total,s,d;

 printf("输入 total!/n"); scanf("%d",&total);

 printf("输入 n!/n"); scanf("%d",&n);

 for (s = i = 0; i<n;)

 { printf ("输入第%d个元素 > 0 且 <= %d)\n",i+1,total);

  scanf ("%d",&d);

  if( d < 1 || d > total)

   { printf("出错,请重新输入!\n");

    contnue;

   }

   s += a[i++] = d;

 }

 sum(0,total,0,__(5)__,a,n);

 printf ("\n\n");

}

试题八

  阅读以下程序说明和FORTRAN程序,将应填入_(n)_处的字句,写在答卷的对应栏内。

[程序说明]

  本程序用以查找给定数组 A 的第 K 小元素。程序执行后,第 K 小元素存放在数组元素 A(K) 中。

  设给定的数组中各元素 A(i)=(i=1,2…N) 互为不相等。它的第 K(1≤k≤N) 小元素是指这样的元素;它大于N个元素中的 K-1 个元素,而小于其余的 N-K 个元素。假如,假设 N=8,数组 A 为:

44 94 12 50 55 6 18 67

它的第 5 小元素(即 K=5 )是 50。

  本程序的处理过程如下:

  将 A(K) 的值(此例为 A(5),此时值为 55 )存入 X,从左向右扫描,直至遇以第一个不小于 X 的元素(此时为 94 ),再从右向左扫描,直到遇见第一个不大于 X 的元素(此时为 18 ),然后交换这两个元素,数且 A 成为:

44 18 12 50 55 6 94 67

继续这一“扫描与交换”的过程,直到两个方向的扫描在数组中间的某处汇合。此时数组被分成两段,汇合点左边的元素均小于汇合点右边的元素。然后选取存在第 K 小元素的一段,重复上述扫描、交换和调整扫描范围的处理过程。程序中采用 L、R 来表示扫描的范围的左右边界。开始时 L 为 1,R 为 N,以后逐次调整。当变成为L值不小于 R 值时,A[K] 即是第K小元素。

[程序]

   SUBROUTINT FIND(A,N,K)

   INTEGET A(N),R,X,W

   L=1

   R=N

20  IF (L .LT. R)THEN

    X=A(K)

    I=L

    J=R

30   IF(A(1) .LT. X)THEN

     I=I+1

     GOTO 30

    ENDIF

40   IF(___(1)___)THEN

     ___(2)___

     GOTO 40

    ENDIF

    IF(I .LE. J)THEN

     W=A(I)

     ___(3)___

     I=I+1

     ___(4)___

    IF(I .LE. J)___(5)___

    ENDIF

    IF(J .LT. K) L=I

    IF(___(6)___) R=___(7)___

    GOTO 20

   ENDIF

   RETURN

   END

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