全国计算机等级考试《二级C语言程序设计》历年真题与模拟试题详解
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2015年9月全国计算机等级考试《二级C语言程序设计》真题及详解

(考试时间120分钟 满分100分)

一、选择题(每题1分,共40分)

1下列叙述中正确的是(  )。

A.所有数据结构必须有根结点

B.所有数据结构必须有终端结点(即叶子结点)

C.只有一个根结点,且只有一个叶子结点的数据结构一定是线性结构

D.没有根结点或没有叶子结点的数据结构一定是非线性结构

【答案】D

【解析】D项正确,线性结构的特点是:集合中必存在“第一个元素”且惟一;集合中必存在“最后一个元素”且惟一;除最后一个元素外,其他数据元素均有惟一的“后继”;除第一个元素外,其他数据元素均有惟一的“前驱”。所以没有根结点或没有叶子结点的数据结构一定是非线性结构。AB两项错误,不是所有数据结构都必须有根结点和叶子结点;C项错误,数据结构中若有中间结点不满足只有一个前件或者后件的条件,就不是线性结构。答案选择D选项。

2以下叙述中错误的是(  )。

A.C语言中的每条可执行语句和非执行语句最终都将被转换成二进制的机器指令

B.C程序经过编译、链接步骤之后才能形成一个真正可执行的二进制机器指令文件

C.用C语言编写的程序称为源程序,它以ASCII代码形式存放在一个文本文件中

D.C语言源程序经编译后生成后缀为.obj的目标程序

【答案】A

【解析】A项错误,注释语句不会被翻译成二进制的机器指令。C源程序经过C编译程序编译之后生成后缀为.obj的二进制文件(称为目标文件),然后由“链接程序”(Link)的软件把.obj文件与各种库函数连接起来生成一个后缀为.exe的可执行文件。答案选择A选项。

3C语言主要是借助以下(  )功能来实现程序模块化的。

A.定义函数

B.定义常量和外部变量

C.三种基本结构语句

D.丰富的数据类型

【答案】A

【解析】C程序的模块化主要通过函数来实现。C语言允许对函数单独进行编译,从而可以实现模块化。答案选择A选项。

4有以下程序段:

char ch; int k;
ch='a'; k =12;
printf("%c,%d,",ch,ch,k); printf("k=%d\n",k);

已知字符a的ASCII码十进制值为97,则执行上述程序段后输出的结果是(  )。

A.因变量类型与格式描述符的类型不匹配,输出无定值

B.输出项与格式描述符个数不符,输出为零值或不定值

C.a,97,12k=12

D.a,97,k=12

【答案】D

【解析】字符变量的值是该字符的ASCII码值,可以参与整型变量所允许的任何运算。“ch='a'”,%c表示以字符格式输出ch的值,所以输出为a;%d表示以十进制代码的形式输出ch的值,为97;k没有对应的输出格式,不输出。在第二个语句中,首先输出“k=”,然后以十进制代码输出k的值,为12。答案选择D选项。

5下列叙述中正确的是(  )。

A.栈是“先进先出”的线性表

B.队列是“先进后出”的线性表

C.循环队列是非线性结构

D.有序线性表既可以采用顺序存储结构,也可以采用链式存储结构

【答案】D

【解析】有序的线性表既可采用顺序存储结构,也可以采用链式存储结构。A项错误,栈是“先进后出”的线性表;B项错误,队列是“先进先出”的线性表;C项错误,循环队列是线性结构的。答案选择D选项。

6若要实现total=1+2+3+4+5求和,以下程序段错误的是(  )。

A.

int i=1,total=1;
while(i<5)
{
  total +=i;
  i+=1;
}

B.

int i=1,total=0;
while(i<=5)
{
  total +=i;
  i+=1;
}

C.

int i=0,total=0;
while(i<5)
{
  i +=1;
  total+=i;
}

D.

int i=0,total=0;
while(i<=5)
{
  total +=i;
  i+=1;
}

【答案】A

