2016 下半年程序员考试真题及答案-下午卷
试题一(共 15 分)
阅读以下说明和流程图,填补流程图中的空缺,将解答填入答题纸的对应栏内。
【说明】
设有整数数组 A[1:N](N>1),其元素有正有负。下面的流程图在该数组中寻找连续排
列的若干个元素,使其和达到最大值,并输出其起始下标 K、元素个数 L 以及最大的和值 M。
例如,若数组元素依次为 3,-6,2,4,-2,3,-1,则输出 K=3,L=4,M=7。该流程图
中考察了 A[1:N]中所有从下标 i 到下标 j(j≥i)的各元素之和 S,并动态地记录其最大
值 M。
【流程图】
注:循环开始框内应给出循环控制变量的初值和终值,默认递增值为 1,格式为:循环
控制变量=初值,终值
1、i,N
2、S+A[j]
3、S
4、j-i+1
5、S
要想在数组中寻找连续排列的若干个元素,使其和达到最大值,并输出其起始下标 K、
元素个数 L 以及最大的和值 M。
那么,会将数组从第一个元素出发,依次比较 A[1],A[1] +A[2],A[1] +A[2]+A[3],……,
A[1] +A[2]+…+A[N],然后再比较 A[2], A[2] +A[3],A[2] +A[3]+A[4],……,A[2] +A[3]+…
+A[N],然后再比较 A[3] +A[4],A[3] +A[4]+A[5],……,A[3] +A[4]+…+A[N],直到最
后一个元素 A[N].
按照这种逻辑,要使用两个循环,且要保存之前求和项。一个是 i 循环,从 1 到 N 递增,
另一个是 j 循环,j 表示的是求和项的最大下标值,那么 j 从 i 开始,且要小于 N。 S+A[j]
—>S 不断保留 A[i]+ A[i+1]+…A[j]的值,直到 j 循环结束。并将 S 的值与之前保存的 M
的值进行比较,如果 S>M,则将 S 的值赋给 M,并求出 L 值,在这里,i 是最小下标值,j
是最大下标值,那么 L=j-i+1。如果 S
试题二(共 15 分)
阅读以下代码,回答问题:1 至问题 3 ,将解答填入答题纸的对应栏内。
【代码 1】
#include
void swap(int x, int y)
{
}
int tmp =x; x= y; y= tmp;
int maim()
{
}
int a= 3, b= 7;
printf("a1= %d b1=%d\n",a,b);
Swap( a, b);
Printf("a2 = %d b2=%d\n”,a,b);
return 0;
【代码 2】
#include
#define SPACE ¨ //空格字符
Int main()
{
char str[128] =”Nothing is impossible! “;
int i,num =0,wordMark=0;
for(i=0;str[i];i++)
If(str[i]=SPACE)
WordMark=0;
else
If(wordMark=0){
wordMark=1;
Mun++;
}
Printf(“%d/n”,num)
retun 0;
}
【代码 3】
#include
#define SPACE “//空格字符
int countStrs(char *);
int main()
{
}
char str[128] = " Nothing is impossible! ";
Printf(‘%d/n,(1)(str))
retum 0;
int countStrs(char *p)
{
int num=0, wordMark= 0;
for(;(2);p++) {
If((3)=SPACE)
wordMark= 0;
else
if( !wordMark ) {
wordMark = 1;
++num
}
}
return(4)
}
【问题 1】(4 分)
写出代码 1 运行后的输出结果。
a1=3
b1=7
a2=3
b2=7
【问题 2】(3 分)
写出代码 2 运行后的输出结果。
3
【问题 3】(8 分)
代码 3 的功能与代码 2 完全相同,请补充 3 中的空缺,将解答写入答题纸的对应栏内。
1) CountStr
2) *p
3) *p
4) num
此题考查 C 语言程序设计能力,要求掌握形参与实参,值传递与引用传递的区别
1、 本题考查函数中值传递与引用传递,在实参与形参传递过程中可以是值传递,值传
递时,形参的改变不会影响实参,引用传递是地址的传递,实参将地址传递给形参时,形参
的改变会影响实参的改变。在本题中的第一次输出 a,b 变量的值时,结果是直接输出,所以
a1=3,b1=7,而在调用 swap 函数时,实参 a,b 传递的是值传递,在函数 swap(int x,int y)
中形参 x,y 也是值类型,在函数 swap 内部是交换两个变量的值,交换完毕后 x=y,y=x,但这
个改变不会影响实参 a,b,所以第二次输出 a2,b2 时,a,b 的值不变还是 3,7,所以输出结
果是:a1=3
b1=7 a2=3
b2=7
2、 本题是计算出字符数组中有多少个单词,单词之间是以空格’ ‘为标识,即遇到
空格时变量 wordMark=0,程序中再判断 wordMark 是否等于 0,若等于 0,则变量 workMark
置为 1,同时变量 num 是用于统计单词个数,此时 num 加 1,最后输出 num 的值就是统计的
单词个数。程序运行结果是 3。
3、 本题是将上面的功能通过调用函数来完成的。第 1 处就应该直接填写调用函数的函
数名,即 countStrs,调用者将数组名作为实参,数组名代表的是数组的首地址,所以这里
是引用传递,函数 countStrs 的形参 p 是一个指针变量,它接收实参 str 数组的首地址,这
样实参与形参都是指针变量。在函数 countStrs 内部,定义两个局部变量 num 用于统计个数,
WordMark 用于标识空格,在 for 循环中,第 2 处应该设置终止条件,即*p,表示指针指向
的内容不为空,第 3 处是判断当前的指向元素是否等于 SPACE,即当前的*p 是否是空格’‘,
如果是则将标识变量 WordMark 等于 0,否则变量 num 自增,最后函数应该返回 num 的值,
所以 4 处应该填 num。答案是:1) countStrs
2) p[i]!='\0'或者是 p[i]
3) p[i]
4)
num
试题三(共 15 分)
阅读以下说明和代码,填补代码中的空缺,将解答填入答题纸的对应栏内。
【说明】
下面的程序利用快速排序中划分的思想在整数序列中找出第 k 小的元素(即将元素从小
到大排序后,取第 k 个元素)。
对一个整数序列进行快速排序的方法是:在待排序的整数序列中取第一个数作为基准
值,然后根据基准值进行划分,从而将待排序的序列划分为不大于基准值者(称为左子序列)
和大于基准值者(称为右子序列),然后再对左子序列和右子序列分别进行快速排序,最终
得到非递减的有序序列。
例如,整数序列“19, 12, 30, 11,7,53, 78, 25"的第 3 小元素为 12。整数序列“19,
12,7,30, 11, 11,7,53. 78, 25, 7"的第 3 小元素为 7。
函数 partition(int a[], int low,int high)以 a[low]的值为基准,对 a[low]、
a[low+l]、…、
a[high] 进 行 划 分 , 最 后 将 该 基 准 值 放 入 a[i] (low ≤ i ≤ high) , 并 使 得 a[low] 、
a[low+l]、,..、
A[i-1]都小于或等于 a[i],而 a[i+l]、a[i+2]、..、a[high]都大于 a[i]。
函 教 findkthElem(int a[],int startIdx,int endIdx,inr k) 在 a[startIdx] 、
a[startIdx+1]、...、a[endIdx]中找出第 k 小的元素。
【代码】
#include
#include
Int partition(int a [],int low, int high)
{//对 a[low..high]进行划分,使得 a[low..i]中的元素都不大于 a[i+1..high]中的元素。
int pivot=a[low]; //pivot 表示基准元素
Int i=low,j=high;
while((1)){
While(ipivot)--j;
a[i]=a[j]
While(ipivot)++i;
a[j]=a[i]
}
(2); //基准元素定位
return i;
}
Int findkthElem(int a[],int startIdx,int endIdx, int k)
{//整数序列存储在 a[startldx..endldx]中,查找并返回第 k 小的元素。
if
(startldx<0
||endIdx<0
||
startIdx>endIdx
||
k<1
||k-l>endIdx
||k-1