2019年下半年程序员考试下午真题(专业解析+参考答案)

第 1 题

阅读以下说明和流程图,填写流程图中的空缺,将解答填入答题纸的对应栏内。
【说明】
某系统中有N个等长的数据记录,其主键值为随机排序且互不相等的正整数编号,表示为K(0),K(1),…,K(N-1)。现采用杂凑法将各数据记录存入区域S(0),S(1),S(2),…,S(M-1)中(M≥N),以加快按主键值检索的效率(初始时各区域都是空的)。
下面流程图中,选用适当的质数P(N≤P≤M),对每个主键值先计算出它除以P的余数j。如果区域S(j)已占用,则考查下一个区域S(j+1),……,直到发现某个区域为 空时,则将该主键值相应的数据记录存入该区域(注意,S(M-1)的下一个区域是S(0))。 为了标记每个区域是否已占用,采用了M个标记位F(0),F(1),…,F(M-1)。初始时所有的标记位都为0,每当一个区域被占用时,将相应的标记位置1。
例如,设6个记录的主键值分别为31、15、20、35、18、10,取质数P=7,用上述杂凑法将这些记录存入区域S(0)~S(7)后,各区域中记录的主键值依次为35、15、空、31、18、10、20、空。
【流程图】

注1:“循环开始”框内给出循环控制变量的初值、终值和增值(默认为1),
格式为:循环控制变量=初值,终值[,增值]
注2:函数int(x)为取x的整数部分,即不超过x的最大整数。


答案与解析

  • 试题难度:一般
  • 知识点:C程序设计>C程序设计
  • 试题答案:

    (1)K(i)/P或等效形式
    (2)0
    (3)1→F(j)或F(j)=1或等效形式
    (4) j+1→j或j=j+1或j++或等效形式
    (5)0→j或j=0或等效形式

  • 试题解析:

    本题旨在考查程序设计(算法流程图设计)的能力。
    杂凑法是大数据处理时常用的数据存储检索方法,其检索效率很高。
    本流程图中,将依靠循环i=0,1,…,N-1,依次将主键值为K(i)的记录存入适当的区 域S(j)中。
    首先,需要求出K(i)除以质数P的余数j,采用的方法是计算K(i)-P*int(K(i)/P)。例 如,对于P=7,31/7的商的整数部分为4,所以31除以7的余数为31-7×4=3。因此流程图中的空(1)应填写K(i)/P或其等效形式。
    然后判断区域S(j)的标志位F(j)是否为0,即空(2)应填写0。
    如果F(j)=0则表示区域S(j)为空,可以将K(i)直接存入区域S(j)中,并将F(j)置1表示已被占用,即空(3)应填写1→F(j)。
    如果F(j)非0,则表示S(j)已占用,需要考虑下一个区域是否为空。也就是说,需要 将j增1,即空(4)应填写j+1→j。如果j增1后已超越最后一个区域,则需要考虑返回区域S(0)。也就是说,当j=M时,需要执行0→j,即空(5)应填写0→j。

第 2 题

阅读以下C代码,回答问题1至问题3,将解答写入答题纸的对应栏内。

【C代码1】

#include<stdio.h>
int main()
{
int num = 5 ;
printf("%d\n",++num);
printf("%d\n",num++);
printf("%d\n",num--);
printf("%d\n",num);
return 0;
}



【问题1】(4分)
请给出C代码1运行后的输出结果。
【问题2】(6分)
已知字符'a’的ASCII码值为十进制数97,请给出调用C代码2中函数func('a')后的输出结果。
【问题3】(5分)
请给出调用C代码3中函数test()后的输出结果。

