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)。