【解析】A项执行过程为:i=1,total=1,判断while循环条件1<5成立,total=1+1,i=2;判断循环条件执行函数体,直到i=4,total=1+1+2+3+4,i=5;i=5循环条件不成立,退出循环,A项不能实现题目要求,错误。B项执行过程:i=1,total=0,1<=5成立,total=0+1=1,i=2;直到i=5,total=1+2+3+4+5,i=6;i=6条件不成立,退出循环,程序正确。C项执行过程:i=0,total=0,0<5成立,i=1,total=1;直到i=5,total=1+2+3+4+5;i=5条件不成立,退出循环,程序正确。D项执行过程:i=0,total=0,0<=5成立,total=0,i=1;直到i=5,total=1+2+3+4+5,i=6;i=6条件不成立,退出循环,程序正确。答案选择A选项。

7下列不属于软件工程3个要素的是(  )。

A.工具

B.过程

C.方法

D.环境

【答案】D

【解析】软件工程是指用工程化的原则和方法来构建和维护软件,其要素包括:方法,用于完成软件工程项目的技术手段;工具,用于支持软件的开发、管理、文档生成;过程,用于支持软件开发的各个环节的控制、管理。答案选择D选项。

8下面不属于黑盒测试方法的是(  )。

A.边界值分析法

B.基本路径测试

C.等价类划分法

D.错误推测法

【答案】B

【解析】常见的黑盒测试方法有:等价类划分法、边界值分析法、错误推测法以及因果图等;常见的白盒测试方法有:逻辑覆盖测试和基本路径测试。答案选择B选项。

9有三个关系R、S和T如下:

则下列操作中正确的是(  )。

A.T=R∩S

B.T=R∪S

C.T=R×S

D.T=R-S

【答案】D

【解析】图中关系R比关系S多一行T中的元组,故由关系R和S得到关系T的操作是差。答案选择D选项。

10下列选项中,不属于数据管理员(DBA)职责的是(  )。

A.数据库维护

B.数据库设计

C.改善系统性能,提高系统效率

D.数据类型转换

【答案】D

【解析】数据库管理员对数据库进行规划、设计、维护、监视等,其主要工作有:数据库设计,主要是对数据模式进行设计;数据库维护,对数据库中的数据安全性、完整性、并发控制及系统恢复、数据定期转储等进行实施与维护;改善系统性能,不断调整内部结构,提高系统效率。答案选择D选项。

11有以下程序

#include <stdio.h>
main()
{
  int a=0,b=0;
  /*给a赋值a=10;
  b=20;给b赋值*/
  printf("a+b=%d\n",a+b);/*输出计算结果*/
}

程序运行后的输出结果是(  )。

A.a+b=0

B.a+b=30

C.a+b=10

D.出错

【答案】A

【解析】注释/*和*/之间的代码不参与编译,所以a、b的值仍为0。答案选择A选项。

12有以下程序段

#include <stdio.h>
main()
{
  int a,b,c;
  a=10;b=50;c=30;
  if(a>b)a=b,b=c;c=a;
  printf("a=%d b=%d c=%d\n",a,b,c);
}

程序的输出结果是(  )。

A.a=10 b=50 c=30

B.a=10 b=50 c=10

C.a=10 b=30 c=10

D.a=50 b=30 c=50

【答案】B

【解析】C语言中使用分号来作为语句的结束,所以a=b,b=c;是一条含有逗号运算符的语句,是if语句的执行体。因为题中a<b,if条件不满足,直接执行c=a。答案选择B选项。

13下列二叉树描述中,正确的是(  )。

A.任何一棵二叉树必须有一个度为2的结点

B.二叉树的度可以小于2

C.非空二叉树有0个或1个根结点

D.至少有2个根结点

【答案】B

【解析】空树度为0,斜二叉树度为1,故A项错误,B项正确。空二叉树没有结点,非空二叉树的定义中要求有且只有一个结点是该树的根结点,故C和D项错误。答案选择B选项。

14下列叙述中,不符合良好程序设计风格要求的是(  )。

