全国计算机技术与软件专业技术资格初级程序员下半年下午试题.docx
《全国计算机技术与软件专业技术资格初级程序员下半年下午试题.docx》由会员分享,可在线阅读,更多相关《全国计算机技术与软件专业技术资格初级程序员下半年下午试题.docx(18页珍藏版)》请在冰豆网上搜索。
![全国计算机技术与软件专业技术资格初级程序员下半年下午试题.docx](https://file1.bdocx.com/fileroot1/2022-11/24/293c2ffc-614f-485f-8907-32451e868e82/293c2ffc-614f-485f-8907-32451e868e821.gif)
全国计算机技术与软件专业技术资格初级程序员下半年下午试题
第2章程序员下午试题分析与解答
试题一
阅读以下说明和流程图,填补流程图中的空缺
(1)~(5),将解答填入对应栏内。
【说明】
下面流程图的功能是:
在已知字符串A中查找特定字符串B,如果存在,则输出B串首字符在A串中的位置,否则输出-1。
设串A由n个字符A(0),A
(1),…,A(n-1)组成,串B由m个字符B(0),B
(1),…,B(m-1)组成,其中n≥m>0。
在串A中查找串B的基本算法如下:
从串A的首字符A(0)开始,取子串A(0)A
(1)…A(m-1)与串B比较;若不同,则再取子串A
(1)A
(2)…A(m)与串B比较,依次类推。
例如,字符串“CABBRFFD”中存在字符子串“BRF”(输出3),不存在字符子串“RFD”(输出-1)。
在流程图中,i用于访问串A中的字符(i=0,1,…,n-1),j用于访问串B中的字符(j=0,1,…,m-1)。
在比较A(i)A(i/1)…A(i+m-1)与B(0)B
(1)…B(m-1)时,需要对A(i)与B(0)、A(i+1)与B
(1)、…、A(i+j)与B(j)等逐对字符进行比较。
若发现不同,则需要取下一个子串进行比较,依此类推。
【流程图】
参考答案
(1)j+1
(2)i+1(3)0(4)i(5)-1
[分析]
本题采用的是最简单的字符子串查找算法。
在串A中查找是否含有串B,通常是在串A中从左到右取逐个子串与串B进行比较。
在比较子串时,需要从左到右逐个字符进行比较。
题中已设串A的长度为n,存储数组为A,动态指针标记为i;串B的长度为m,存储数组为B,动态指针标记为j。
如果用伪代码来描述这种算法的核心思想,则可以用以下的两重循环来说明。
外循环为:
Fori=0ton-mdo
A(i)A(i+1)...A(i+m-1)~B(0)B
(1)...B(m-1)
要实现上述比较,可以采用内循环:
Forj=0tom-1do
A(i+j)~B(j)
将这两重循环合并在一起就是:
Fori=0ton-1do
Forj=0tom-1do
A(i+j)~B(j)
这两重循环都有一个特点:
若发现比较的结果不相同时,就立即退出循环。
因此,本题中的流程图可以间接使用循环概念。
初始时,i与j都赋值0,做比较A(i+j)~B(j)。
若发现相等,则继续内循环(走图的左侧),j应该增1,继续比较,直到j=m为止,表示找到了子串(应输出子串的起始位置i);若发现不等,则退出内循环,继续开始外循环(走图的右侧),j应恢复为0,i应增1,继续比较,直到i>n-m为止,表示不存在这样的子串(输出-1)。
在设计流程图时,主要的难点是确定循环的边界(何时开始,何时结束)。
当难以确定边界值变量的正确性时,可以用具体的数值之例来验证。
这是程序员应具备的基本素质。
试题二
阅读以下说明和C程序代码,将应填入(n)处的字句写在对应栏内。
【说明】
下面C程序代码的功能是:
对于输入的一个正整数n(100≤n<1000),先判断其是否是回文数(正读反读都一样的数)。
若不是,则将n与其反序数相加,再判断得到的和数是否为回文数,若还不是,再将该和数与其反序数相加并进行判断,依此类推,直到得到一个回文数为止。
例如,278不是回文数,其反序数为872,相加后得到的1150还不是回文数,再将1150与其反序数511相加,得到的1661是回文数。
函数intisPalm(longm)的功能是:
将正整数m的各位数字取出存入数组中,然后判断其是否为回文数。
若m是回文数则返回1,否则返回0。
【C程序代码】
#include<stdio.h>
#include<stdlib.h>
intisPalm(longm)
{/*判断m是否为回文数*/
inti=0,k=0;
charstr[32];
while(m>0){/*从个位数开始逐个取出m的各位数字并存入字符数组str*/
str[k++]=
(1)+'0';
m=m/10;
}
for(i=0;i<k/2;i++)/*判断str中的k个数字字符序列是否是回文*/
if(str[i]!
=str[
(2)])return0;
return1;
}
intmain()
{
longn,a,t;
printf("inputapositiveinteger:
");scanf("%ld",&n);
if(n<100||n>=1000)return-1;
while((3)){/*n不是回文数时执行循环*/
printf("%ld->",n);
for(a=0,t=n;t>0;){/*计算n的反序数并存入a*/
a=(4)*10+t%10;t=t/10;
}/*endoffor*/
n=(5);/*与反序数求和*/
}/*endofwhile*/
printf("%id\n",n);
system("pause");return0;
}
参考答案
(1)m%10,或其等价表示
(2)k-1-i
(3)!
isPalm(n),或isPalm(n)!
=1,或isPalm(n)==0(4)a(5)n+a
[分析]
本题考查C程序设计的基本能力。
函数isPalm(longm)的功能是判断m是否为回文数,其方法是先将m的各位数字依次取出转换为对应的数字字符保存在数组str中,然后再判断str中的字符序列是否对称。
代码如下:
while(m>0){/*从个位数开始逐个取出m的各位数字并存入字符数组str*/
str[k++]=m%10+'0';
m=m/10;
}
因此,空
(1)处应填入“m%10",将数m的个位数字取出。
以上while循环结束时,k的值即为m取初始值时的位数。
若需判断str[0]、str[1]、…、str[k-1]中的k个数字字符序列是否对称,则应依次比较str[0]与str[k-1]、str[1]与str[k-2]、…str[k/2-1]与str[k2+1]是否相等,若都相等,则是回文数;若其中有一处不等,则不是回文数。
代码如下:
for(i=0;i<k/2;i++)
if(str[i]!
=str[
(2)])return0;
因此,空
(2)处应填入“k-1-i”。
根据题目描述,从最初输入的数开始,直到得到一个回文数时结束,因此对于数n,调用函数isPalm(n),根据返回值确定n是否为一个回文数,空(3)处应填入“!
isPalm(n)”。
为了求一个数t的反序数,可从其个位数字开始,依次取出其各位数字并进行组合。
下面以t=345举例说明通过整除取余“%”、整除“/”取出各位数字并组合出543的过程。
初始时:
a=0t=345
下一步:
345%10=>5a*10+5=>a=5t/10=345/10=>t=34
下一步:
34%10=>4a*10+4=>a=54t/10=34/10=>t=3
下一步:
3%10=>3a*10+3=>a=543t/10=3/10=>t=0
因此,可知空(4)处应填入“a”。
最后数n与其反序数a相加得到新的数,继续产生回文数的过程。
空(5)处应填入“n+a”。
试题三
阅读以下说明和C函数,将应填入(n)处的字句写在对应栏内。
【说明】
已知某二叉树的非叶子结点都有两个孩子结点,现将该二叉树存储在结构数组Ht中。
结点结构及数组Ht的定义如下:
#defineMAXLEAFNUM30
structnode{
charch;/*当前结点表示的字符,对于非叶子结点,此域不用*/
char*pstr;/*当前结点的编码指针,非叶子结点不用*/
intparent;/*当前结点的父结点,为0时表示无父结点*/
intlchild,rchild;
/*当前结点的左、右孩子结点,为0时表示无对应的孩子结点*/
};
structnodeHt[2*MAXLEAFNUM];/*数组元素Ht[0]不用*/
该二叉树的n个叶子结点存储在下标为1~n的Ht数组元素中。
例如,某二叉树如果其存储结构如下图所示,其中,与叶子结点a对应的数组元素下标为1,a的父结点存储在Ht[5],表示为Ht[1].parent=5。
Ht[7].parent=0表示7号结点是树根,Ht[7].child=3、Ht[7].rchild=6分别表示7号结点的左孩子是3号结点、右孩子是6号结点。
如果用0或1分别标识二叉树的左分支和右分支(如上图所示),从根结点开始到叶子结点为止,按所经过分支的次序将相应标识依次排列,可得到一个0、1序列,称之为对应叶子结点的编码。
例如,上图中a,b,c,d的编码分别是100,101,0,11。
函数LeafCode(Ht[],n)的功能是:
求解存储在Ht中的二叉树中所有叶子结点(n个)的编码,叶子结点存储在Ht[1]~Ht[n]中,求出的编码存储区由对应的数组元素pstr域指示。
函数LeafCode从叶子到根逆向求叶子结点的编码。
例如,对上图中叶子结点a求编码的过程如下图所示。
typedefenumStatus{ERROR,OK}Status;
【C函数】
StatusLeafCode(structnodeHt[],intn)
{
intpc,pf;/*pc用于指出树中的结点,pf则指出pc所对应结点的父结点*/
inti,start;
chartstr[31]={'\0'};/*临时存储给定叶子结点的编码,从高下标开始存入*/
for(i=1;
(1);i++){/*对所有叶子结点求编码,i表示叶结点在HT数组中的下标*/
start=29;
pc=i;pf=Ht[i].parent;
while(pf!
=
(2)){/*没有到达树根时,继续求编码*/
if((3).lchild==pc)/*pc所表示的结点是其父结点的左孩子*/
tstr[--start]='0';
else
tstr[--start]='1';
pc=(4);pf=Ht[pf].parent;/*pc和pf分别向根方向回退一层*/
}/*endofwhile*/
Ht[i].pstr=(char*)malloc(31-start);
if(!
Ht[i].pstr)returnERROR;
strcpy(Ht[i].pstr,(5));
}/*endoffor*/
returnOK;
}/*andofLeafCode*/
参考答案
(1)i<=n,或其等价表示
(2)0(3)Ht[pf],或(*(Ht+pf))
(4)pf(5)&tstr[start],或tstr+start
[分析]
本题考查C语言的基本控制结构、数组以及参数传递基础知识。
哈夫曼算法构造最优二叉树的过程如下。
(1)根据给定的n个权值{W1,W2,…,Wn}构成n棵二叉树的集合F={T1,T2,…,Tn},其中每棵二叉树Ti中只有一个带权为Wi的根结点,其左、右子树均空。
(2)在F中选取两棵根结点权值最小的树作为左、右子树构造一棵新的二叉树,且置新二叉树的根结点的权值为其左、右子树根结点的权值之和。
(3)在F中删除这两棵二叉树,同时将新得到的二叉树加入F中。
(4)重复
(2)和(3),直到F只含一棵树为止。
这棵树便是最优二叉树。
最优二叉树是从叶子到根构造起来的,每次都是先确定一棵二叉树的左、右子树,然后再构造出树根结点,因此,最优二叉树中只有叶子结点和分支数为2的内部结点。
若已知叶子的数目为n,则内部结点数比叶子少1,因此,整棵树所需的存储空间规模是确定的,可以采用数组空间来存储最优二叉树。
题目中已经指出该二叉树的n个叶子结点存储在下标为1~n的Ht数组元素中,同时举例说明父结点编号为0的结点式树根结点。
因此,空
(1)处应填入“i<=n”。
同时,除了根结点之外,每个结点都有唯一的父结点,因此到达树根的标志为结点的父结点编号为0,因此,空
(2)处应填入“0”。
根据代码中pc和pf的作用:
pc用于指出树中的结点,pf则指出pc所对应结点的父结点,则空(3)处应填入“Ht[pf]”,空(4)处填入“pf”使得pc回退至其父结点位置。
空(5)考查了标准函数的调用,对于函数strcpy(),其原型为char*strcpy(char*,constchar*)。
两个参数都是字符指针,根据代码中tstr的作用,应将tstr+start(tstr[start]~tstr[29]存放编码)作为实参调用strcpy,因此空(5)处应填入“tstr+start”或“&tstr[start]”。
试题四
阅读以下说明和C函数代码,回答问题并将解答写在对应栏内。
【说明】
著名的菲波那契数列定义式为
f1=1f2=1fn=fn-1+fn-2(n=3,4,…)
因此,从第1项开始的该数列为1,1,2,3,5,8,13,21,…。
函数fibl和fib2分别用递归方式和迭代方式求解菲波那契数列的第n项(调用fib1、fib2时可确保参数n获得一个正整数)。
【C函数代码】
【问题1】
函数fib1和fib2存在错误,只需分别修改其中的一行代码即可改正错误。
(1)函数fib1不能通过编译,请写出fib1中错误所在行修改正确后的完整代码。
(2)函数fib2在n≤2时不能获得正确结果,请写出fib2中错误所在行修改正确后的完整代码。
【问题2】
将函数fib1和fib2改正后进行测试,发现前46项都正确,而第47项的值是一个负数,请说明原因。
【问题3】
函数fib1、fib2求得菲波那契数列第n项(n>40)的速度并不相同,请指出速度慢的函数名,并简要说明原因。
[试题四分析]
本题考查C程序设计基础知识。
[问题1]
函数fib1不能通过编译,原因在于语句“fib1(n)=fib1(n-1)+fib1(n-2)”出错,该语句中fib1(n)、fib1(n-1)、fib1(n-2)都是函数调用,由于fib1是返回长整型数据的函数,所以不能为函数调用fib1(n)赋值。
该语句处应将fib1(n-1)+fib1(n-2)的值作为返回值,形式为“returnfib1(n-1)+fib1(n-2)”。
在函数fib2中,for语句从i等于3开始循环,用于计算菲波那契数列第3项及以后各项的值。
对于n等于1或2,for语句的循环体并不执行,因此对于第1、2项数列值,最后返回的f值是不确定的,为f赋初值1即可纠正该错误。
[问题2]
C语言提供的基本数据类型long所表示的整数数据范围为[-231,231-1],即-2147483648~2147483647,而菲波那契数列是单调递增的数列,因此函数fib1和fib2改正后运行时,只要项数n超过某个值,计算结果一定会溢出,此后的计算结果也不再正确了。
溢出情况发生时,原本是正数的计算结果表现为负数,或者原本是负数的计算结果表现为正数。
[问题3]
完成同一任务的递归计算与迭代计算过程的时空效率并不相同,一般来说,递归计算过程所占用的空间更多、计算时间更长。
这是由于递归函数执行过程中引起一系列的函数调用和返回,所以需要较多的时间开销(控制转移和存储空间管理操作所需的时间)及空间开销(每一次调用时为函数中的形式参数和自动局部变量分配存储空间等),因此与实现相同功能的非递归函数相比,运行效率较低。
参考答案
[问题1]
(1)returnfib1(n-1)+fib1(n-2);或return(fib1(n-1)+fib1(n-2));
(2)longf=1;或longf=(long)1;或longf=1L;
[问题2]
运算结果超出范围,或运算结果超出long型数据的最大值,或溢出
[问题3]
函数名:
fib1
原因:
递归调用时间消耗(或开销)更大,本递归函数包含大量重复计算
试题五
阅读以下应用说明、属性设置以及VisualBasic程序代码,将解答写在对应栏内。
【应用说明】
本应用运行时,由用户输入一个正整数n后自动产生n个正整数,然后按照用户的指定要求对该组数进行处理。
该应用的运行界面如下图所示:
1.窗体中有两个文本框。
(txtSrc,txtObj)、两个标签(lblSrc,lblObj)、三个命令按钮(cmdGendat,cmdProc,cmdQuit)和一个弹出式菜单(procMenu,初始时不可见)。
2.文本框txtSrc(由标签lblSrc提示)用于显示产生的数据,文本框txtObj(由标签lblObj提示)用于显示处理结果,要求每行显示一个整数。
3.程序启动时,命令按钮cmdProc(运算要求)不可用。
单击命令按钮cmdGendat(产生数据)后,提示用户输入一个n的值并生成n个正整数存入数组元素a
(1)~a(n),然后将数据逐行显示在txtSrc中,并设置命令按钮cmdProc可用。
4.单击命令按钮cmdProc(运算要求)后弹出菜单。
选择菜单项并单击后,进行相应处理并将结果显示在txtObj中,同时将lblObj的标题改为该菜单项表示的处理命令。
弹出式菜单“运算要求”的结构如下表所示:
标题
名称
层次
运算要求
procMenu
1
排序
Sorting
2
递增排序
Ascend
3
递减排序
Descend
3
找特殊数
SpecNum
2
中位数
MidNum
3
求均数
AvgNum
3
一个整数序列的中位数是指对该序列进行非递减(增)排列后最中间位置上的元素。
若序列长度为偶数,则取中间两个元素的平均值为其中位数。
【属性设置】
为实现单击命令按钮cmdProc后弹出“运算要求”菜单(procMenu),设计时需将procMenu的
(1)属性设置成false。
供
(1)选择的属性:
DefaultEnabledScaleModeStyleVisible
【VisualBasic程序代码】
Dima()ASInteger,nAsInteger
PrivateSubForm_Load()
txtSrc.Text="":
txtObj.Text="":
(2)=False
EndSub
PrivateSubcmdGendat_Click()'生成正整数序列并存入数组a
OnErrorGoToErrorhandler
n=InputBox$("请输入数组元素个数:
","输入序列长度")
If(n<1)Then
MsgBox"输入数据错误!
",vbOKOnly,"提示:
"
GoToErrorhandler:
EndIf
ReDima(n)AsInteger
s=""
Fori=1Ton'将生成的正整数存入a
(1)~a(n)中
a(i)=Int(Rnd*10000):
s=s&Str$(a(i))&vbCrLf
Next
txtSrc.Text=s
(3)'设置运算要求命令按钮可用
Errorhandler:
EndSub
PrivateSubcmdProc_Click()
PopupMenuprocMenu
EndSub
PrivateSubMidNum_Click()'求中位数
lblObj.Caption=MidNum.Caption&":
"
Fori=1Toround((n+1)/2>'用选择排序法对数组a进行部分排序
a(0)=a(i):
k=i'a(0)用作临时变量,暂存第i次选出的最小元素
Forj=i+1Ton
Ifa(j)<a(0)Then
a(0)=a(j):
k=(4)
EndIf
Next
Ifk<>iThen
a(k)=a(i):
a(i)=a(0)
EndIf
Next
Ifn/2-n\2>0Then'n为奇数时,取中间一个数
txtObj.Text-Str$(a((5))
Else'n为偶数时,取中间两个数的平均值
txtobj.Text=Str$(Int((a(n\2)+a(n\2+1))/2))
EndIf
EndSub
'其他代码略
参考答案
(1)Visible
(2)cmdProc.Enabled(3)cmdProc.Enabled=True
(4)j(5)(n+1)/2,或n\2+1,或n/2+1,或其等价表示
[分析]
本题考查VB应用开发中菜单应用技术与基本的程序设计技术。
菜单的基本作用有两个:
一是提供人机对话的界面,以便让使用者选择应用系统的各种功能;二是管理应用系统,控制各种功能模块的运行。
在实际应用中,菜单可分为两种:
弹出式菜单和下拉式菜单。
VisualBasic中的菜单通过菜单编辑器,即菜单设计窗口建立,可以通过以下4种方式进入菜单编辑器。
(1)执行“工具”菜单中的“菜单编辑器”命令。
(2)使用Ctrl+E组合键。
(3)单击工具栏中的“菜单编辑器”按钮。
(4)在要建立菜单的窗体上单击鼠标右键,从弹出的快捷菜单中选择“菜单编辑器”命令。
菜单编辑器窗口分为数据区、编辑区和菜单显示区三个部分,如下图所示。
数据区用来输入或修改菜单项、设置属性。
该区分为若干栏,包括标题、名称、索引、快捷键、帮助上下文、协调位置、复选、有效、可见和显示窗口列表。
编辑区有左、右箭头,上、下箭头,下一个,插入和删除7个按钮,用来对输入的菜单项进行简单的编辑。
菜单在数据输入区输入,在菜单项显示区显示。
菜单项显示区位于菜单设计窗口的下部,输入的菜单项在这里显示出来,并通过内缩符号(…)表明菜单项的层次。
条形光标所在的菜单项是“当前菜单项”。
为使菜单项在运行时起作用,还需要在该窗体的代码窗口内,为有关的菜单项对象的单击事件编写程序代码。
弹出式菜单平常在窗体中并不可见,当用鼠标右击窗体(或其中某个控件)时,就会在鼠标所指位置处弹出该菜单。
弹出式菜单也称为上下文相关菜单(菜单的内容常与运行时实际的状态有关)。
弹出式菜单和下拉式菜单的不同之处是:
应在各弹出式菜单项的上级设置一个顶层菜单项,而且在菜单编辑器中应取消该菜单项的“可见”属性,使其不可见,因此空
(1)处应填入“Visible”。
程序启动时,要求命令按钮cmdProc(运算要求)不可用