答案与解析

  • 试题难度:一般
  • 知识点:C程序设计>C程序设计
  • 试题答案:

    【问题1】
    6
    6
    7
    6
    【问题2】
    a:97
    c:99
    e:101
    【问题3】
    BCDEF
    CDEF
    DEF
    EF
    F

  • 试题解析:

    本题考查考生对C程序基本语句和控制结构的理解和应用。
    C代码1主要考查前置自增(自减)和后置自增(自减)运算的含义。自增(自减)运算是C程序中频繁使用的运算,其含义是将变量的值增加1(减去1)。前置自增时,是将变量的值增加1,增1后变量的值作为表达式的值;后置自增时,是先取变量的值作为表达式的值,然后将变量的值增加1,自减运算同理。本代码段中,num的初始值为5,经过前置自增运算“++num”之后,num的值变为6,该表达式(++num)的值也是num自增后的值,即第一个printf输出6。对于表达式“num++”,是对num进行后置自增,该表达式的值取num自增之前的值(即6,即第二个printf输出6),而num的值变为7。接下来在printf中进行后置自减运算“num--”,此时表达式的运算结果是num自减之前的值(即7,即第三个printf输出7),而num的值会改变为6,因此第4个printf 输出6。
    C代码2主要考查针对字符运算的单重循环控制。字符数据的内部表示是其编码, 例如字符'a'的ASCII码值为97,输出时的格式控制串为"%c:%d"时,要求以字符方式和十进制数值方式输出,因此可看到输出结果为a:97。字符集中对数字、字母的编码都是 连续的,因此ch表示字符'a'时,ch+2就表示字符'c',以此类推。
    C代码3主要考查针对字符运算的双重循环控制。外层循环控制变量raw取值范围为0~5(等于5时结束循环),内层循环控制变量ch的取值范围为符‘B’+row~‘B’+5(等 于‘B’+5即‘G’时结束内层循环),如下表所示。


第 3 题

阅读以下说明和C代码,填写程序中的空缺,将解答写入答题纸的对应栏内。
【说明】
规定整型数组a中的元素取值范围为[0,N),函数usrSort( int n, int a[] )对非负整型数组a的前n个元素进行计数排序。排序时,用temp_arr[i]表示i在数组a中出现的次数, 因此可以从0开始按顺序统计每个非负整数在a中的出现次数,然后对这些非负整数按照从小到大的顺序,结合其出现次数依次排列。
例如,对含有10个元素{0,8,5,2,0,1,4,2,0,1}的数组a[]排序时,先计算出有3个0、2 个1、2个2、1个4、1个5和1个8,然后可确定排序后a的内容为{0,0,0,1,1,2,2,4,5,8}。
下面代码中用到的memset函数的原型如下,其功能是将p所指内存区的n个字节都设置为ch的值。

void*memset (void *p, int ch, size_t n);


【C代码】

#include<stdio.h>
#include<stdlib.h>
#include<string.h>


#define N 101


void printArr(int a[],int n);
void usrSort(int n,int a[]);


int main()
{
      int a[10]={0,8,5,2,0,1,4,2,0,1};

       printArr (a,sizeof(a)/sizeof(int));
     (   1  )     _;             //调用usrSort()对数组a进行升序排序
printArr ( a,sizeof(a)/sizeof(int) );
return 0;
}
void printArr (int a[],int n)
{
     int i;
     for(i=0;i<n;i++)
             printf("%d ", a[i]);
     printf("\n");
}

void usrSort(int n, int a[])
{
      int i,k;
      int *temp_arr;        //用temp_arr[i]表示i在a中出现的次数
      temp_arr=(int *)malloc(N*sizeof(int) );
      if(!temp_arr) return;
      //将所申请并由temp_arr指向的内存区域清零
     memset(_   (2)   _);
     for(i=0;i<n;i++)
           temp_arr[_(  3   )    ]++;
     k=0;
     for(i=0;i<N;i++){
           int cnt;                          //cnt表示i在数组a中的出现次数
    (  4   )  ;
          while(cnt>0){
                    a[k]=i;                //将i放入数组a的适当位置
   (   5   )  ;
                    cnt--;
           }
     }
     free(temp_arr);
}



答案与解析

  • 试题难度:一般
  • 知识点:C程序设计>C程序设计
  • 试题答案:

    (1) usrSort(10,a)或等效形式,a可替换为&a,&a[0]。
    (2) temp_arr,0,N*sizeof(int)或等效形式,其中N和sizeof(int)可替换为101、4。
    (3) a[i]或*(a+i)或等效形式
    (4) cnt = temp_arr[i]或cnt= *(temp_arr+i)或等效形式
    (5)k++或++k或k=k+1或k+=1或等效形式

  • 试题解析:

    本题考查考生对C程序基本结构、函数定义及调用和运算逻辑的理解和应用。
    根据空(1)所在语句的注释,明确是对函数usrSort进行调用。usrSort的原型声明为“void usrSort(int n, int a[])",第一个参数表示需要排序的元素个数,第二个参数表示对哪个数组进行排序,题目中,需要对含有10个元素的数组进行排序,因此 空(1)应填入“usrSort(10,a)” 或其等效形式