A.程序的效率第一,清晰第二

B.程序的可读性好

C.程序中要有必要的注释

D.输入数据前要有提示信息

【答案】A

【解析】“清晰第一,效率第二”是当今主导的程序设计风格。对程序的要求不仅是能够运行正常,还要便于调试和维护,所以程序要具有良好的可读性,语句结构应该简单直接,这有利于程序的开发与维护。答案选择A选项。

15有以下程序

#include <stdio.h>
main()
{
  int x,y,z;
  x=y=1;
  z=x++,y++,++y;
  printf("%d,%d,%d\n",x,y,z);
}

程序运行后的输出结果是(  )。

A.2,3,1

B.2,3,2

C.2,3,3

D.2,2,1

【答案】A

【解析】注意区分,z=x++是先将x的值赋给z,再令x自增;z=++x是先将x自增,再将自增后的值赋给z;而无论是++x还是x++,都会完成x自增的运算。对于表达式“z=x++,y++,++y;”,因为赋值运算符的优先级高于逗号运算符的优先级,所以可以将上式改成“(z=x++),(y++),(++y)”。然后从左向右先计算表达式z=x++,后缀自增运算先进行其他运算,再执行自增运算,所以z的值为1,x的值为2,再计算逗号表达式第二个表达式y++,此时y的值为1,y++的值为2,最后计算第三个表达式++y,y的值为3。答案选择A选项。

16设二叉树如下:

则后序序列为(  )。

A.ABDEGCFH

B.DBGEAFHC

C.DGEBHFCA

D.ABCDEFGH

【答案】C

【解析】后序遍历,先访问左子树,再访问右子树,最后访问根结点。法一:本题中,树不为空,所以先后序遍历左子树,得DGEB,再后序遍历右子树,得HFC,最后访问根结点。所以该二叉树的后序序列为DGEBHFCA。法二:由后序遍历的过程知,树的根结点一定是最后遍历到,即A结点一定在遍历序列的最后,答案选择C选项。

17以下叙述中正确的是(  )。

A.break语句不能用于提前结束for语句的本层循环

B.使用break语句可以使流程跳出switch语句体

C.continue语句使得整个循环终止

D.在for语句中,continue与break的效果是一样的,可以互换

【答案】B

【解析】B项正确,break语句可以跳出switch语句和循环。A项错误,break语句在for循环内部的作用是跳出循环;C项错误,continue语句的作用是跳过本次循环体中余下尚未执行的语句,立刻进行下一次的循环条件判定,即仅结束本次循环,并没有使整个循环终止;D项错误,continue和break的效果完全不同。答案选择B选项。

18有以下程序:

#include <stdio.h>
main()
{
  int a=1,b=0;
  if(--a) b++;
  else if(a==0) b+=2;
  else b+=3;
  printf("%d\n",b);
}

程序运行后的输出结果是(  )。

A.0

B.1

C.2

D.3

【答案】C

【解析】“++”和“--”运算,当以前缀形式出现时,则先进行加一或减一操作,再进行其他运算,当以后缀形式出现时,则先进行其他运算,再进行加一或减一操作。a初始定义为1,b为0,执行--a,a的值变为0,--a的值也为0,即if判断为假,执行b+=2,输出b的值为2。答案选择C选项。

19待排序的关键码序列为(15,20,9,30,67,65,45,90),要按关键码值递增的顺序排序,采取简单选择排序法,第一趟排序后关键码15被放到第(  )个位置。

A.2

B.3

C.4

D.5

【答案】B

【解析】简单选择排序的算法可以描述为:将整个待排序序列分为有序和无序两部分,初始时有序部分为空;每一趟排序时扫描无序序列,找到最小的元素,将它与无序序列的首元素交换位置,直到无序序列为空。所以第一趟排序后,将选出的最小元素9与15交换,15被放在第3个位置。答案选择B选项。

20下列关系表达式中,结果为“假”的是(  )。

A.(3+4)>6

B.(3!=4)>2

