全面历年程序员软考考试下午真题合集
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
申明:此为2004上半年至今的所有程序员软考下午试题真题并且每套后面均配有答案,接近30套,每年两套。
由于文件过大,拆成上午试题和下午试题,在百度文库同样可以搜索“最全历年程序员软考考试上午真题合集“。
此外还有模拟试题提供,百度文库搜索“最全程序员软考考试上午模拟试题合集”和“最全程序员软考考试下午模拟试题合集”。
注:如果图片显示不全,适当将图片缩小即可。
过来人总结,多做做下午场试题,最好打印。
上午场试题对着电脑即可,只要不是一点不懂基本上午场没问题。
初级程序员2004上半年下午试题
1、试题1
阅读下列说明、流程图和算法,将应填入______处。
[流程图说明]
下面的流程图用N-S盒图形式描述了数组A中的元素被划分的过程。
其划分方法是:以数组中的第一个元素作为基准数,将小于基准数的元素向低下标端移动,大于基准数的元素向高下标端移动。
当划分结束时,基准数定位于A[i],并且数组中下标小于i的元素的值均小于基准数,下标大于i的元素的值均大于基准数。
设数组A的下界为low,上界为high,数组中的元素互不相同。
例如,对数组(4,2,8,3,6),以4为基准数的划分过程如下: [流程图]
[算法说明]
将上述划分的思想进一步用于被划分出的数组的2部分,就可以对整个数组实现递增排序。
设函数int p(intA[],int low,int high)实现了上述流程图的划分过程并返回基准数在数
组A中的下标。
递归函数void sort(int A[],int L,int H)的功能是实现数组A中元素的递增排序。
[算法]
void sort(int A[],int L,int H){
if(L<H){
k=p(A,L,H); /*p()返回基准数所在数组A中的下标*/
sort( (4) );/*小于基准数的元素排序*/
sort( (5) );/*大于基准数的元素排序*/
};
}
2、试题2
阅读下列函数说明和C函数,将应填入______处的语句写在答题纸的对应栏。
[函数2.1说明]
函数palindrome(char s[])的功能是:判断字符串s是否为回文字符串,若是,则返回0,否则返回-1。
若一个字符串顺读和倒读都一样,称该字符串是回文字符串,例如,“LEVEL”是回文字符串,而“LEVAL”不是。
[函数2.1]
int palindrome(char s[])
{
char *pi,*pj;
pi=s;pj=s+strlen(s)-1;
while(pi<pj&& (1) ) {
pi++;pj--;
}
if( (2) ) return-1;
else return 0;
}
[函数2.2说明]
函数f(char *str,char del)的功能是:将非空字符串str分割成若干个子字符串并输出,del 表示分割时的标志字符。
例如,若str的值为“”,del的值为“3”,调用此函数后,将输出3个子字符串,分别为“12”,“4”和“5”。
[函数2.2]
void f(char *str,char del)
{
int i,j,len;
len=strlen(str);
i=0;
While(i<len){
While( (3) )i++; /* 忽略连续的标志字符*/
/* 寻找从str[i]开始直到标志字符出现的一个子字符串*/ j=i+1;
while(str[j]!=del &&str[j]!'\0')j++;
(4) ='\0';/* 给找到的字符序列置字符串结束标志*/
printf("%s\t",&str[i]);
(5) ;
}
}
3、试题3
以下是与Visual Basic开发应用有关的5个问题。
对每个问题,请将答案填入答题纸的对应栏。
(1)在Visual Basic中,工程文件、窗体文件和标准模块文件的扩展名是什么?从下列选项中选择:prg,prj,exe,vbp,form,frm,win,fra,std,bas,vbs,vbm。
(2)设某窗体上有1个命令按钮,其名称为CmdSave,运行时该按钮上显示有“保存(S)”字样的信息。
为使热键Alt+S与该命令按钮相关联,应该对按钮CmdSave的Caption属性设置什么样的属性值?
(3)设某窗口有1个图像框Imagel及2个命令按钮“放大”和“缩小”。
单击“放大”按钮就会使该图像框的长和宽都放大10%;单击“缩小”按钮就会使该图像框的长和宽都缩小10%(该图像框的左上角不动)。
分别写出这2个命令按钮的单击事件过程中的程序代码。
(4)为使某个单选按钮初始时默认被选中,在开发时应怎样做?
(5)若有语句Tmpval=MsgBox(“非法操作!”,vbOKCancel+vbCritical,“提示”),简要描述程序运行时弹出的消息框的主要特征。
4、试题4
阅读以下说明和C程序代码,将应填入______处的语句写在答题纸的对应栏。
[说明]
函数MultibaseOutput(long n,intB.的功能是:将一个无符号十进制整数n转换成B(2≤B ≤16)进制数并输出。
该函数先将转换过程中得到的各位数字入栈,转换结束后再把B进制数从栈中输出。
有关栈操作的诸函数功能见相应函数中的注释。
C代码中的符号常量及栈的类型定义如下:
# define MAXSIZE 32
typedef struct{
int * elem; /* 栈的存储区*/
int max;/* 栈的容量,即栈中最多能存放的元素个数*/
int top;/* 栈顶指针*/
}Stack;
[C代码]
int InitStack(Stack * S,int n) / * 创建容量为n的空栈*/
{ S->elem=(int *)malloc(n * sizeof(int));
if(S->elem==NULL)return-1;
S->max=n; (1) =O;return 0;
}
int Push(Stack * S,int item) / * 将整数item压入栈顶* /
{ if(S->top==S->max){ printf(“Stack is full! \n”);return-1;}
(2) =item;return 0;
}
int StackEmpty(StackS) {return (! S.top)? 1:0;} / * 判断栈是否为空* /
int Pop(Stack *S ) / * 栈顶元素出栈* /
{ if(! S->top){printf(“Pop an empty stack! \n”);return-1;}
return (3) ;
}
void MultibaseOutput(long n,intB.
{ int m;StackS;
if (InitStack(&S,MAXSIZE.){printf(“Failure! \n”);return;}
do {
if(Push(&S, (4) )){printf(“Failure! \n”);return;}
n= (5) ;
}while(n!=0);
while(! StackEmpty(S)){ / * 输出B进制的数* /
m=Pop(&S);
if(m<10)printf(“%d”,m);/ * 小于10,输出数字* /
else printf(“%c”,m+55); / * 大于或等于10,输出相应的字符* / }
printf(“\n”);
}
5、试题5
阅读以下应用说明及Visual Basic程序代码,将应真入______处的语句写在答题纸的对应栏。
[应用说明5.1]
应用程序的窗体中有1个下拉式列表框(名称为Combol)和2个文本框(名称分别为Txt1和Txt2)。
运行时,用户从Combo1的列表中进行选择,程序就会将选中条目的容及编号(从0开始)分别在文本框Txt1和Txt2中显示出来。
[程序代码5.1]
Private Sub Combol_Click()
Txt1,Text=Combol. (1)
Txt2.Text=Combol. (2)
End Sub
(注意:可供(2)处选择的选项有List,Index,ListIndex,LisCount,Number)
[应用说明5.2]
本应用程序的运行窗口如图2-1所示。
当用户在输入框(名为TxtIn)中输入数值数据,并从下拉式列表框(名称为CmbOp)中选择所需的运算后,输出框(名为TxtOut)中就会显示运算的结果。
用户单击“清除”按钮(名为
CmdClear)后,输入框和输出框都清空。
[程序代码5.2]
Private Sub CmbOp_Click()
Dim DataIn As Double,DataOut as Double
DataIn= (3)
Select Case (4)
Case“取整数部分”
DataOut=Int(DataIn)
Case“求平方根”
If DataIn<0 Then
MsgBox$(“负数不能开平方!”
Else
DataOut=Sqr(DataIn)
End If
Case“取绝对值”
DataOut=Abs(DataIn)
(5)
TxtOut.Text=str$(DataOut)
End Sub
6、试题6
阅读下列函数说明和C函数,将应填入______处的语句写在答题纸的对应栏。
[函数6说明]
函数DelA_InsB(LinkedList La,LinkedList Lb,int key1,int key2,int len)的功能是:将线性表A中关键码为key1的结点开始的len个结点,按原顺序移至线性表B中关键码为key2的结点之前,若移动成功,则返回0;否则返回-1。
线性表的存储结构为带头结点的单链表,La为表A的头指针,Lb为表B的头指针。
单链表结点的类型定义为:
typedef struct node {
int key;
struct node * next;
} * LinkedList;
[函数6]
int DelA InsB(LinkedList La,LinkedList Lb,int key1,int key2,int len)
{ LinkedListp,q,s,prep,pres;
int k;
if(! La->next‖! Lb->next‖->next‖len<=0)return-1;
p=La->next;prep=La;
while(p&&p->key!=key1){ / * 查找表A中键值为key1的结点* /
prep=p;p=p->next;
}
if(! p)return -1; / * 表A中不存在键值为key1的结点* /
q=p;k=1;
while(q&& (1) ){ / * 在表A中找出待删除的len个结点* /
(2) ;k++;
}
if(! q)return-1:/ * 表A中不存在要被删除的len个结点* /
s=Lb->next; (3) ;
while(s s && s->key!=key2){ / * 查找表B中键值为key2的结点* / pres=s;s=s->next;
}
if(! s)return-1;/ * 表B中不存在键值为key2的结点* /
(4) =q->next; / * 将表A中的len个结点删除* /
q->next= (5) ;
pres->next=p;/ * 将len个结点移至表B * /
return 0;
}
7、试题7
阅读以下应用说明、属性设置及Visual Basic程序代码,将应填入______处的语句写在答题纸的对应栏。
[应用说明7]
本应用程序的运行窗口如图2-5所示。
只要用户单击“闪烁”按钮,文字“欢迎光临”就会以0.3s消失、0.3s显示反复进行闪烁;单击“停止”按钮,闪烁停止,恢复图示的初态。
[属性设置7]
[程序代码7]
Private Sub CmdF C1ick()
Timerl. (3) =True
Label.Visible=False
End Sub
Private Sub Timerl_Timer()
(4) =not Label.Visible
End Sub
Private Sub CmdT_Click()
Timerl.Enabled= (5)
Label.Vlsible=true
End Sub
8、试题8
阅读下列程序说明和C程序,将应填入______处的语句写在答题纸的对应栏。
[程序8说明]
程序用于计算某公司每个职工应缴纳的个人所得税额和全体职工缴纳的个人所得税总额。
职工的当月收入(工资或薪金)通过键盘输入,每次输入一个职工的工号和工资(或薪金)。
由于该公司的工资或薪金是不定时发放的,所以输入过程中每个职工的收入会出现多次输入,整个输入以工号小于等于。
结束。
假设个人所得税法规定:个人收入所得,按月计税,以每月收入总额减除免税金额800元后的余额作为该月的月应纳税所得额。
适用税率如表2-1所示。
上表表明,个人收入所得税是按照超额累计的税率来征收的。
设一个人的月应纳税所得额为K(元),用下面的公式计算其应缴纳的个人所得税额S(元):若0<K≤500,则S=K×5%;
若500<K≤2000,则S=500×5%+(K-500)×10%;
若2000<K≤5000,则S=500×5%+1500×10%+(K-2000)×15%;
若5000<K≤20000,则S=500×5%+1500×10%+3000×15%+(K-5000)×20%,
……
例如,某人某月收入总额为4100元,减去800元后,应纳税所得额为3300元,其应缴纳的个人所得税额为500×5%+1500×10%+1300×15%=370元。
[程序8]
#include<stdio.h>
#define MaxNum 50
#define BASE 800 / * 免税金额基数* /
int paylevel[]={0,500,2000,5000,20000,40000,60000,80000,100000,1000001}; int taxPrate[]={5,10,15,20,25,30,35,40,45}; / * 税率表* /
typedef struct{
int Id;/ * 职工的工号* /
long Salary; / * 职工的工资* /
}Info;
/ * 查找工号为Id的职工在数组employee中的下标,返回值为0表示没有* /
int find(int Id,Info employee[],iht m){
int j;
employee[O].Id=Id;
for(j=m; (1) ;j--);
return j;
}
void main(vpid)
{Info employee[MaxNUm+1);
long Wage;
double sum=0,K,S;
int i,j,N=0,Code;
scanf(“%d %Id”,&Code,&Wage);/ * 读入职工号、工资或薪金* / while(Code>0){
i=find(Code,employee,N);
if(i>0)employee[i].Salary+=Wage;
else { (2)
employee[N].Id=Code;employee[N].Salary=Wage;
}
scanf(“%d %”,&Code,&Wage);
}
for(i=1;i<=N;i++){
K= (3) ;/ * 计算月应纳税所得额* /
S=0;/ * 月应纳税额赋初值* /
if(K>0){
for(j=1;j<=9;j++)
if( (4) ) / * 月应纳税所得额超过第j级* /
S=S+(Paylevel[j]-paylevel[j-1])*taxPrate[j-1]/100;
else{S=S+( (5) )*taxPrate[j-1]/100;break;}
}
printf(“职工%d应缴纳的个人所得税额:%10.2If\n”,employee[i].ld,S);
sum+=S;
}
printf(“全体职工个人所得税总额:%10.2If\n”,sum);
}
9、试题9
阅读以下应用说明及Visual Basic程序代码,将应填入______处的语句写在答题纸的对应栏。
[应用说明9]
本应用程序的运行窗口如图2-6所示。
窗口中的3个文本框和2个按钮,名称分别为Txt_salary,Txt_base,Txt_tax,Cmd compute 和Cmd_quit。
运行时,文本框Txt_base中存放的是免税金额基数(应扣除的基本费用)。
当用户在文本框Txt_salary中输入月收入(工资或薪金)并单击“计算”按钮Cmd_compute后,Txt_tax框中就显示计算所得的应纳税额。
文本框Txt_base和Txt_ tax在运行时不接受用户输入,Txt_base的容以灰色显示。
个人工资(或薪金)所得税是按照超额累进的税率来征收的,其计算方法参考试题8。
[程序代码9]
Option Base 0
Private Sub Cmd_compute_Click()
Dim paylevel,taxPrate
paylevel=Array(0,500,2000,5000,20000,40000,60000,80000,100000,1000001) taxPrate=Array(5,10,15,20,25,30,35,40,45)
K= (1)
S=0
if(K>0) Then
For j=1 TO 9
If (2) Then
S=S+(paylevel(j)-paylevel(j-1)) * taxPrate(j-1)/100
Else
S=S+( (3) ) * taxPrate(j-1)/100
Exit For
End If
Next j
End If
(4) =Str$(S)
End Sub
Private Sub Cmd_quit_Click()
End
End Sub
Private Sub Form_Load()
Txt_tax.Text=“”
Txt_salary.Text=“”
Txt_base.Text=800
Txt_tax.Locked=True
Txt_base.Enabled= (5)
End Sub
答案:
1、(1)j--
(2)i++
(3)A[i]←pivot或A[j]←pivot
(4)A,L,k-1
(5)A,k+1,H
[解析]
题目考查快速排序算法。
快速排序采用了一种分治的策略,通常称为分治法。
其基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。
递归地解这些子问题,然后将这些子问题的解组合为原问题的解。
快速排序的具体过程为:
第一步,在待排序的n个记录中任取一个记录,以该记录的排序码为基准,将所有记录分成2组,第一组各记录的排序码都小于等于该排序码,第二组各记录的排序码都大于该排序码,并把该记录排在这2组中间,这个过程称为一次划分。
第二步,采用同样的方法,对划分出来的2组元素分别进行快速排序,直到所有记录都排到相应的位置为止。
在进行一次划分时,若选定以第一个元素为基准,就可将第一个元素备份在变量pivot 中,如图中的第①步所示。
如此以来,基准元素在数组中占据的位置就空闲出来了,因此下一步就从后向前扫描,如图中的第②步所示,找到一个比基准元素小的元素时为止,将其前移,如图中的第③步所示。
然后再从前向后扫描,如图中的第④步所示,找到一个比基准元素大的元素时为止,将其后移,如图中的第⑤步所示。
这样,从后向前扫描和从前向后扫描交替进行,直到扫描到同一个位置为止,如图中的第⑥步所示。
由题目中给出的流程图可知,以第一个元素作为基准数,并将A[loW]备份至pivot,i用于从前向后扫描的位置指示器,其初值为low,j用于从后往前扫描的位置指示器,其初值为high。
当i<j时进行循环:
(1)从后向前扫描数组A,在i<j的情况下,如果被扫描的元素A[j]>pivot,就继续向前扫描(j--),如果被扫描的元素A[j]<pivot就停止扫描,并将此元素的值赋给目前空闲着的A[i];
(2)这时,再从前向后扫描,在i<j的情况下,如果被扫描的元素A[j]<pivot,就继续向后扫描(i++);如果被扫描的元素A[j]>pivot就停止扫描,并将此元素的值赋给目前空闲着的A[j];
(3)这时,又接第(1)步,直到i≥j时退出循环。
退出循环时,将pivot赋给当前的A [i](A[i]←pivot)。
递归函数的目的是执行一系列调用,直到到达某一点时递归终止。
为了保证递归函数正常执行,应该遵守下面的规则:
(1)每当一个递归函数被调用时,程序首先应该检查一些基本的条件是否满足,例如,某个参数的值等于零,如果是这种情形,函数应停止递归。
(2)每次当函数被递归调用时,传递给函数一个或多个参数,应该以某种方式变得“更简单”,即这些参数应该逐渐靠近上述基本条件。
例如,一个正整数在每次递归调用时会逐渐变小,以至最终其值到达零。
本题中,递归函数sort(int A[],int L,int H)有3个参数,分别表示数组A及其下界和上界。
根据流程图可知,这里的L相当于流程图中的i,这里的H相当于流程图中的j。
因为p()返回基准数所在数组A中的下标,也就是流程图中最后的“A[i]←pivot”中的i。
根据快速排序算法,在第一趟排序后找出了基准数所在数组A中的下标,然后以该基准数为界(基准数在数组中的下标为k),把数组A分成2组,分别是A[L,...,k-1)和A[k+1,...,
H],最后对这2组中的元素再使用同样的方法进行快速排序。
2、(1)*pi==*pj
(2)pi<pj或*pi != * pj,及其等价形式
(3)str[i]==del
(4)str[j]
(5)i=j+1
[解析]
[函数2.1]
若一个字符串顺读和倒读都一样,称该字符串是回文字符串。
如果使用数组s[n]来存储一个字符串,则根据这个定义,要判断一个串是否是回文字符串,需要循环比较:
(1)该字符串的第一个元素s[0]和最后一个元素s[n-1]比较,如果s[0]不等于s[n-1],则s 不是回文字符串。
(2)如果s[0]等于s[n-1],则第二个元素s[1]和倒数第二个元素s[n-2]比较,如果s[1]不等于s[n-2],则s不是回文字符串。
(3)依次类推,直到最中间的2个元素也比较完毕(如果s有偶数个元素),或者只剩下中间的1个元素(如果s有奇数个元素)。
当上述循环结束时,如果最中间的元素没有进行比较,就说明s不是回文字符串,如果进行了比较,则s是回文字符串。
在函数2.1中,pi和pj是2个指向字符的指针,程序首先将s的首地址赋给pi(即pi=&a[0]),将元素s[strlen(s)-1)的地址赋给pj(即pj=&s[strlen(s)-1]),当pi<pj并且pi和pj所指向的字符相等时进行循环:pi自增,pj自减。
退出循环后,如果pi≥pj,则s是回文字符串(如果s有偶数个元素,则为pi>pj,如果s 有奇数个元素,则为pi=pj);如果pi<pj,则s不是回文字符串。
[函数2.2]
由函数2.2说明可知,此函数对给定的字符串进行从左至右的扫描,找出不包含标志字符的子字符串。
在函数2.2中,i的初值为0,len表示字符串的长度。
当i<len时进行循环:如果当前字符是标志字符,则不做处理,继续扫描以处理标志字符连成一串的情况。
当退出该循环时,当前字符str[i]不是标志字符,这时开始寻找从str[i]开始,直到标志字符出现的一个子字符串(i保持不变,用j标记寻找的过程),给找到的字符序列置字符串结束标志,以便于后面语句的输出。
输出语句结束后,就要继续寻找后面的不包含标志字符的子字符串,这时需要把指针i 移动j的后面,继续扫描。
3、(1)工程文件扩展名为vbp,窗体文件扩展名为frm,标准模块文件的扩展名为bas。
(2)按钮CmdSave的Caption属性可以这样设置:保存(&S)。
(3)“放大”命令按钮单击事件过程程序代码如下:
Imagel.Width=Imagel.Width*1.1;
Imagel.Height=Imagel.Height*1.1;
“缩小”命令按钮单击事件过程程序代码如下:
Imagel.Height=Imagel.Height*0.9;
Imagel.Width=Imagel.width*O.9;
(4)将该单选按钮的Value属性值设置成True。
(5)消息框的标题栏显示“提示”;消息框中有1个出错标记及2个命令按钮,分别显示“确定”和“取消”;消息框中显示的信息为“非法操作!”。
[解析]
(1)Visual Basic应用程序可以用4种类型的文件保存。
第一类是单独的窗体文件,扩展名为FRM;第二类是公用的标准模块文件,扩展名为BAS;第三类是类模块文件,扩展名为CLS;第四类是工程文件,这种文件由若干个窗体和模块组成,扩展名为VBP。
(2)对于任何一个控件,只要它有Caption属性,就可以为其指定访问键。
对于一般控件(非菜单项),可以在设计阶段通过属性窗口在Caption属性中加“&”设置访问键。
访问键只能是一个字符,而且这个字符必须是键盘上的某个键,否则没有实际意义。
因此,通常用键盘上存在的西文字符作为访问键。
如果用汉字作为菜单项或控件的标题,则通常把访问键放在标题后面的括号中。
(3)对图像框的“放大”和“缩小”,可以通过设置它的Height属性和Width属性而改变。
(4)为使一个单选按钮初始时默认被选中,一般是对它的Checked属性进行设置,把该属性标记为True。
(5)MsgBox语句的形式为MsgBox Msg$[,type%][,title$][,helpfile,context]。
Msg是一个字符串,其容在产生的对话框显示;type是一个整数值或符号常量,用来控制在对话框显示的按钮、图标的种类和数量;title是一个字符串,用来显示对话框的标题。
4、(1)S->top
(2)S->elem[S->top++]
(3)S->elem[--S->top]
(4)n%B
(5)n/B
[解析]
对于一个栈,首先应对它进行初始化,设置它的容量、栈顶等,一般有2种做法:
(1)top=0。
在这种做法下,如果要进行入栈操作,则先将压人栈的元素值赋给栈顶指针所指向的单元,然后栈顶指针加1;如果要进行出栈操作,则将栈顶指针减1,然后将要出栈
的元素弹出栈。
(2)top=-1。
在这种做法下,如果要进行入栈操作,则首先将栈顶指针加1,然后把压人栈的元素值赋给栈顶指针所指向的单元;如果要进行出栈操作,则首先将要出栈的元素弹出栈,然后再将栈顶指针减1。
显然,在本题中使用的是第一种方法。
(1)空填写S->top,使S->top=0。
这样将整数item 压入栈顶的语句为S->elem[S->top++]=item,即(2)空填写S->elem[S->top++)。
出栈操作是返回S->elem[--S->top)t这是(3)空的答案。
将十进制数n转换为二进制数时,把n除以2的余数压入栈,而用n除以2的商代替n,依次类推,直到n等于0为止。
这时,再把栈中的值一一弹出,就可得到二进制数据。
类似地,把十进制数n转换成B进制数的过程也是如此,一般算法描述为(其中S为栈):
do{
n%B入栈;
n=n/B;
}while(n);
5、(1)Text
(2)ListIndex
(3)Val(TxtIn.Text)或TxtIn.Text
(4)CmbOp.Text
(5)End Select
[解析]
组合框(Combo Box)是组合列表框和文本框的特性而成的控件。
它的Text属性值是用户所选择的项目的文本或直接从编辑区输入的文本。
它的ListIndex属性值为选中条目的编号。
文本框的Text属性用来设置本框中的显示的容。
在VB中,情况语句的一般格式为:
Select Case测试表达式
Case表达式表列1
[语句块1]
[Case表达式表列2
[语句块2]]
...
[Case Else
[语句块n]]
End Select
6、(1)k<len
(2)q=q->next
(3)pres=Lb
(4)prep->next
(5)s或pres->next
[解析]
本题是在链表插入和删除单个结点的基础上进行扩展,一次性插入多个结点和删除多个结点其原理和插入、删除一个结点的运算是一致的。
首先在A链表中查找键值为key1的结点,使用了下列循环:
While(p&&p->key!=key1) { / * 查找表A中键值为key1的结点* / Prep=p;p=p->next;
}因此,当找到键值为key1的结点时,p指向该结点,prep指向p的前驱。
然后看在p的后面是否有len个结点,使用了下列语句:
q=p;k=1;
while(q&& (1) ) { / * 在表A中找出待删除的len个结点* /
(2) ;k++;
}显然,首先把q指向p,k为计数器,所以该循环的结束条件有2个,一个是p的后面没有len个结点,这时q为空,所以(2)空应填写q=q->next,使q的指针往后移动;另一个是p的后面有len个结点,这时k=len。
所以(1)空应填写k<len。
根据上面的语句,如果p的后面有len个结点,则q指向第len个结点。
如图2-2所示(虚线表示省略了中间若干个结点)。
同样,在表B中查找键值为key2的结点,使用了下列循环:
s=Lb->next; (3) ;
while(s&&s->key!=key2){ / * 查找表B中键值为key2的结点* / pres=s;s=s->next;
}首先,s指向第一个结点,然后进行循环,循环的结束条件也是2个,要么s为空(这时说明从头到尾都没有找到键值为key2的结点),要么找到了,s指向该结点,pres指向s的前驱。
但是,如果第一个结点的键值就是key2的话,根据循环条件,循环中的语句不执行,则pres没有值,所以(3)空应该填写pres=Lb,使pres始终指向s的前驱。
如图2-3所示(虚线表示省略了中间若干个结点)。
最后将p到q的连续len个结点从A表中删除,在B表中插入,如图2-4所示。
程序中使用的语句如下:
(4) =q->next; / * 将表A中的len个结点删除* /
q->next= (5) ;
pres->next=p;/ * 将len个结点移至表B * /
要把p到q的连续len个结点从A表中删除,就要把p的前驱(prep)的next指向q的next,因此,(4)空应填写prep->next。
然后把q的next指向B表中s,把s的前驱(pres)的next 指向p,所以,(5)空应填写s。
7、(1)False
(2)300
(3)Enabled
(4)Label.Visible
(5)False
[解析]
在VB中,计时器控件主要有Name、Enabled和Interval等属性。
Name属性是该计时器的标识符。
Enabled=true表示打开计时器,开始计时;Enabled=false表示关闭计时器,停止计时。
Interval属性用来设置计时器事件之间的间隔,一般以ms为单位,取值围为0~65535,因此其最大时间间隔不能超过65s。
因为60000ms为1min,如果把Interval属性设置为1000,则表明每秒钟发生一个计时器事件。
本题要求0.3s闪烁一次,因此,应该把Interval的属性值设置为300。
在窗体运行时,需要用户单击“闪烁”按钮后才开始闪烁,所以初始化时,计时器的Enabled属性值应该为False。
当用户单击“闪烁”按钮时,计时器的Enabled属性值应该为True。
当用户单击“停止”按钮时,计时器的Enabled属性值应该为False。
8、(1)employee[j].Id!=Id
(2)n=n+1;或者n++;或者++n
(3)employee[i].Salary-BASE;或者employee[i].Salary-800
(4)k>paylevel[j]
(5)k-paylevel[j-1]
[解析]
第一个函数find(Id,employee[],m),其功能为查找工号为Id的职工在数组employee中的下标,返回值为0表示没有。
int find(int Id,Info employee[],int m){
int j;
employee[0].Id=Id;
for(j=m; (1) ;j--);
return j;
}
显然,在函数find()中,首先把要查找的Id赋给数组的第一个元素,然后循环从最后一个元素开始查找,所以(1)空应填写循环结束的条件。
可能有2种情况,一是在某个记录中找到了要查的Id(根据函数要求,这时要返回Id的职工在数组employee中的下标),二是找遍整个数组都没有找到Id(根据函数要求,这时要返回0),但在循环的前面已经设置了哨兵“employee[0].Id=Id”,所以,循环至多到j=0时就会退出。
因此,(1)空应填写employee[j].Id !=Id。
然后再分析主函数的第一段程序。
Info employee[MaxNum+1];
long wage;
double sum=0,k,s;
int i,j,n=0,code;
seanf(“%d%Id”,&code,&wage);/ * 读入职工号、工资或薪金* /
while(code>O){
i=find(code,employee,n);
if(i>0)employee[i].Salary+=wage;
else{
(2) ;
Employee[n].Id=code;employee[n].Salary=wage
}
seanf(“%d%Id”,&code,&wage);
}
这里用code代表职工号,wage代表工资。
当输入一个职工的职工号和工资后,就调用find()函数查找该职工是否已经在cmployee[]中,返回值要么是0(表示该职工的信息是第一次录入,则需要在employee[]中增加一个元素,并把刚录入的值记录到该元素),要么大于0(表示该职工的信息已经存入employee[]中,则需要累加该职工的工资收入)。
所以,(2)空应填写n++。
当录入的code为一个负数时,上述循环结束,表示所有职工的数据都已经录入完毕。
接下来开始计算所得税。
计算方法是:从employee[]中逐个取出职工工资数据,按照给定的公式计算并输出该职工的所得税,同时进行累加,求出整个公司的所得税。
程序段如下:
for(i=1;i<=n;i++){
k= (3) ; / * 计算月应纳税所得额* /
s=0;/ * 月应纳税额赋初值* /
if(k>0){
for(j=1;j<=9;j++)
if( (4) ) / * 月应纳税所得额超过第j级* /
s=s+(paylevel[j]-paylevel[j-1]) * taxPratel[j-1]/100;
else{s=s+( (5) ) * taxPratel[j-1]/100;break}
}
printf(“职工%d应缴纳的个人所得税额:%10.21f\n”,employee[I].Id,s);
sumd+=S,
}
在上面的程序段中,显然,n表示职工总数,s表示当前职工应缴纳的税金,sum表示公司所有职工缴纳的总税金,k表示月应纳税所得额,所以,(3)空应填写k= employee[i].Salary-800。
下面讨论所得税的计算问题。
从题目说明中给出的计算公式中可以看出,税金的计算是采用逐级累计的方式。
根据第(4)空的注释“月应纳税所得额超过第j级”,这说明(4)空是判断当前职工的工资是否超过paylevel[j],所以,(4)空应该填写k>paylevel[j]。
如果一个职工的月应纳税所得额大于第j级,则其第j—1级收入的全额部分应按适用税率计算税额((paylevel[j]-paylevel[j-1])*taxPrate[j-1]/100);如果一个职工的月应纳税所得额不大于第j级(没有到达第j级),则其第j-1级收入的实际超出部分采用适用税率计算税额。
因此,(5)空应填写k-paylevel[j-1]。
需要注意的是,paylevel[]={0,500,2000,5000,20000,40000,60000,80000,100000,1000001};即程序中设定的级数标准的金额比题目的表格中给出的级数标准金额差1。
9、(1)Txt_salary.Text-Txt_base.Text
(2)K>PayLevel(j)
(3)K-paylevel(j-1)
(4)Txt_tax.Text
(5)False
分析
本题与试题8是同样的问题(但比试题8简单,因为这里只计算一个人的所得税),只是用VB来实现而已。
显然,在上面的程序中,K表示月应纳税所得额,所以,(1)空应填写Txt_salary.Text-Txt_base.Text。
下面讨论所得税的计算问题。
从题目说明中给出的计算公式中可以看出,税金的计算是采用逐级累计的方式。
(2)空应判断月应纳税所得额是否超过了第j级,所以,(2)空应该填写K>PayLevel[j]。
如果一个职工的月应纳税所得额大于第j级,则其第j-1级收入的全额部分应按适用税率计算税额((paylevel[j]-paylevel[j-1]) * taxPrate[j-1]/100);如果一个职工的月应纳税所得额不大于第j级(没有到达第j级),则其第j-1级收入的实际超出部分采用适用税率计算税额。
因此,(3)空应填写K-PayLevel[j-1]。
计算结束后,应该把计算结果显示在对应的文本框(Txt_tax)中,因此,(4)空是一个显示语句,即为Txt_tax.Text=Str$(S)。
因为试题要求文本框Txt_base和Txt_tax在运行时不接受用户输入,Txt_base的容以灰色显示,所以需要设计其Enabled属性(可在设计时确定,也可在窗体启动时确定,本题选择第二种方式)为False。
初级程序员2004下半年下午试题。