。注意:第二个参数需要传入的数组(数组首地址),用数组名数组名或下标为0的数组元素取地址都可以,因此。
空(2)所在语句是调用memset对申请的存储区域进行初始化。根据注释,要求将 temp_arr指向的内存区域清零,根据声明memset时的定义, voidmemset (void p, int ch, size_t n); , 此处需要对temp_arr

所指向的空间区域的元素值都设置为0,而总king就可以结合语句:temp_arr=(int )malloc(Nsizeof(int) );,表示temp_arr占用空间为Nsizeof(int),可知函数调用为memset ( temp_arr , 0 , N sizeof ( int ) ) 。
空(3)所在的循环语句遍历数组a[]的所有元素,将元素a[i]作为temp_arr的下标, 从而使得temp_arr[a[i]]表示了a[i]表示的值在数组a中出现的次数。例如:数组a中函数元素1,则需要temp_arr[1]的值+1, 数组a中函数元素5,则需要temp_arr[5]的值+1。
空(4)、(5)主要是通过temp_arr中的元素取值情况来对数组a中元素进行重排,假设tem_arr[0]=3,则表示0元素出现了3次。首先用cnt保留元素出现的次数, 可知空(4)处应设置cnt的初始值,为“temp_arr[i]”。 当cnt>0时,表示元素i出现的次数超过了1次,需要进行循环填入, 每在数组中放入1个i元素后,cnt自减(表明还需要放置的次数要减1),而k需要自增(表明元素放置位置要往后一个),以给出下一个i要放入的数组位置,因此空(5)处应填入“k++”或其等效形式。</p>

第 4 题

阅读以下说明和C代码,填写程序中的空缺,将解答写入答题纸的对应栏内。

函数strCompress(char *s)对小写英文字母串进行压缩,其基本思路是:如果串长小于3则不压缩,否则对连续出现的同一字符,用该字符及其个数来表示。例如,字符串"abbbcdddddddeeed"压缩后表示为"ab3cd7e3d"。
如图4-1所示,在计算连续出现的同一字符个数时,借助字符指针s和计数变量k表示串中的字符,当s所指字符与其后的第k个字符不同时,一个重复字符串的压缩参数即可确定。 

【C代码】
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void strCompress(char *);

int main()
{
     char test[]= "abbbcdddddddeeed";

     printf("%s\n", test);
(1);        //调用strCompress实现test中字符串的压缩
    printf("%s\n",test);

    return 0;
}

void strCompress(char *str)
{
int  i;
     char *p,tstr[11];              //在tstr中以字符串方式表示同一字符连续出现的次数
     char *s =str,*buf;           //借助buf暂存压缩后的字符串

     if(strlen(str)<3)
           return;

   buf =(char *)malloc(strlen(str)*sizeof(char)+1);
   if(!buf)
           return;
   for(i=0;*s;){
int k=1;                                      //用k累计当前字符的连续出现次数

          buf[_(2)_]=*s;                 //先将当前字符写入buf[]
          if(s[1]&&*s==*(s+1)){
                 k++;
                 while(_(3)_)k++;

                sprintf(tstr, "%d", k);                     //将k的值转换为数字串暂存在tstr中

               //将暂存在tstr中的数字字符逐个写入buf[]
              p =tstr;
              while(*p)
                    buf [i++]=_(4)_;
       }
       s+=k;           //跳过连续出现的同一字符,使s指向下一个不同的字符
}

     (5)='\0';                    //设置字符串结尾
     strcpy(str,buf);    //将暂存在buf中的压缩字符串复制给原串

     free(buf);
}