C.3<=4||3

D.(3<4)==1

【答案】B

【解析】A项,先执行3+4=7,7>6,结果为真;B项,先执行3!=4为真,即为1,1>2结果为假;C项,先执行3<=4结果为真,即1,再逻辑或运算只要左边值为1,就不在执行右边运算,结果为真;D项,先执行3<4结果为真,即为1,再执行1==1,结果为真。答案选择B选项。

21有如下程序:

#include <stdio.h>
main()
{
  int i;
  for (i=0;i<5;i++)
    putchar('9'-i);
  printf("\n");
}

程序运行后的输出结果是(  )。

A.54321

B.98765

C.'9''8''7''6''5'

D.'43210'

【答案】B

【解析】本题执行过程为:i=0,输出字符9,在i<5的情况下,依次输出字符8、7、6、5。在i=5时,退出for循环。最后显示在命令窗口结果为98765。答案选择B选项。

22下列叙述中正确的是(  )。

A.可以用关系运算符比较字符串的大小

B.空字符串不占用内存,其内存空间大小是0

C.两个连续的单引号是合法的字符常量

D.两个连续的双引号是合法的字符串常量

【答案】D

【解析】A项错误,关系运算符不能比较字符串大小,可以用函数库中的字符串比较函数来比较字符串的大小;B项错误,空字符串占用一个字节的内存;C项错误,字符常量是用单引号把一个字符括起来;D项正确,两个连续的双引号是一个字符串常量,称为空串。答案选择D选项。

23以下关于C语言函数参数传递方式的叙述正确的是(  )。

A.数据只能从实参单向传递给形参

B.数据可以在实参和形参之间双向传递

C.数据只能从形参单向传递给实参

D.C语言的函数,参数既可以从实参单向传递给形参,也可以在实参和形参之间双向传递,可视情况选择使用

【答案】A

【解析】数据只能由实参单向传递给形参称为“值传递”,而不能由形参传给实参,A项正确,B、C、D错误;数组名、指针等作参数,实参传递给形参的是地址值,这样形参和实参就指向同一段内存单元,在函数体内对形参数据的改变也将影响到实参。答案选择A选项。

24以下叙述中错误的是(  )。

A.当在程序的开头包含头文件stdio.h时,可以给指针变量赋NULL

B.函数可以返回地址值

C.改变函数形参的值,不会改变对应实参的值

D.可以给指针变量赋一个整数作为地址值

【答案】D

【解析】A项正确,NULL是在头文件stdio.h中定义的符号常量;B项正确,函数的返回值可以是地址,即指针;C项正确,函数调用中形参值的变化不会传递给实参;D项错误,不能将一个整数直接赋给指针变量作为地址,只能用取地址运算符“&”把该整型变量的地址赋值给该指针变量。答案选择D选项。

25有以下程序(说明:字母A的ASCII码值是65):

#include <stdio.h>
void fun(char *s)
{
  while(*s)
  {
    if(*s%2)printf("%c",*s);
    s++;
  }
}
main()
{
  char a[]="BYTE";
  fun(a);
  printf("\n");
}

程序运行后的输出结果是(  )。

A.BY

B.BT

C.YT

D.YE

【答案】D

【解析】函数只会输出ASCII码值为奇数的字母,执行fun(a)时,依次取出a[]中的字母,因为B的ASCII码值为66,所以不会输出B,字母Y的ASCII码值为89,字母T的ASCII码值为84,字母E的ASCII码值为69,所以最后输出字母YE。答案选择D选项。

26有以下程序:

#include <stdio.h>
main()
{
  …
  while(getchar()!='\n');
  …
}

以下叙述中正确的是(  )。

A.此while语句将无限循环

B.getchar()不可以出现在while语句的条件表达式中

C.当执行此while语句时,只有按回车键程序才能继续执行

D.当执行此while语句时,按任意键程序就能继续执行

【答案】C

