全国计算机技术与软件专业技术资格初级程序员上半年下午试题.docx
《全国计算机技术与软件专业技术资格初级程序员上半年下午试题.docx》由会员分享,可在线阅读,更多相关《全国计算机技术与软件专业技术资格初级程序员上半年下午试题.docx(25页珍藏版)》请在冰豆网上搜索。
全国计算机技术与软件专业技术资格初级程序员上半年下午试题
第2章程序员下午试题分析与解答
试题一
阅读以下说明和流程图,回答问题1和问题2。
【说明】
为便于管理,每本正式出版的图书都印有国际标准书号。
标准书号由“ISBN”和10个数字组成,其格式为:
ISBN组号-出版者号-书名号-校验码。
其中,校验码是根据前面9个数字计算得到的,用于计算机自动校验。
假设标准书号的10个数字依次是a
(1),a
(2),…,a(10),则校验码a(10)的设置应使S=10*a
(1)+9*a
(2)+8*a(3)+…1*a(10)能被11整除。
如果校验码a(10)应设置成10,则规定以“X”表示之。
例如,信息处理技术员考试大纲的标准书号为:
ISBN7-302-11191-X。
第1段上的数字“7”是国际ISBN中心分配给中国ISBN中心管理的组号。
第2段上的“302”表示清华大学出版社。
标准书号的校验过程如图1-1所示,计算校验码的过程如图1-2所示,其中,Mod(S,11)表示S除以11得到的余数。
【流程图】
【问题1】
请填补流程图中的空缺
(1)~(4)。
【问题2】
设“程序员考试大纲”标准书号前9个数字为7-302-08493,请写出其校验码。
参考答案
[问题1]
(1)(11-I)*a[I](或I*a(11-I))
(2)9
(3)S+(11-I)*a[I]→S(或S+(I+1)*a(10-I)→S)
(4)MOD(11-R,11)
[问题2]9
试题一[分析]
制订标准书号的目的是实现图书的国际统一编码,以便于实现计算机化的图书管理信息系统,使出版社内的图书管理、书库中的图书管理以及书店的图书销售管理具有更高的工作效率和管理水平。
标准书号采用分段编码,总长度是统一的,而段的长度是不统一的。
例如,中国的出版者号规定为2~7位数字。
对较大的出版社分配比较短的码,留出较长的书名号为较多的书进行编码。
标准书号的最后一位是校验码。
设置校验码可以大大减少录入错误造成的管理混乱。
校验码一般由计算机程序产生。
当操作人员录入前9个数字后,计算机就会自动启动计算校验码的过程,输出正确的校验码。
在书店(或书库),不论是建库还是查询检索,在手工输入带校验码的标准书号后,计算机就会自动启动校验过程,判断是否输入错误。
计算校验码的过程中,首先要计算S=10*a
(1)+9*a
(2)+8*a(3)+…+2*a(9),这就要采用循环。
在循环前应设置初始值S=0,在循环体内应执行S+(11-I)*a
(1)→S或S+(I+1)*a(10-I)→S(其中的乘号“*”不要丢失)。
该循环应对循环变量I=1~9进行(步长默认为1),因此,
(2)处应填9,(3)处填S+(11-I)*a(I)→S或S+(I+1)*a(10-I)→S。
接着再计算该S值除以11的余数R。
显然0
R
10。
由于R与校验码之和应能被11整除,因此,校验码应等于MOD(11-R,11)(填11-R者没有考虑R=0的情况)。
从而(4)处应填MOD(11-R,11)。
在校验码等于10的情况,还应以符号X表示之。
对标准书号的校验过程中,首先要将校验码为x的情况转换成数据10,以便于后续计算。
为了计算S=10*a
(1)+9*a
(2)+8*a(3)+…+1*a(10),需要采用循环。
在循环前,应设置初始值S=0,对循环变量I从1到10(步长默认为1),执行语句S+(10-I+1)*a(I)→S或S+I*a(11-I)→S,因此,
(1)处填(11-I)*a(I)或I*a(11-I)。
计算出S的值后,还应判断S除以11的余数是否为0。
若余数为0,说明S能够被11整除,表示校验结果正确:
若余数非0,则说明输入的标准书号有错(可能是校验码输入有错,也可能是前面的数字输入有错)。
这时计算机会输出错误信息,请操作人员仔细校对改正。
试题二
阅读以下说明和C语言函数,将解答填入对应栏内。
【说明】
下面待修改的C程序完成的功能是:
对于给定的一个长正整数,从其个位数开始,每隔一位取一个数字(即取其个位、百位、万位等数字),形成一个新的整数并输出。
例如,将该程序修改正确后,运行时若输入“14251382”,则输出的整数为“4532”。
下面给出的C程序代码中有五个错误,请指出所有的错误。
【C程序代码】
01#include<stdio.h>
02
03intmain()
04{
05longn,num;
06inti;
07
08do{
09printf("请输入一个正整数:
");
10scanf("%ld",n);
11}while(n<=0);
12k=1;
13for(i=1;n>=0;i++){
14if(i%2=1){
15num=num+(n%10)*k;
16k=k*10;
17}
18n=n/10;
19}
20printf("新数据为:
%d\n",num);
21return0;
22}
参考答案
错误1:
变量k没有声明(或定义)。
错误2:
变量num没有初始化,或者num应初始化为0。
错误3:
第10行scanf函数参数错,或者“scanf("%1d",n);”中的n应该为“&n”;或者n之前应加取地址符号。
错误4:
第13行循环条件错,或改为“n>0”。
错误5:
第14行if语句条件错,将“=”改为“==”;或者将“1%2=1”改为“i%2==1”
试题二[分析]
本题考查程序检错和排错能力。
程序错误一般分成语法错误和语义错误两种类型,其中语法错误是形式上的错误,语义错误是含义上的错误,编译程序能够发现程序中的所有语法错误。
语义错误又可分为静态语义错误和动态语义错误,静态语义错误编译时检查,而动态语义错误在程序运行时表现。
C程序中,常见的错误有:
使用的变量没有定义、变量没有赋值初就直接使用、输入输出的数据类型与所用格式说明符不一致、超出数据范围、输入时数据的组织方式与要求不符、误把“=”作为关系运算符“等于”、语句的分号缺少或放置错误、缺少“{}”、符号引用错误,“(、)、[、]”括号不配对、引用数组元素超界等。
在本题的程序中,使用变量num的语句为“num=num+(n%10)*k;”。
由于变量num没有赋初值,该语句运行的结果导致num的值是不确定的。
在本题给出的程序中,出现了如下错误。
(1)使用的变量k没有定义(语法错误,编译程序报告:
k是未定义的标识符)。
(2)变量num没有赋初始值就直接使用(动态语义错误),应将其初始值设为0。
由于num是局部变量,使用变量num的语句为“num=num+(n%10)*k”,系统不保证对其进行初始化,导致程序的运行结果不确定。
(3)第14行,误把“=”作为关系运算符“等于”(语法错误),
(4)第10行,输入变量时忘记使用地址符号(动态语义错误),运行时变量n不能正确接收输入的数据。
(5)第13行,循环条件错误,导致无穷循环。
考生应多上机调试程序,这样就可以熟悉常见的程序错误,从而提高编程水平和效率。
试题三
阅读以下说明和C语言函数,将应填入(n)处的字句写在对应栏内。
【说明】
函数countmonths(DATEstart,DATEend)的功能是:
计算两个给定日期之间所包含的完整月份数。
该函数先算出起止日期中所含的完整年数,再计算余下的完整月份数。
规定两个相邻年份的同月同日之间的间隔为1年。
例如,2007.5.30—2008.5.30的间隔为1年。
若相邻两年中前一年是闰年,并且日期是2月29日,则到下一年的2月28日为1年,即2008.2.29—2009.2.28的间隔为1年。
规定两个相邻月份的相同日之间的间隔为1个月,但需要特别考虑月末的特殊情况。
例如,2007.1.29—2007.2.28的间隔为1个月,同理,2007.1.30—2007.2.28、2007.1.31—2007.2.28的间隔都是1个月。
计算起止日期间隔不足一年的完整月份数时,分如下两种情况。
(1)起止日期不跨年度。
先用终止日期的月号减去起始日期的月号得到月份数,然后再根据情况进行修正。
例如,起止日期为2008.3.31—2008.9.20,通过月号算出月份数为6。
修正时,通过调用函数makevalid将2008.9.31改为2008.9.30,与终止日期2008.9.20比较后,将月份数修正为5。
(2)起止日期跨年度。
计算方法如下例所示:
对于起止日期2008.7.25—2009.3.31,先计算2008.7.25—2008.12.25的月份数为5,再算出2008.12.25—2009.3.25的月份数为3,因此2008.7.25—2009.3.31之间的完整月份数为8。
日期数据类型定义如下:
typedefstruct{
intyear;intmonth;intday;/*日期的年号(4位)、月和口号*/
}DATE;
程序中使用的函数cmp_date()、isLeapYear()和makevalid()说明如下。
【C语言函数】
intcount_months(DATEstart,DATEend)
{
intyears=0,months=0;
DATEr;
if(cmp_date(start,end)>0){
r=start;start=end;end=r;
}
years=end.year-start.year;/*计算年数*/
r=start;
r.year=end.year;
if(cmp_date(r,end)>0){/*修正年数*/
(1);
r.year--;
}
if(r.year<end.year){/*跨年度时,先计算到12月的月份数*/
months=
(2);
r.month=12;
}
months+=(end.month+12-r.month)%12;
r.year=end.year;r.month=end.month;
makevalid((3));/*将日期r修正为有效日期*/
if(cmp_date(r,end)>0)/*修正月份数*/
(4);
months+=(5);/*计算总月份数*/
returnmonths;
}
参考答案
(1)years--,或其等价形式
(2)12-r.month,或其等价形式
(3)&r
(4)months--,或其等价形式
(5)years*12
试题三[分析]
本题考查编程能力。
根据题目的说明,函数count_months(DATEstart,DATEend)的功能是计算两个给定日期之间所包含的完整月份数。
计算月份数时,可以从起始日期开始,到终止日期结束,逐月计算;也可以先算出完整年份数,再计算剩余的完整月份数,最后用完整年份数乘以12再加上剩余的完整月份数。
题目中采用后者。
先用end的年号减去start的年号,得到一个年份值,如下所示:
years=end.year-start.year;/*计算年数*/
显然,上式算出的年份数可能产生误差(多算一年,即end的月号和日期要小于start的日期),因此可能需将years减去1后进行修正。
因此,空
(1)处应填入“years--”。
接下来计算月份数。
由题目中的说明,计算起止日期间隔不足一年的完整月份数时,分如下两种情况。
(1)起止日期跨年度。
计算方法如下例所示:
对于起止日期2008.7.25—2009.3.31,先计算2008.7.25—2008.12.25的月份数为5,再算出2008.12.25—2009.3.25的月份数为3,因此2008.7.25—2009.3.31之间的完整月份数为8。
以下代码处理该情况:
if(r.year<end.year){/*跨年度时,先计算到12月的月份数*/
months=
(2);
r.month=12;
}
因此,空
(2)处应填入“12-r.month”。
(2)起止日期不跨年度。
先用终止日期的月号减去起始日期的月号得到月份数,然后再根据情况进行修正。
例如,起止日期为2008.3.31—2008.9.20,通过月号算出月份数为6。
修正时,通过调用函数makevalid将2008.9.31改为2008.9.30,与终止日期2008.9.20比较后,将月份数修正为5。
以下代码处理该情况:
months+=(end.month+12-r.month)%12;
r.year=end.year;r.month=end.month;
makevalid((3));/*将日期r修正为有效日期*/
if(cmp_date(r,end)>0)/*修正月份数*/
(4);
根据函数makevalid的接口说明,其实参应取变量r的地址,因此空(3)处填入“&r”。
简单地用两个月份号相减可能产生的误差是多算了一个月,因此将months减1进行修正,所以空(4)处填入“months--”。
最后计算总月份数,年份数乘以12再加上不足一整年的月份数即可得到月份总数。
因此空(5)处填入“years*12”。
(以下试题四至试题五任选一题)
试题四
阅读以下说明和C语言函数,将应填入(n)处的字句写在对应栏内。
【说明】
函数sort(NODE*head)的功能是;用冒泡排序法对单链表中的元素进行非递减排序。
对于两个相邻结点中的元素,若较小的元素在前面,则交换这两个结点中的元素值。
其中,head指向链表的头结点。
排序时,为了避免每趟都扫描到链表的尾结点,设置一个指针endptr,使其指向下趟扫描需要到达的最后一个结点。
例如,对于图4-1(a)的链表进行一趟冒泡排序后,得到图4-1(b)所示的链表。
链表的结点类型定义如下:
typedefstructNode{
intdata;
structNode*next;
}NODE;
【C语言函数】
voidsort(NODE*head)
{NODE*ptr,*preptr,*endptr;
inttempdata;
ptr=head->next;
while(
(1))/*查找表尾结点*/
ptr=ptr->next;
endptr=ptr;/*令endptr指向表尾结点*/
ptr=
(2);
while(ptr!
=endptr){
while((3)){
if(ptr->data>ptr->next->data){
tempdata=ptr->data;/*交换相邻结点的数据*/
ptr->data=ptr->next->data;
ptr->next->data=tempdata;
}
preptr=(4);ptr=ptr->next;
}
endptr=(5);ptr=head->next;
}
}
参考答案
(1)ptr->next
(2)head->next
(3)ptr!
=endptr,或其等价形式
(4)ptr
(5)preptr
试题四[分析]
本题考查链表运算能力。
从题目中的以下代码可知,ptr最后应指向表尾结点。
ptr=head->next;
while(
(1))/*查找表尾结点*/
ptr=ptr->next;
endptr=ptr;/*令endptr指向表尾结点*/
显然,空
(1)处应填入“ptr->next”,这样循环结束时,ptr指向表尾结点。
若填入“ptr”,则循环结束时,ptr为空指针。
进行冒泡排序时,从头至尾依次比较逻辑上相邻的两个结点的数据,如果小元素在前大元素在后,则交换。
这样,经过一趟扫描,就将最大元素交换到了表的最后。
下一趟可将次大元素交换到最大元素之前。
显然,空
(2)处应填入“head->next”。
由于程序设置的endptr用于指示出每趟扫描需到达的最后一个结点,ptr用于依次扫描链表中的结点,因此空(3)处的循环条件为“ptr!
=endptr”。
显然,指针preptr起的作用是指向ptr的前驱结点,因此,ptr每向后修改一次,相应地preptr就要修改一次,空(4)处应填入“ptr”。
本趟循环结束后,下一趟扫描也就确定了,因此在空(5)处填入“preptr”。
试题五
阅读以下应用说明以及用VisualBasic开发过程中所编写的程序代码,将应填入(n)处的字句写在对应栏内。
【应用说明】
某应用的登录界面如下:
登录界面中的文本框txtUserID和txtPassword分别用于接受用户输入的用户名和口令,命令按钮为“确定(cmdOk)”和“取消(cmdCancel)”。
ADO数据控件Adodc1与数据库EmployeeData连接。
在EmployeeData中,表“Users”的字段“UserID”和“Pswd”分别记录了所有的合法用户名和口令。
在登录界面中,输入正确的用户名和口令并单击“确定”按钮后,就会打开应用程序的主窗口fxmApp。
用户名或密码输入错误时,给出提示信息并返回登录界面。
【VisualBasic程序代码】
PrivateSubcmdOKClick()
Adodcl.ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=D:
\data\EmployeeData.mdb;PersistSecurityInfo=False"
Adodcl.RecordSource="select*
(1)"
Adodcl.Refresh
Do
usrname=
(2)
pwd=Adodc1.Recordset("Pswd")
Adodc1.Recordset.MoveNext
LoopUntil(usrname=(3))Or(Adodc1.Recordset.EOF)
Ifusrname<>txtUserID.TextThen
MsgBox"无效的用户ID,请重新输入!
",,"提示信息"
Else
If(4)Then
MsgBox"欢迎进入系统主界面!
",,"提示信息"
Unloadme
(5)
Else
MsgBox"无效的用户密码,请重新输入!
",,"提示信息"
EndIf
EndIf
EndSub
答案:
(1)fromUsers
(2)Adodc1.Recordset("UserID")
(3)txtUserID.Text
(4)txtPassword.Text=pwd
(5)frmApp.Show
试题五[分析]本题考查VB开发数据库应用能力。
代码中的空
(1)处是典型的SQL查询语句,应填入“fromUsers”。
一般情况下,用户登录某系统时,都要输入用户名和口令,与系统记录的用户名和口令进行比较,通过后才能登录系统。
参照“pwd=Adodc1.Recordset("Pswd")”,空
(2)处应填入“Adodc1.Recordset("UserlD")”,从数据库中取出用户名与用户在登录界面输入的用户名txtUserlD.Text进行比较,若相同,则再取出该用户的口令进行比对,因此空(3)处应填入“txtUserID.Text"。
空(4)处用于比较口令,填入“txtPassword.Text=pwd",空(5)处填入“frmApp.Show"。
(以下试题六至试题八任选一题)
试题六
阅读下列说明和C++代码,请回答问题1至问题3。
【说明】
已知下列程序运行时的输出应为:
1:
1
1:
1
1:
1
【问题1】
请补齐下述代码中的空缺1和2。
【问题2】
类Stock的定义中有两处错误,请指出错误所在行号并给出该行修改后的完整结果。
【问题3】
指出该代码是否存在内存泄漏。
【C++程序】
01#include<iostream>
02usingnamespacestd;
03classStock{
04protect:
05
(1){};
06Stock(ihtn,intpr=1){
07shares=n;share_val=pr;
08};
09void~Stock(){};
10public:
11//成员函数
12voidoutput(){
13
(2)<<shares<<":
"<<shareval<<endl;
14}
15private:
16//成员变量
17intshares;
18intshare_val;
19};
20
21voidmain(){
22Stocka
(1);a.output();
23Stockb;b.output();
24Stockc=Stock();c.output();
25}
参考答案
[问题1]
(1)Stock():
shares
(1),share_val
(1)
或Stock():
share_val
(1),shares
(1)
(2)cout
[问题2]错误1第4行,修改为:
public:
错误2第9行,修改为:
~Stock(){}
[问题3]否,或不存在内存泄漏
试题六[分析]已知程序的输出全部为1,根据主程序中Stockb;这一语句可以判断出:
类Stock有默认的构造函数,且该构造函数将初始化类中的一些成员变量。
所以
(1)处应该填写的内容为Stock的构造函数,因为该构造函数的函数体内没有语句,所以只能采用初始化列表的方式对成员变量进行初始化。
成员函数output输出成员变量的值,因此
(2)处应该填写标准的输出cout。
由于类至少需要一个共有的构造函数,因此,第4行的protected应该更改为public:
,而析构函数不能有返回类型,因此第9行应该去掉void。
main函数中对类的使用没有通过new操作符生成stock类的对象,因此不存在内存泄露,并且main函数中三种对象的生成方式是等价的。
试题七
阅读以下应用说明、VisualBasic开发说明以及程序代码,将应填入(n)的字句写在对应栏内。
【应用说明】
某交通灯演示程序启动后,其运行窗口中包括红绿灯标志以及当前红绿灯状态剩余秒数的动态显示(如下图)。
红灯与绿灯持续的时间分别为30秒与40秒。
持续时间结束时,立即变更红绿灯,并重新显示剩余秒数。
【Vis