答案与解析

  • 试题难度:一般
  • 知识点:C程序设计>C程序设计
  • 试题答案:

    (1)strCompress(test)或strCompress(&test[0])或等效形式
    (2)i++
    (3)*s==*(s+k)或s[0]=s[k]或*(s+k)&&*s==*(s+k)或s[k]&&s[0]==s[k]或等效形式
    (4)*p++或等效形式
    (5)buf[i]或buf[i++]或*(buf+i)或等效形式
    注意:从试题五和试题六中,任选一道题解答。

  • 试题解析:

    本题考查C程序流程控制和字符串处理及指针的应用。
    空(1)处实现对函数strCompress 的调用,根据strCompress 的声明和定义(void strCompress(char *str)要求实参提供字符存储的地址,main函数中的字符数组test保存了需要压缩的字符串,因此空(1)应填入“strCompress(test)”或其等效形式。
    在函数strCompress中,其方式为:
    ①将首个字符存在 buf数组第一个位置中
    ②计算该字符出现的次数,用k表示。此处计算时用if if(s[1]&&*s==*(s+1)) 先做初步判断,当*s==*(s+1)表示当前位置第一个字符等于第二个字符,说明有多次出现,k值+1,如果不成立,表示该字符只出现了一次,跳过if中间的过程,直接往下一个不同字符进行判定。
    当出现重复字符时,此时还要判断后面是否有重复的字符,且用k进行计数该字符出现的次数。所以第(3)空用*s==*(s+k)表示后面字符与该字符是否相同,如果相同,k值+1,直到出现不同的字符,结束循环。循环结束后,要将k值赋给buf数组中,所以用用sprintf函数将k转为字符串,然后将暂存在tstr中的数字字符逐个写入 buf数组,所以第(4)空为buf[i++]=*p++,将k对应的字符串存入到buf的下一个位置。
    ③下一个不同字符同样想要进行赋值到buf中,但是赋值位置是之前字符的后一个位置,所以(2)填的是i++。然后对于下一个不同字符的初始位置要做下判断,例如:假设是“aaab”那么下一个不同字符是在s+3的位置,如果是“ab”那么下一个不同字符是在s+1的位置,所以此处其不同字符的偏移量是由k(前一个字符的重复次数)所确定,表示为s+k,所以用s+=k; 表示跳过连续出现的同一字符,使s指向下一个不同的字符。
    接下来就是重复第②、③的过程,直到字符串结束。设置buf数组末尾为字符串结束标记,由于每次在buf[] 中写入字符时都对下标i进行了自增,for循环结束后,buf[i]即表示压缩字符串最后一个字符之后的位置,因此第(5)空用buf[i]='\0'表示设置字符串结尾。

第 5 题

阅读以下说明和Java代码,填写代码中的空缺,将解答写入答题纸的对应栏内。

【说明】
球类比赛记分系统中,每场有两支球队(Team)进行比赛(Game),分别记录各自的得分。图5-1所示为记分系统的类图。



【Java代码】


答案与解析

  • 试题难度:一般
  • 知识点:Java程序设计>Java程序设计案例
  • 试题答案:

    (1)int goals =0或int goals
    (2)this.name
    (3)goals++或++goals或等价表示
    (4)Team
    (5)new Game(t1,t2)

  • 试题解析:

    本题考查考生应用Java语言进行程序设计的能力,涉及类、对象、方法的定义和相关操作。要求考生根据给出的案例和代码说明,阅读并完成程序填空。
    本题中涉及比赛和球队。根据说明进行设计,题目给出了类图(图5-1类图所示)。
    图中类Game和Team之间是聚合关系。Game类有两个public的方法:getResults()和incrementGoal()分别表示获取比赛结果和某支球队进1球后增加比分;private属性是参加比赛的两支球队。Team类中有3个public方法,分别为本球队进1球后增加得分、获得本队得分和获得球队名称;private的属性为球队名称和得分。球队名采用String类型,得分信息从上下文可知是goals,用int类型。
    在Team对象创建时,初始化球队名称和得分。Java中,对象的属性若为基本数据类型int,自动初始化为0,如果有显式初始化执行显式初始化;对象的属性若为引用类型String,自动初始化为null,所以需要在构造器中对球队名称加以显式初始化。其构造器接收球队名称,参数名称与对象的属性名均为name,用this关键字加以区分。其中this 关键字用来引用当前对象或类实例,可以用点取属性或行为,即:
    this.name = name;
    注:没有同名时是否有this.都表示名称所表示的对象属性。
    从方法getGoals()中return goals;判断,缺少属性goals来表示得分。再从上下文判断,方法increamentGoal()中,表示在比赛中某球队进1球,即goals的值增加1。
    创建Game对象表示两支球队的一场比赛。构造器参数为两支球队,用以初始化 Game对象的两个属性。方法getResults()用于输出当前比分。方法incrementGoal()用于表示一球队进1球,具体是哪支球队由参数给定,所以参数类型为Team。
    主控逻辑代码在Game类中程序主入口main()方法中实现。在main()方法中,先创建两支球队(用new关键字),即两个Team类的对象,球队名称分别为“TA”和“TB”, 引用名称分别为t1和t2,即:
    Team t1 = new Team("TA");
    Team t2 = new Team("TB");
    以这两个对象引用名称为参数,创建一场比赛对象(用new关键字),引用名称为 football,即:
    Game football = new Game(t1,t2);
    然后用:
    football.incrementGoal(t1);
    football.incrementGoal(t2);
    分别表示球队TA进一球,球队TB进一球。然后调用getResults()方法输出此时的比分,即:
    football.getResults();
    然后TB再进一球,再调用getResults()方法输出此时的比分,即:
    football.incrementGoal(t2);
    football.getResults();
    综上所述,空(1)需要定义表示一支球队的得分goals并初始化为0,题目代码中已经给出用分号结尾,所以空(1)为int goals或int goals=0;空(2)需要表示Team对 象的name属性,即this.name;空(3)需要表示当前球队得分加1,因为只有一条语句,只要表示goals加1即可,即goals++或++goals(等价表示);空(4)需要表示参数类型为球队,即Team;空(5)处为创建Game类的对象football,需要两个Team类型对象的引用,从其后面语句可知,两个引用名称为t1和t2,即new Game(t1,t2)。

第 6 题

阅读下列说明和C++代码,填写代码中的空缺,将解答写入答题纸的对应栏内。
【说明】
球类比赛记分系统中,每场有两支球队(Team)进行比赛(Game),分别记录各自的得分。图6-1所示为记分系统的类图。

【C++代码】


答案与解析

  • 试题难度:一般
  • 知识点:C++程序设计>C++程序设计
  • 试题答案:

    (1) int goals或int goals= 0
    (2)this->name
    (3)goals++或++goals或等价表示
    (4)Team*
    (5)new Game(t1, t2)

  • 试题解析:

    本题考查考生应用C++语言进行程序设计的能力,涉及类、对象、函数的定义和相关操作。要求考生根据给出的案例和代码说明,阅读并完成程序填空。
    本题中涉及比赛和球队。根据说明进行设计,题目给出了类图(图6-1类图所示)。
    图中类Game和Team之间是聚合关系。Game类有两个public的函数:getResults() 和incrementGoal:分别表示获取比赛结果和某支球队进1球后增加比分;private属性就是参加比赛的两支球队。Team类中有3个public函数,分别为本球队进1球后增加得分、获得本队得分和获得球队名称;private的属性为球队名称和得分。球队名采用string类型,得分信息从上下文可知是goals,用int类型。
    在Team对象创建时,初始化球队名称和得分。C++11标准之后,对象的属性定义时才可显式初始化;对象的属性name类型为string,需要在构造器中对球队名称加以显式初始化。其构造器接收球队名称,参数名称与对象的属性名均为name,用this关键字加以区分。其中this关键字用来引用当前对象或类实例,可以用->取属性或行为,即:
    this->name = name;
    this->goals =0;
    注:没有同名时是否有this->都表示名称所表示的对象属性。
    从函数getGoals()中的return goals判断,缺少属性goals来表示得分。再从上下文判断,函数increamentGoal()中,表示在比赛中某球队进1球,即goals的值增加1。
    创建Game对象表示两支球队的一场比赛。构造器参数为两支球队,用以初始化 Game对象的两个属性。函数getResults()用于输出当前比分。函数incrementGoal()用于表示一支球队进1球,具体是哪支球队由参数给定,所以参数类型为Team*。
    主控逻辑代码在程序主入口函数main()中实现。在main()函数中,先创建两支球队(用new关键字),即两个Team类的对象指针,球队名称分别为“TA”和“TB”,指针名称分别为t1和t2,即:
    Team *t1 = new  Team("TA");
    Team *t2 = new  Team("TB");

    以这两个对象指针名称为参数,创建一场比赛对象(用new 关键字),指针名称为 football,即:
    Game *football = new Game(t1,t2);
    然后用:
    football->incrementGoal(t1);
    football->incrementGoal(t2);
    表示球队TA进一球,球队TB进一球。然后调用getResults()函数输出此时的比分,即:
    football->getResults ();
    然后TB再进一球,再调用getResults()函数输出此时的比分,即:
    football->incrementGoal(t2);
    football->getResults() ;
    综上所述,空(1)需要定义表示一支球队的得分goals,题目代码中已经给出用分号结尾,所以空(1)为int goals(或c++11标准之后int goals=0也支持);空(2)需要表示Team对象指针的name属性,即this->name;空(3)需要表示当前球队得分加1, 因为只有一条语句,只要表示goals加1即可,即goals++或++goals(等价表示);空(4)需要表示参数类型为球队指针,即 Team*;空(5)处为创建Game类的对象football, 需要两个Team类型对象的指针,从其后面语句可知,两个指针名称为t1和t2,即new Game(t1, t2)。

results matching ""

    No results matching ""