【解析】本题中while循环条件为getchar()!='\n',表示只要不输入回车键,getchar()!='\n'语句一直为真,则while循环会出现空循环,当按下回车键后跳出while循环执行下一条语句。答案选择C选项。

27有以下程序:

#include <stdio.h>
void f(int *p,int *q);
main()
{
  int m=1,n=2,*r=&m;
  f(r,&n);
  printf("%d,%d",m,n);
}
void f(int *p,int *q)
{
  p=p+1;
  *q=*q+1;
}

程序运行后的输出结果是(  )。

A.1,3

B.2,3

C.1,4

D.1,2

【答案】A

【解析】语句p=p+1;只改变指针p的地址,与p的内容无关,所以m值没有改变,而语句*q=*q+1;是改变该指针所指地址中的内容,所以n变为3,m不变,仍为1,答案选择A选项。

28以下函数按每行8个输出数组中的数据:

void fun(int *w,int n)
{
  int i;
  for(i=0;i<n;i++)
  {
    ______
    printf("%d",w[i]);
  }
  printf("\n");
}

下画线处应填入的语句是(  )。

A.if(i/8==0)printf("\n");

B.if(i/8==0)continue;

C.if(i%8==0)printf("\n");

D.if(i%8==0)continue;

【答案】C

【解析】每行输出8个数组数据后输入一个换行,所以应该采取对8取余的方法,余数循环一次便换行一次,所以语句为if(i%8==0) printf("\n");,答案选择C选项。

29以下叙述中正确的是(  )。

A.函数的形参类型不能是指针类型

B.函数的类型不能是指针类型

C.设有指针变量为double *p,则p+1将指针p移动8个字节

D.基类型不同的指针变量可以相互混用

【答案】C

【解析】C项正确,一般情况下,double类型的变量长度为8个字节,对指针进行加、减运算时,数字“1”指1个存储单元长度。A项错误,函数的形参可以是数值类型,也可以是指针类型;B项错误,C语言中有指向函数的指针,称为函数指针;D项错误,int类型的指针只能指向int,不能指向double,基类型不同的指针变量不能混用。答案选择C选项。

30设有以下定义:

char s1[]="0123";

char s2[]={'0','1','2','3'};

则以下叙述正确的是(  )。

A.数组s1的长度小于s2的长度

B.数组s1和s2的长度相同

C.数组s1的长度大于s2的长度

D.数组s1和s2完全等价

【答案】C

【解析】字符数组s1赋值字符串"0123",字符串中字符依次放入数组中,在最后一个字符后要添加一个结束字符'\0',数组s1长度为5。数组s2只需要4个单元即可放下所有初始化值,故数组长度为4。所以数组s1的长度大于s2的长度,C项正确,AB错误。两个数组等价是指两个数组长度和类型以及对应每个元素值均相同,所以s1和s2不是完全等价,D项错误。答案选择C选项。

31有以下程序(strcpy为字符串复制函数,strcat为字符串连接函数):

#include <stdio.h>
#include <string.h>
main()
{
  char a[10] ="abc",b[10]="012",c[10]="xyz";
  strcpy(a+1,b+2);
  puts(strcat(a,c+1));
}

程序运行后的输出结果是(  )。

A.a12xyz

B.12yz

C.a2yz

D.bc2yz

【答案】C

【解析】先执行strcpy,将b数组中第2个及之后位置上的字符复制到a数组中第1个及之后的位置上的字符位置,即此时数组a中字符为a2,再执行strcat连接函数,将a中字符与c数组中第2个及之后位置上的字符连接,即为a2yz。注意,数组下标从0开始。答案选择C选项。

32以下叙述中正确的是(  )。

A.简单递归不需要明确的结束递归的条件

B.任何情况下都不能用函数名作为实参

C.函数的递归调用不需要额外开销,所以效率很高

D.函数既可以直接调用自己,也可以间接调用自己

【答案】D

【解析】D项正确,C语言中的函数可以直接或间接地自己调用自己,前者称简单递归,后者称间接递归。A项错误,递归必定要有一个明确的结束递归的条件;B项错误,递归就是把函数名作为实参的一种特殊情况;C项错误,函数的递归调用过程中,系统要为每一层调用中的变量开辟存储单元,记住每一层调用后的返回点,要增加许多额外的开销,通常会降低程序的运行效率。答案选择D选项。

33有以下函数:

#include <stdio.h>
void func(int n)
{
  int i;
  for(i=0;i<=n;i++)printf("*");
  printf("#");
}
main()
{
  func(3);
  printf("????");
  func(4);
  printf("\n");
}

程序运行后的输出结果是(  )。

A.****#????***#

B.***#????*****#

C.**#????*****#

D.****#????*****#

【答案】D

【解析】从main函数开始,执行func(3)函数,for循环执行4次,连续输出四个“*”,然后输出一个“#”;输出“????”;再次调用func(4),for循环执行5次,连续输出五个“*”,然后输出一个“#”;最后输出换行符。答案选择D选项。

34有以下程序:

#include <stdio.h>
int b=2;
int fun(int *k)
{
  b=*k+b;
  return(b);
}
main()
{
  int a[10]={1,2,3,4,5,6,7,8},i;
  for(i=2;i<4;i++)
  {
    b=fun(&a[i])+b;
    printf("%d",b);
  }
  printf("\n");
}

程序运行后的输出结果是(  )。

A.1012

B.810

C.1028

D.1016

【答案】C

【解析】因为int是全局变量,所以它的值在整个程序结束时才会消失。for循环第一次i=2,a[i]=3,所以fun(&a[i])=3+2=5,这时b为5,所以b=fun(&a[i])+b=5+5=10。第二次循环时,b=10,然后fun(&a[i]),代入a[i]=4,这时fun(&a[i])=10+4=14,所以b=fun(&a[i])+b=14+14=28。答案选择C选项。

35以下叙述中正确的是(  )。

A.在C语言中,预处理命令行都以“#”开头

B.预处理命令行必须位于C源程序的起始位置

C.#include<stdio.h>必须放在C程序的开头

D.C语言的预处理不能实现宏定义和条件编译的功能

【答案】A

【解析】“编译预处理”就是在C编译程序对C源程序进行编译前,由编译预处理程序对这些编译预处理命令行进行处理的过程。A项正确,在C语言中,凡是以“#”号开头的行,都称为“编译预处理”命令行。B项错误,预处理命令行可以出现在程序的任何一行的开始部位,其作用一直持续到源文件的末尾;C项错误,#include<stdio.h>可以出现在程序的任意一行的开始部位;D项错误,预处理可以实现宏定义、条件编译和文件包含。答案选择A选项。

36有以下程序:

#include <stdio.h>
main()
{
  char a,b,c,d;
  scanf("%c%c",&a,&b);
  c=getchar();
  d=getchar();
  printf("%c%c%c%c\n",a,b,c,d);
}

当执行程序时,按下列方式输入数据(从第一列开始,<CR>代表回车,注意:回车是一个字符)

12<CR>

34<CR>

则输出结果是(  )。

A.1234

B.12

C.12<CR>3

D.12<CR>34

【答案】C

【解析】scanf()函数的一般调用形式为:scanf(格式控制,输入地址列表)。其中,格式控制是用双引号括起来的字符串,包括格式字符和普通字符,格式是由“%”和格式字符组成。getchar()函数的功能是从标准输入设备上读入一个字符。根据程序中的格式控制可知,接收输入时分别把1赋给了a,2赋给了b,然后getchar()函数提取一个换行符赋给c,再提取一个字符3赋给了d。所以程序的输出结果为:12<CR>3。答案选择C选项。

37在C语言中,只有在使用时才占用内存单元的变量,其存储类型是(  )。

A.auto和register

B.extern和register

C.auto和static

D.static和register

【答案】A

【解析】C语言中,动态存储区域中存放的变量在使用时才分配内存空间。auto变量的存储单元是分配在内存的动态存储区中,每当进入函数体时自动分配存储单元。register变量也是自动类变量。static说明的变量为静态变量,静态变量在内存的静态存储中占据着永久的存储单元,直至程序运行结束。extern说明的变量为外部变量,属于全局变量,全局变量在整个程序运行期间都占用内存空间。答案选择A选项。

38以下程序:

#include <stdio.h>
void fun(int x)
{
  if(x/2>1) fun(x/2);
  printf("%d",x);
}
main()
{
  fun(7);
  printf("\n");
}

程序运行后的结果是(  )。

A.137

B.731

C.73

D.37

【答案】D

【解析】函数fun是递归函数,递归终止条件是x小于等于3,当大于3时递归调用fun(x/2)。第一次循环x/2=3,调用fun(3),x/2=1,跳出if循环,执行输出x=3,然后回到第一次循环,执行if循环的语句,输出x=7。答案选择D选项。

39以下结构体类型说明和变量定义中正确的是(  )。

A.typedef struct{int n;char c;}REC;REC t1,t2;

B.struct REC;{int n;char c;};REC t1,t2;

C.typedef struct REC:{int n=0;char c='A';}t1,t2;REC t1,t2;

D.struct{int n;char c;}REC;

【答案】A

【解析】A项,用typedef定义结构体类型名REC后,可以用REC定义变量。B项,“struct REC;”后面不应加分号;C项,没有这样的书写形式;D项,REC定义的是一个变量,不是结构体类型,因此不能用来定义结构体变量。答案选择A选项。

40以下叙述正确的是(  )。

A.在C语言中调用fopen函数就可把程序中要读、写的文件与磁盘上实际的数据文件联系起来

B.fopen函数的调用形式为:fopen(文件名)

C.fopen函数的返回值为NULL时,则成功打开指定的文件

D.fopen函数的返回值必须赋给一个任意类型的指针变量

【答案】A

【解析】A项正确,C语言中打开一个文件通过系统函数fopen实现,通过这个函数把程序中要读、写的文件与磁盘上实际的数据文件联系起来;B项错误,函数调用中缺少参数“操作方法”,其调用的一般形式为:文件指针名=fopen(文件名,使用文件方式);;C项错误,fopen函数返回一个指向指定文件的文件指针,如果不能实现打开指定文件的操作,则返回一个空指针NULL;D项错误,fopen函数的返回值必须赋给一个文件类型的指针变量。答案选择A选项。

二、程序填空题(共18分)

请补充fun函数,该函数的功能是:计算N×N维矩阵元素的方差,结果由函数返回。维数在主函数中输入。

例如:

的计算结果是14.414。

求方差的公式为:

其中

注意:

请勿改动主函数main和其他函数中的任何内容,仅在函数fun的横线上填入所编写的若干表达式或语句。

【试题源程序】

#include <stdio.h>
#include <stdlib.h>
#define N 20
/**********found**********/
double fun(______,int n)
{
  int i,j;
  double s=0.0;
  double f=0.0;
  double aver=0.0;
  double sd=0.0;
  for(i=0;i<n;i++)
    for(j=0;j<n;j++)
      s+=a[i][j];
  /**********found**********/
  aver=______;
  for(i=0;i<n;i++)
    for(j=0;j<n;j++)
      f+=(a[i][j]-aver)*(a[i][j]-aver);
  f/=(n*n);
  /**********found**********/
  sd=______;
  return sd;
}
main()
{
  int a[N][N];
  int n;
  int i,j;
  double s;
  printf("*****Input the dimension of array n******\n");
  scanf("%d",&n);
  printf("*****The array*****\n");
  for(i=0;i<n;i++)
  {
    for(j=0;j<n;j++)
    {
      a[i][j]=rand()%50;
      while (a[i][j]==0)
        a[i][j]=rand()%60;
      printf("%4d",a[i][j]);
    }
    printf("\n\n");
  }
  s=fun(a,n);
  printf("*****THE RESULT*****\n");
  printf("%4.3f\n",s);
}

答:

int a[][N]

s/(n*n)

sqrt(f)

【解析】根据题目中的方差公式,先要计算矩阵元素的平均值,再求矩阵元素与平均值差的平方的平均值,最后调用库函数求方差。

填空1:根据函数中各变量的使用情况及实参的类型,这里应该是对二维数组a的定义,因为二维数组做形参,可以省略第一维的长度,但不能省略第二维的长度,所以此处应填int a[][N]。

填空2:这里求矩阵元素的平均值,注意元素的个数应该是n*n。

填空3:此处应该调用库函数sqrt()求平方根,同时程序需要加上#include<math.h>。

三、程序修改题(共18分)

下列给定程序中,函数fun()的功能是:将n个无序整数从小到大排序。请改正程序指定部位的错误,使它能得到正确结果。

注意:

不要改动函数main(),不得增行或删行,也不得更改程序的结构。

【试题源程序】

#include <stdio.h>
void fun(int n, int *a)
{
  int i,j,p,t;
  for(j=0;j<n-1;j++)
  {
    p=j;
    /**********found**********/
    for(i=j+1;i<n-1;i++)
      if(a[p]>a[i])
        /**********found**********/
        t=i;
    if(p!=j)
    {
      t=a[j];
      a[j]=a[p];
      a[p]=t;
    }
  }
}
void putarr(int n, int *z)
{
  int i;
  for(i=1;i<=n;i++,z++)
  {
    printf("%4d",*z);
    if(!(i%10))
      printf("\n");
  }
  printf("\n");
}
void main()
{
  int aa[20]={9,3,0,4,1,2,5,6,8,10,7},n=11;
  printf("\n\nBefore sorting %d numbers:\n",n);
  putarr(n,aa);
  fun(n,aa);
  printf("\nAfter sorting %d numbers:\n",n);
  putarr(n,aa);
}

答:

(1)错误:for(i=j+1;i<n-1;i++)

正确:for(i=j+1;i<n;i++)

(2)错误:t=i;

正确:p=i;

【解析】

错误1:选择排序法是在外循环中从第一个元素开始,依次与比它小的元素进行交换,直到交换完第n-1个元素,最后一个元素就是最大的元素,循环次数为n-1次,如果设定循环次数为n次,则最后一次第n个元素与自己交换;内循环是找出比当前元素更小的元素,故是从当前需要交换的元素的下一个元素开始,直到第n个元素。故“for(i=j+1;i<n-1;i++)”应改为“for(i=j+1;i<n;i++)”。

错误2:t是fun函数中用来交换两个元素的辅助变量,不是交换元素下标的变量,因此t=i;是错误的。p是用来记录当前最小元素下标的,当a[p]>a[i]时,把i赋给p。所以“t=i;”应改为“p=i;”。

四、程序设计题(共24分)

函数fun的功能是:将a、b中的两个两位正整数合并形成一个新的整数放在c中,合并的方式是:将a中的十位和个位数依次放在变量c的千位和十位上,b中的十位数和个位数依次放在变量c的个位和百位上。

例如:a=45,b=12。调用该函数后:c=4251。

注意:

请勿改动主函数main和其他函数中的任何内容,仅在fun函数的花括号中填入所编写的若干语句。

【试题源程序】

#include <stdio.h>
void fun(int a, int b, long *c)
{
 
}
void main()
{
  int a,b;
  long c;
  printf("Input a,b:");
  scanf("%d%d",&a,&b);
  fun(a,b,&c);
  printf("The result is:%ld\n",c);
}

答:

void fun(int a , int b, long *c)
{
  *c=(a/10)*1000+(b%10)*100+(a%10)*10+b/10;
}

【解析】本题的主要问题是如何取出a和b的个位数和十位数,取出后如何表示成c中相应的位数。由于a和b都是只有两位的整数,所以分别对它们除10可得到它们的十位数,分别用10对它们求余可得到它们的个位数。得到后对应乘以1000、100、10、1就可得到c的千位数、百位数、十位数和个位数。注意:使用c时要进行指针运算。