一、单选题
A.ABc B.abc C.Abc D.Ab.c
【答案】D
【解析】本题考点是标识符的命名规则:只能由字母、数字和下划线三种字符组成,开头必须是字母或下划线,不能为系统关键字,区分大小写。D 选项中,“.”是非法字符。
2.(2017)分析以下程序,下列说法正确的是( )。
#include<stdio.h>
void main()
{
int x=3,a=3,b=3;
if(x=a+b)
printf("∗∗∗∗");
else
Printf("@@@@");
}
A.输出:∗∗∗∗ B.输出:@@@@
C.不能通过编译,有语法错误 D.能通过编译,但不能连接
【答案】A
【解析】本题考点是区分“=”和“==”两个运算符。if 表达式“x=a+b”是赋值号,而“a+b”的值是6。6 的条件是真,所以执行语句“printf("∗∗∗∗");”,选项A 正确。
3.(2017)若“int a;float b=12.2;”,则执行“a=(int)b%3;”后,a 的值是( )。
A.1 B.0 C.2.2 D.1.22
【答案】B
【解析】本题考点是强制转换运算符和求余运算符的运算规则。表达式“a=(int)b%3;”先执行“(int)b”,将变量b 强制转换为int 是12,再计算12%3,值是0,0 再赋给整型变量a。所以B 选项正确。
4.(2018)若“int a=12;”,执行“a/=a+8;”后,a 的值是( )。
A.1 B.8 C.9 D.0
【答案】D
【解析】本题考点是复合赋值表达式。表达式“a/=a+8”可以写成“a=a/(a+8)”,也就是“a=12/20”,由于a 是整型,所以a 的值是0。故选D。
5.(2018)若“int a=5,b;”,执行“b=a>>2;”后,b 的值是( )。
A.10 B.20 C.1 D.2
【答案】C
【解析】本题考点是右移位运算符。首先将a 的值以二进制补码形式写出:00000000 00000101,再往右移走两位,低位移出两位,高位补0,得到结果是00000000 00000001。所以变量b 的值是1。故选C。
6.(2018)若“char a[6]=" abcde";”,执行“printf("%d",strlen(a));”后,输出结果是( )。
A.5 B.6 C.7 D.e
【答案】A
【解析】本题考点是stelen(),求字符串长度函数。strlen(a)是求数组a 有效字符个数,数组a 里有“abcde”,有效字符长度是5 个字符(有效字符是指第一个结束标志之前的字符),在这里要区分sizeof 的使用方法。故选A。
7.(2019)已知“int w=1,x=2,y=3,z=4;”,则表达式“w>x?w:z>y?z:x”的值是( )。
A.1 B.2 C.3 D.4
【答案】D
【解析】本题考点是条件表达式的嵌套运算。表达式“w>x?w:z>y?z:x”先判断表达式1“w>x”,不大于,条件为假,就以表达式3“z>y?z:x”的值作为整个表达式的值。而表达式“z>y?z:x”又是一个条件表达式。再来先判断表达式1“z>y”,大于,条件成立,就以表达式2“z”的值作为整个表达式的值。故选D。
8.(2019)若有定义语句“int a[3][5];”,按内存中的数据存放顺序,a 数组的第10 个元素是( )。
A.a[1][4] B.a[1][3] C.a[2][3] D.a[2][4]
【答案】A
【解析】本题考点是二维数组在内存中的存放顺序。在TC 中,二维数组是按行存放在内存中的:a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[1][0],a[1][1],a[1][2],a[1][3],a[1][4],a[2][0],a[2][1],a[2][2],a[2][3],a[2][4],所以第10 个元素是a[1][4]。故选A。
9.(2019)已知“inta=1,b=2,c=3,x;”与“x=(a^b)&c;”,则x 的值为( )。
A.0 B.1 C.2 D.3
【答案】D
【解析】本题考点是位运算符与表达式。表达式“x=(a^b)&c”,先计算(a^b)的值,是0001^0010=0011(异或运算符“^”运算规则是当对应二进制位相同为0,相反为1);再和c 做按位与运算:0011&0011=0011(按位与运算规则是对应的两个二进制位均为1 时,结果为1,否则为0)。故选D。
二、综合应用题
1.(2017)从键盘上输入一个百分制成绩score,按下列原则输出其评分等级:
score≥90,等级为A;
80≤score<90,等级为B;
70≤score<80,等级为C;
60≤score<70,等级为D;
score<60,等级为E。
请补全下列代码:
#include <stdio.h>
void main()
{
int data;
____①___/ /定义grade 字符变量
printf("请输入成绩:");
scanf("%d",____②___);
switch(data/10)
{
case 10:
case 9:grade='A';break;
case 8:grade='B';break;
case 7:grade='C';break;
case 6:grade='D';break;
____③_
}
printf("评分等级为:%c",____④___);
}
【答案】①char grade; ②&data; ③default grade='E'; ④grade
【解析】第①空:需要定义一个字符型变量,关键字是char。
第②空:输入数值给变量,需要加取地址符“&”,而程序共两个变量,其中,grade 变量用于保存等级,是字符型变量,而data 变量是整型变量,正好用于接收成绩。
第③空:题意一共是5 个等级,程序中已经给出其中4 个等级,只剩下小于60 分等级为“E”的成绩,所以可以采用关键字default 把这类成绩置为“E”等级,default grade='E'。
第④空:输出等级,而等级保存在字符变量grade 中。
2.(2018)入夏标志着春夏季节完成转换,气候学上入夏的标准是必须要连续5 天日平均气温达到22 ℃或以上,则这连续5 天中的第一天为入夏日。函数fun 的功能是判断5月份是否入夏并输出有关信息,若入夏,就返回是哪天,否则,返回-1。请补全下列代码。
#include <stdio.h>
int fun(int a[],int n){ /∗a 存放某月的每日气温值,n 存放的是此月的天数∗/
int i,c=0;
for(i=0;i<n;i++){
if(____①___){
c++;
if(c>=5)____②___;
else____③___;
}
____④___;
}
return -1;
}
int main()
{
int t[31]={20,21,22,22,19,18,18,19,22,23,
22,21,20,21,24,22,25,24,23,
21,23,22,21,22,25,26,30,28,27,28}
int d;
d=fun(t,31);
if(d==-1)
printf("Not in summer\n")
else
printf("5-%d in summer\n",d+1);
return 0;
}
【答案】①a[i]>=22 ②return i-5 ③continue ④c=0
【解析】在第①空:fun 函数中,变量c 用于记录是否有连续5 天温度达到22 ℃,所以,第①空要判断第i 天的温度是否大于或等于22 ℃。
第②空:如果有连续5 天温度大于或等于22 ℃,就要返回这5 天当中的第一天,所以是:return i-5。
第③空:如果温度大于或等于22 ℃,但又还没有满足连续5 天,还要接着往下继续循环判断,用语句continue。
第④空:如果不是连续出现5 天温度大于或等于22 ℃的天气,需要将c 的值置为0,再重新统计。
3.(2019)下面程序功能是统计5 个同学成绩(1~100 间的整数)中低于平均成绩的人数并输出,请补全以下代码。
#include <stdio.h>
main()
{ int i,count=0;
____①___;
float ave=0.0;
printf("input 5 scores:\n");
for(i=0;i<5;i++)
{____②___;
ave+=score[i];
}
____③___;
for(i=0;i<5;i++)
if(____④___)
count++;
printf("%2d",count);
}
【答案】int score[5] ②scanf("%d",&score[i]) ③ave/=5 ④score[i]<ave
【解析】第①空:需要定义一个数组,用于保存5 个同学的成绩。
第②空:给5 个同学输入成绩,采用scanf("%d",&score[i])语句。
第③空:在输入成绩时已求出总分,但根据题意,需要求出平均分才能求出低于平均分的人数。
第④空:从输出语句可以看出,count 变量累计低于平均成绩的人数,所以,在第④空中要将每个同学的成绩和平均分ave 进行比较,成绩低于平均分的,让count 变量累加1。
三、阅读程序,写出运行结果
1.(2017)下列程序的运行结果是____①___。
#include <stdio.h>
void main()
{
char a[]={'a','b','c','d','e','f','g','h','\n'};
int x,y;
x=sizeof(a);
y=strlen(a);
printf("%d,%d",x,y);
}
【答案】运行结果为:9,9
【解析】本题考点是区分sizeof 和strlen()。
将sizeof(a)的值赋给变量x;sizeof(a)是求a 所占内存数,a 数组是char 型,每个元数占1个字节,一共有9 个元素,所以a 数组占9 个内存单元。将strlen(a)的值赋给变量y;strlen(a)是求数组a 的有效字符个数,有效字符指第一个结束标志“\0”之前的字符,此数组中所有字符都是有效字符,共有9 个。
2.(2017)下列程序的运行结果是____②___。
#include <stdio.h>
void fun(int b[3])
{
int j;
for(j=0;j<3;j++)
{
b[j]=j;
}
}
void main()
{
int a[3]={1,2,3},k;
fun(a);
for(k=0;k<3;k++)
{
printf("%d",a[k]);
}
}
【答案】运行结果为:012
【解析】本题考点是参数传递,数组名作为函数参数的情况。
当数组名作函数参数时,不是进行值的传送,所进行的传送只是地址传送,也就是把实参数组的首地址赋予形参数组名。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。即实参数组a 和形参数组b 是同一数组,当形参数组的元素值发生改变时,也就改变实参数组a 中元素值。在fun 函数中,for 循环语句中将形参数组b 元素的值依次改变为b[0]=1,b[1]=1,b[2]=2。再返回main 函数,输出数组a 中元素值也是012(注意输出时的格式)。
3.(2017)下列程序的运行结果是____③___。
#include <stdio.h>
int fun(int a,int b)
{
return(a+b);
}
void main()
{
int x=2,y=3,z=4,r;
r=fun(fun(x,y),z);
printf("%d",r);
}
【答案】运行结果为:9
【解析】本题考点是函数的调用方式:函数实参值是函数调用返回值。此时应注意函数参数的求值顺序,在TC 中,求参数的顺序是从右到左。r=fun(fun(x,y),z);,先代入z 的值,即fun(fun(x,y),4);,再求出参数fun(x,y)的值,是5,即r=fun(5,4);,则fun 函数返回值是9,再赋给变量r。输出r 的值是9。
4.(2017)下列程序的运行结果是____④___。
#include <stdio.h>
void main()
{
char a[ ]="abcdef",b[ ]="acdeea";
char∗p1,∗p2;
int i;
p1=a;
p2=b;
for(i=0;i<6;i++)
{if(∗(p1+i)!=∗(p2+i))printf("%c",∗(p1+i));
}
}
【答案】运行结果为:bcdf
【解析】本题考点是通过指针引用数组元素。指针p1 指向数组a,指针p2 指向数组b。在for循环中,通过指针比较两个数组前6 个元素的值是否相同,当两个数组中对应位置元素值不同时,输出数组a 中数组值。语句if(∗(p1+i)!=∗(p2+i)),当i=0 时,if(∗(p1+0)!=∗(p2+0)),即if('a'!='a')条件不成立,所以不输出;当i=1 时,if(∗(p1+1)!=∗(p2+1)),即元素if('b'!='c')条件成立,所以输出数组a 中的元素值,即输出字符‘b’;当i=2 时,if(∗(p1+2)!=∗(p2+2)),即元素if(' c'!=' d')条件成立,所以输出数组a 中的元素值,即输出字符‘c’;当i=3 时,if(∗(p1+3)!=∗(p2+3)),即元素if('d'!='e')条件成立,所以输出数组a中的元素值,即输出字符‘d’;当i=4 时,if(∗(p1+4)!=∗(p2+4)),即if('e'!='e')条件不成立,所以不输出;当i=5 时,if(∗(p1+5)!=∗(p2+5)),即元素if('f'!='a')条件成立,所以输出数组a 中的元素值,即输出字符‘f’;当i=6 时,for 循环条件不成立,退出循环。故程序输出结果是:bcdf。
5.(2017)下列程序的运行结果是____⑤___。
#include <stdio.h>
void inv(int∗p,int n)
{
int∗i,∗j,m=(n-1)/2,t;
j=p+n-1;
for(i=p;i<p+m;i++,j--)
{
t=∗i;
∗i=∗j;
∗j=t;
}
}
void main()
{
int i;
int a[6]={3,5,7,0,6,2};
inv(a,6);
for(i=0;i<6;i++)
{
printf("%d",a[i]);
}
}
【答案】运行结果为:267053
【解析】本题考点是通过函数调用再利用指针实现数组中的元素值交换。在主函数中调用函数inv(a,6);,将数组a 传给指针变量p,使p 指向数组a 的首地址。在被调函数inv 中,指针变量i 指向数组的首地址,即数组a 第0 号元素的地址;指针变量j 指向数组a 最后一个元素的地址。在for 循环中,第一次循环:指针i 指向第0 号元素,指针j 指向第5 号元素,条件“i<p+2”成立,在循环体实现两个指针所指元素值进行交换,使数组a 的元素依次是2,5,7,0,6,3;第二次循环:执行i++,j--后,指针i 指向第1 号元素,指针j 指向第4 号元素,条件“i<p+2”成立,在循环体实现两个指针所指元素值进行交换,使数组a 的元素依次是2,6,7,0,5,3;第三次循环:执行i++,j--后,指针i 指向第2 号元素,指针j 指向第3 号元素,条件“i<p+2”已经不成立,所以退出循环。返回主函数,依次输出数组a 中的各元素的值是267053。
6.(2018)下列程序的运行结果是____①___。
#include <stdio.h>
int main()
{
int a=14,b=35,c;
if(a<b)
c=a,a=b,b=c;
c=a%b;
while(c!=0)
a=b,b=c,c=a%b;
printf("gcd=%d\n",b);
return 0;
}
【答案】运行结果为:gcd=7
【解析】本题实质是求a 和b 的最大公约数。if(a<b)条件成立,采用中间变量,一条逗号语句使得变量a 和b 的值交换,a=35,b=14;然后执行c=a%b;,使得c=7;接执行while 语句,c!=0 条件成立,执行逗号语句a=b,b=c,c=a%b;,使得a=14,b=7,c=0;条件c!=0 条件不成立,则退出循环。执行printf("gcd=%d\n",b);,输出gcd=7。
7.(2018)下列方程的运行结果是____②___。
#include <stdio.h>
int main()
{
int a[20],i,m=10,k=8;
for(i=0;m>0;i++)
{
a[i]=m%k;
m/=k;
}
for(i--;i>=0;i--)
printf("%d",a[i]);
return 0;
}
【答案】运行结果为:12
【解析】本题将m 转换成k 进制,再输出。进入for 循环:i=0;,条件m>0 成立,执行循环体a[i]=m%k;m/=k;,使得a[0]=2,m=1,然后执行i++;,使得i=1。判断条件m>0 成立,执行循环体,使得a[1]=1,m=0。然后执行i++;,使得i=2。再判断条件m>0 不成立,退出循环。接着执行下一个for 循环输出数组。注意,此时i 的值是2,进入for 循环执行表达式1 时,i--;,使得i 的值为1,条件i>=0 成立,执行循环体输出a[1]是1,然后执行i--;,使得i=0,条件i>=0 成立,执行循环体输出a[0]是0,接着又执行i--;,使得i=-1;,判断条件i>=0 不成立,退出循环。所以整个程序的运行结果是12。
8.(2018)下列程序的运行结果是____③___。
#include <stdio.h>
int main(){
char str[50]="welcome2018"
int i,n=0
for(i=0;str[i]!=' \0';i++)
if('0'<=str[i]&& str[i]<='9')
n=n∗10+str[i]- '0';
printf("result=%d\n",n)
return 0;
}
【答案】运行结果为:result=2018
【解析】本题是将字符数组中的所有数字字符转换成数值,再整体输出数值。进入for 循环:第一次循环,i=0;,判断条件s[i]!='\0'条件成立,再判断if 语句if('0' <=str[i]&&str[i]<='9')条件不成立;进入第二次循环,执行i++,使得i=1,判断条件s[i]!='\0'成立,再判断if语句if('0'<=str[i]&&str[i]<='9')不成立;进入第三次循环,执行i++,使得i=2,依次下去,直到i=7,判断条件s[i]!='\0'成立,再判断if 语句if('0'<=str[i]&&str[i]<='9')成立,执行语句n=n∗10+str[i]='0';,使得n=2;进入下一次循环,执行i++;,使得i=8;判断条件s[i]!='\0'成立,再判断if 语句if('0'<=str[i]&&str[i]<='9')成立,执行语句n=n∗10+str[i]='0';,使得n=20;进入下一次循环,执行i++,使得i=9;判断条件s[i]!='\0'成立,再判断if 语句if('0' <=str[i]&&str[i]<='9')成立,执行语句n=n∗10+str[i]='0';,使得n=201;进入下一次循环,执行i++,使得i=10;判断条件s[i]!='\0'成立,再判断if 语句if('0'<=str[i]&&str[i]<='9')成立,执行语句n=n∗10+str[i]='0';,使得n=2018;进入下一次循环,执行i++,使得i=10;判断条件s[i]!='\0' 不成立,退出循环。接着执行输出语句printf("result=%d \n",n),输出结果是result=2018。
9.(2018)下列程序的运行结果是____④___。
#include <stdio.h>
int f(int n)
{
if(n==1‖n==0)
return 1;
return(n∗f(n-1));
}
int main()
{
printf("%d",f(5));
return 0;
}
【答案】运行结果为:120
【解析】本题考点是递归调用,利用递归求得5!。在main()函数中输出f(5)。调用f 函数,把实参5 传给形参n,n 的值为5。5!=1 或0,执行return(n∗f(4));。在返回之前,先调用f(4),进入f(4),4!=1 或0,执行return(n∗f(3));。在返回之前,先调用f(3),进入f(3),3!=1 或0,执行return(n∗f(2));。在返回之前,先调用f(2),进入f(2),2!=1 或0,执行return(n∗f(1));。在返回之前,先调用f(1),进入f(1),这次n==1,因此本次函数结束,返回1;回到f(2),计算2∗f(1)并返回2;回到f(3),计算3∗f(2)并返回6;回到f(4),计算4∗f(3)并返回24;回到f(5),计算5∗f(4)并返回120;程序回到main()函数,执行printf 打印输出120。
10.(2018)下列程序的运行结果是____⑤___。
#include <stdio.h>
void fun(int∗w,int m,int n){
int i,j,t
for(i=m;i<n;i++){
t=w[n-1];
for(j=n-2;j>=0;j--)
w[j+1]=w[j];
w[0]=t
}
}
int main(){
int,i,a[9]={1,2,3,4,5,6,7,8,9};
fun(a,4,9)
for(i=0;i<9;i++)
printf("%4d",a[i]);
return 0;
}
【答案】运行结果为:5 6 7 8 9 1 2 3 4
【解析】本题的fun 函数是将数组a 后移5 个元素置前面位置,再在main 函数中输出数组a。在main()函数中调用fun 函数,进入fun 函数:形参指针w 指向数组a,m 的值是4,n 的值是9。进入外层for 循环:第一次循环,i=4;i<9 条件成立;进入循环体t=w[8]=9;,再进入内层循环,从j=7 开始,每次减1 到j=0;每次循环执行w[j+1]=w[j];,使得每个数组元素住后移一位:1,1,2,3,4,5,6,7,8。退出内层循环,把t 的值赋给w[0]。9,1,2,3,4,5,6,7,8;i 的值加1。进入第二次循环:i=5;i<9 条件成立;进入循环体t=w[8]=8;,再进入内层循环,从j=7 开始,每次减1 到j=0;每次循环执行w[j+1]=w[j];,使得每个数组元素往后移一位:9,9,1,2,3,4,5,6,7;退出内层循环,把t 的值赋给w[0]。结果为8,9,1,2,3,4,5,6,7;i 的值加1。进入第三次循环:i=6;i<9 条件成立;进入循环体t=w[8]=7;,再进入内层循环,从j=7 开始,每次减1 到j=0;每次循环执行w[j+1]=w[j];,使得每个数组元素往后移一位:8,8,9,1,2,3,4,5,6;退出内层循环,把t 的值赋给w[0]。结果为7,8,9,1,2,3,4,5,6;i 的值加1。进入第四次循环:i=7;i<9 条件成立;进入循环体t=w[8]=6;,再进入内层循环,从j=7 开始,每次减1 到j=0;每次循环执行w[j+1]=w[j];,使得每个数组元素往后移一位:7,7,8,9,1,2,3,4,5;退出内层循环,把t 的值赋给w[0]。结果为6,7,8,9,1,2,3,4,5;i 的值加1。进入第五次循环:i=8;i<9 条件成立;进入循环体t=w[8]=5;,再进入内层循环,从j=7 开始,每次减1 到j=0;每次循环执行w[j+1]=w[j];,使得每个数组元素往后移一位:6,6,7,8,9,1,2,3,4;退出内层循环,把t 的值赋给w[0]。结果为5,6,7,8,9,1,2,3,4;i 的值加1。进入第六次循环:i=9;i<9 条件不成立;退出循环。返回main()函数输出数组a:5 6 7 8 9 1 2 3 4。
11.(2019)下列程序的运行结果是________。
#include <stdio.h>
main(){
int i=0;
do printf("%d,",i);
while(i++);
printf("%d\n",i);
}
【答案】运行结果为:0,1
【解析】本题考点是i++后置自增。do-while 循环先无条件执行一次循环体,输出0。再判断条件(i++),i 的初值是0,++在后,所以是先用后加;先用i 的值是0。条件为假,退出循环。退出循环后,再输出i 的值是1。
12.(2019)下列程序的运行结果是________。
#include <stdio.h>
int fun(char∗s) {
char ∗t=s;
while(∗t++);
return t-s;
}
main(){
chart[8]="123456";
printf("%d\n",fun(t));
}
【答案】运行结果为:7
【解析】本题需要认真看清程序。在fun 函数中,while 语句后跟了分号,表示while 语句的循环体为空。在fun 函数中定义指针变量t 指向数组t 的首地址,执行while 语句,使得指针t 一直往数组后移,当t 指向字符‘6’时,判断(∗t++),++在后,先判断“∗t”的值为真,再使t 指向下一个字符‘\0’,再判断(∗t++),++在后,先判断“∗t”的值为假,同时,再使t 指向下一个结束标志字符‘\0’,退出循环,返回t-s 值为7。在main 函数中输出fun 函数的值为7。
13.(2019)下列程序的运行结果是________。
#include <stdio.h>
int fun(char s[]){
int n=0;
while(∗s<='9'&&∗s>='0')
{n=10∗n+∗s-'0';
s++;}
return n;
}
main(){
printf("%d\n",fun("056a0"));
}
【答案】运行结果为:56
【解析】本题是将数字字符转换为数值,一旦出现不是数字字符,即退出转换,再输出数值。字符串056a0 的首地址由形参指针变量s 指向。在while 语句中,从字符串056a0 第一个字符开始判断是否是数字字符。第一次循环:字符‘0’是数字字符,执行n=10∗n+∗s-'0';,使得n=0,s++指向下一个字符‘5’地址。进入第二次循环:字符‘5’是数字字符,执行n=10∗n+∗s-'0';,使得n=5,s++指向下一个字符‘6’地址。进入第三次循环;字符‘6’是数字字符,执行n=10∗n+∗s-'0';,使得n=56,s++指向下一个字符‘a’地址。进入第四次循环:字符‘a’不是数字字符,退出循环。返回n 的值56。在main 函数中输出fun 函数的值56。
14.(2019)下列程序的运行结果是________。
#include <stdio.h>
int f(int n){
if(n<=2)
return 1;
else
return f(n-1)+f(n-2);
}
main(){
int n=5;
printf("f(n)=%d\n",f(3));
}
【答案】运行结果为:f(n)=2
【解析】本题是利用递归调用计算Fibonacci 数列。在main 函数中调用f(3),进入函数f(3),3<=2,不成立,因此准备执行return f(n-1)+f(n-2);,在返回之前,先计算f(2)和f(1)的值。进入f(2),2<=2,成立,因此调用结束,返回1;再进入f(1),1<=2,成立,因此调用结束,返回1;回到f(3),计算1+1,f(3)函数调用结束,返回2。因此,在main 函数中输出f(n)=2。
15.(2019)下列程序的运行结果是________。
#include <stdio.h>
int f(char ∗s,char ∗t){
int n=0,num=0;char ∗p,∗r;
while(∗s)
{ p=s;r=t;
while(∗r)
if(∗r==∗p)
{r++;p++;}
else
break;
if(∗r==' \0')
num+=1;
n++;s++;
}
return num;
}
main()
{printf("the result is %d\n",f("aabdabc","ab"));
}
【答案】运行结果为:the result is 2
【解析】本题考查在母串中子串出现的次数。母串“aabdabc”由形参s 指针变量指向,子串“ab”由形参s 指针变量指向。
进行while 循环:第一次循环,判断∗s 值字符‘a’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为真,执行r++;p++;,判断∗r 值字符‘b’为真,再判断∗r==∗p,条件为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0'),条件为假,则说明在母串中还没有出现子串,接着s++使s 指向母串中的第二个字符‘a’。
进入第二次循环,判断∗s 值字符‘a’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为真,执行r++;p++;,判断循环条件∗r 值字符‘b’为真,再判断∗r==∗p,条件为真,判断循环条件∗r 值字符‘\0’为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0'),条件为真,则说明在母串中出现子串一次,执行num 加1,使得num=1,接着s++使s 指向母串中的下一个字符‘b’。
进入第三次循环,判断∗s 值字符‘b’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0'),条件为假,则说明在母串中还没有出现子串,接着s++使s 指向母串中的下一个字符‘d’。
进入第四次循环,判断∗s 值字符‘d’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0'),条件为假,则说明在母串中还没有出现子串,接着s++使s 指向母串中的下一个字符‘a’。
进入第五次循环,判断∗s 值字符‘a’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为真,执行r++;p++;,判断循环条件∗r 值字符‘b’为真,再判断∗r==∗p,条件为真,判断循环条件∗r 值字符‘\0’为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0' ),条件为真,则说明在母串中出现子串一次,执行num 加1,使得num=2,接着s++使s 指向母串中的下一个字符‘b’。
进入第六次循环,判断∗s 值字符‘b’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0'),条件为假,则说明在母串中还没有出现子串,接着s++使s 指向母串中的下一个字符‘c’。
进入第七次循环,判断∗s 值字符‘c’为真,再进入内层循环,判断∗r 值字符‘a’为真,进入循环体,判断∗r==∗p,条件为假,退出循环,再判断子串是否遇到结束标志if(∗r=='\0'),条件为假,则说明在母串中还没有出现子串,接着s++使s 指向母串中的下一个字符‘\0’。
判断循环条件∗s 值为假,退出循环,函数f 返回num 的值为2。在main 函数中输出f 函数的值,输出结果:the result is 2。
四、程序填空
按照题目要求填写正确内容,使程序完整。
1.(2017)函数countBitl 用于统计某个字节中值为1 的位的个数。
unsigned int countBitl(char byteData)
{
int i;
unsigned int num=0,tmpVal;
for(i=0;i<8;i++)
{
tmpVal=____①___;
tmpVal&=0x01;
if(tmpVal)
____②___;
}
return num;
}
【答案】①byteData>>i ②num++或num+=1
【解析】第①空:由于tmpVal&=0x01;(作用是取tmpVal 最低位的数值),所以,在它前面需要给变量tmpVal 赋待统计的数值byteData,第i 次要取最低位时,待统计数值byteData 就要右移i 位,所以是byteData>>i。
第②空:判断tmpVal 的值是否是真,如果是真,说明最低值为1,需要累加到变量num 中。所以填写num++或num+=1。
2.(2017)以下程序在main 函数中调用reverse 函数,按逆序重新放置数组a 中元素的值,reverse 函数使用递归实现数组逆序。此程序运行后输出:54321。
#define N 5
reverse(int∗s,int i,int j)
{(www.xing528.com)
int t;
if(i<j)
{
t=∗(s+i);
____①___;
∗(s+j)=t;
reverse(____②___);
}
}
void main()
{
int a[N]={1,2,3,4,5};
int i=0;
reverse(____③___);
for(i=0;i<N;i++)
printf("%d",a[i]);
}
【答案】①∗(s+i)=∗(s+j) ②s,i+1,j-1 ③a,0,4
【解析】第①空:形参变量i 是数组第0 号元素下标,形参变量j 是数组最后一个元素下标。在if 语句中,i<j,就交换第0 号元素的最后一个元素的值,交换采用了中间变量t。所以填写:∗(s+i)=∗(s+j)。
第②空:发生递归调用,而在下一次调用是要将第1 号元素和倒数第2 号元素值进行交换,所以要改变变量i 和变量j 的下标值,要使i 的值加1,j 的值减1,如此递归调用下去,直到i>=j。所以填写:s,i+1,j-1。
第③空:在main 函数中调用reverse 函数,要与reverse 函数的形参对应,所以填写:a,0,4。
3.(2018)下列程序的功能是把文件A 的内容追加到文件B 中。例如文件A 为“I'm ten”,文件B 为“I'm a student”,追加之后,文件B 的内容为“I'm a student! I'm ten”。
#include <stdio.h>
int main(){
____①___;
char ch;
if((fp1=fopen("A.txt","r"))!=NULL){
if((fp2=fopen(" B.txt","a"))!=NULL){
while((ch=fgetc(fp1))!=EOF)
____②___;
fclose(fp2);
}
else{
printf("file B cannot be opened\n");
___③____
exit(0)
}}
else{
printf("file A cannot be opened\n")
exit(0);
}
return 0;
}
【答案】①FILE ∗fp1,∗fp2 ②fputc(ch,fp2) ③fclose(fp1)
【解析】第①空:需要定义文件指针,在源程序中用到了两个文件指针fp1 和fp2,所以填写:FILE ∗fp1,∗fp2。
第②空:在循环条件表达式中,是从A.txt 文件中依次读取单个字符给变量ch,直到遇到文件结束标志,那么在第②空中就要将读取出来的字符写到文件 B.txt 中去,所以填写:fputc(ch,fp2)。
第③空:如果文件 B.txt 没有打开成功,就要把A.txt 文件关闭,所以填写:fclose(fp1)。
4.(2018)下列程序中,函数f 的功能是用选择排序法对一个数组中的数据按升序进行排序。void f(int a[],int N) { /∗a 为待排序数组N 中数据元素个数∗/
int i,j,p,t;
for(i=0;i<N-1;i++){
p=i;
for(____①___;j<N;j++)if(a[p]>a[j])
____②___;
if(p!=i){
t=a[i];a[i]=a[p];a[p]=t
}
}
}
【答案】①j=i+1 ②p=j
【解析】第①空:因为是用选择排序法排序,而选择排序法的中心思想是:将第一位置的数和后面的数进行比较,并记录最小值的下标,和第一位置的数进行交换,所以第①空填写:j=i+1。
第②空:是记录最小值的下标,存放在变量p 中,所以填写:p=j。
5.(2019)下列程序的功能是求整数n(1~10)的阶乘的位数,例如5!=120,输出结果是3。
#include <stdio.h>
____①___
int fun(int n)
{ int i,d=0;
____②___;
for(i=1;i<=n;i++)
s+=log10____③___;
____④___;
return d;
}
main()
{ int n=5;
printf("s=%d",____⑤___));
}
【答案】①include"math.h" ②double s=1.0 ③(i∗1.0) ④d=(int)s ⑤fun(n)
【解析】第①空:由于源程序中用到了数学函数log10,所以应填写:include"math.h"。
第②空:在源程序中用到变量s,s 所累加的值是实型(log10 函数所返回的值是double 型),所以要先定义变量s 为double 型。
第③空:因为要求整数n 阶乘的位数,所以应填写(i∗1.0)。
第④空:将s 的值取整,赋给变量d,就是阶乘的位数。
第⑤空:在main 函数中调用fun 函数,并把n 的值传给形参。
五、阅读程序,修改程序中的错误,不得增行或删行,也不得更改程序结构。
1.(2017)以下程序从键盘获取字符串输入,并将输入字符串追加写入C 盘data.txt 文件中。以下程序只允许修改两行。
L1 void main()
L2 {
L3 FILE ∗fp;
L4 char buf[100],∗fileName="c:/ /data.txt";
L5 gets(buf);
L6 if((fp=fopen(fileName,"w"))!=NULL)
L7 {
L8 puts(buf);
L9 fclose(fp);
L10 }
L11 }
【答案】①L6 if((fp=fopen(filename,"a"))!=NULL) ②L8 fputs(buf,fp);
【解析】L6:题目要求是以追加的方式写入文件中,打开文件的方式应该是“a”。程序代码应该改成:if((fp=fopen(filename,"a"))!=NULL)。
L8:题目要求是将字符串写到文件data.txt 中,应改成fputs(buf,fp);。
2.(2017)函数endsWith(char∗str,char∗substr)用于判断字符串str 是否以子字符串substr结尾,是,返回整数1,否则,返回整数0。以下程序只允许修改三行。
L1 int endsWith(char ∗str,char ∗substr)
L2 {
L3 int sublen=0;
L4 while(str!='\0')
L5 {
L6 if(substr[sublen]!='\0')
L7 {
L8 sublen++;
L9 }
L10 str++;
L11 }
L12 int i=0;
L13 for( ;i<sublen;i++)
L14 {
L15 char strCh=∗str;
L16 char subCh=∗--substr;
L17 if(strCh!=subCh)
L18 {
L19 return 0;
L20 }
L21 }
L22 return 1;
L23 }
【答案】①L4 while(∗str!='\0') ②L15 char strCh=∗--str;
③L16 char subCh=∗(substr+sublen-1-i);
【解析】L4:这个while 循环的作用是将str 指针指向字符串末尾‘\0’,并统计了子字符串substr 的长度。while 条件表达式是要判断str 所指字符值是否是结束标志‘\0’。所以应改成while(∗str!='\0')。
L15:经过上一次循环后,str 指针变量已经指向了字符串的结束标志‘\0’,所以给变量strCh赋值应是char strCh=∗--str;,这才是指向母串中最后一个字符。
L16:要指向子串中最后一个字符,应改成:char subCh=∗(substr+sublen-1-i);。
3.(2018)下列程序中,函数fun 的功能是:根据形参m,计算如下公式的值。
。以下程序只允许修改三行。
L1 #include <stdio.h>
L2 void fun(int m)
L3 {
L4 double y=1.0;
L5 int i;
L6 for(i=2;i<m;i++)
L7 y+=1/(i+i);
L8 return(y);
L9 }
L10 int main()
L11 {
L12 int n=5
L13 printf("\nThe result is %1f\n",fun(n));
L14 return 0;
【答案】①L2 double fun(int m) ②L6 for(i=2;i<=m;i++) ③L7 y+=1.0/(i∗i);
【解析】L2:fun 函数是需要返回double 型数据y,所以要把fun 函数改成double 类型,应改成:L2 double fun(int m)。
L6:题目的意思是要计算到,所以i 的变化应是到i=m 为止,应改成:L6 for(i=2;i<=m;i++)。
L7:题目涉及分数,在TC 中表示分数时,用除法,必须保证有一边运算符是实型,所以应改成:y+=1.0/(i∗i);
4.(2018)下列程序的功能是用折半查找法来查找一个输入的数是否在一个已经排好序的数组中,如果存在,就返回所在位置的下标,如果不存在,就返回“Not be found”。
以下程序只允许修改两行。
L1 #include <stdio.h>
L2 #define N 5
L3 int fun(int a[],int m)
L4 {
L5 int low=0,high=N-1,mid;
L6 while(low<=hight){
L7 mid=high-low;
L8 if(m<a[mid])
L9 high=mid-1;
L10 else if(m>a[mid])
L11 low=mid+1;
L12 else
L13 mid=m;
L14 }
L15 return(-1);
L16 }
L17 int main()
L18 {
L19 int i,a[N]={7,9,13,24,67},k,m;
L20 scanf("%d",&m);
L21 k=fun(a,m);
L22 if(k>=0)
L23 printf("m=%d,index=%d\n",m,k);
L24 else
L25 printf("Not be found! \n");
L26 return 0;
L27 }
【答案】①L7 mid=(high+low)/2 ②L13 return mid;
【解析】L7:题中采用折半查找,需要用到中间下标值,而中间下标值的求傎是:mid=(high+low)/2。
L13:根据题意,如果找到,应该返回数在数组中的下标值,应改成return mid。
5.(2019)下面程序的功能是用插入排序方法对数组中的元素从小到大进行排序。以下程序只允许修改两行。
L1 #include <stdio.h>
L2 void f(int a[],int N)
L3 {
L4 int i,j,t;
L5 for(i=1;i<N;i++)
L6 {
L7 t=a[i];
L8 for(j=i-1;j>=0;j--)
L9 a[j+1]=a[i];
L10 a[j+1]=t;
L11 }
L12 }
L13 main()
L14 {
L15 int i;
L16 int a[5]={12,45,3,-98,32};
L17 f(a,5);
L18 for(i=0;i<5;i++)
L19 printf("%4d",a[i]);
L20 }
【答案】①L8 for(j=i-1;j>=0&&t<x[j];j--) ②L9 x[j+1]=x[j];
【解析】L8:程序第8 行是在查找数值t 的待插入位置,若元素序列数比这个数大,则把元素向右移一位,直到元素序列数小于或等于这个数或已到最左边元素,应改成for(j=i-1;j>=0&&t<x[j];j--)。
L9:元素右移一个位置,应是x[j+1]=x[j];。
6.(2019)下面程序的功能是:从键盘输入一个整数n(数组下标范围内的),把没有重复元素值的数组aa 中比aa[n]小的元素放在aa[n]的左边,比aa[n]大的元素放在aa[n]的右边,数组元素仍然保存在原数组中,例如,如果aa={33,67,42,58,25,76,85,16,41,56},输入3,则输出结果是“33,42,25,16,41,56,58,67,76,85”。以下程序只允许修改三行。
L1 #include <stdio.h>
L2 #include<N 10>
L3 void fun(int aa[],int n)
L4 {
L5 int I,j=0,k=0,t;
L6 int bb[N];
L7 t=aa[j];
L8 for(I=0;I<N;I++)
L9 {
L10 if(aa[I]>t)
L11 bb[j++]=aa[I];
L12 if(aa[I]<t)
L13 aa[k++]=aa[I];
L14 }
L15 a[k]=t;
L16 for(I=0;I<j;I++,k++)
L17 aa[k]=bb[I];
L18 }
L19 main()
L20 {
L21 int i,n;
L22 int aa[N]={33,67,42,58,25,76,85,16,41,56};
L23 fun(aa,3);
L24 printf("\n∗∗∗new list∗∗∗\n");
L25 for(i=0;i<N;i++)
L26 printf("%4d",aa[i]);
L27 }
【答案】①L2 #define N 10 ②L7 t=aa[n]; ③L15 a[k++]=t;
【解析】L2:符号常量的定义应用#define N 10。
L7:变量t 用于保存第n 号元素值,根据题意,是以第n 号元素值作为分界线。
L15:要让k 的值加1,以便第17 行aa[k]在下一次保存数组bb 元素中的值时是从下一位置开始的,应填写:a[k++]=t;。
六、程序设计题
1.(2017)编写程序用于从键盘逐个读取整数,并将整数按照升序插入链表,每插入一个数后,将链表中的数据都输出一次,当输入整数0 时,结束插入。
#include <stdio.h>
#include <stdlib.h>
struct NumNode
{
int data;
struct NumNode∗next;
};
struct NumNode ∗insertToList(struct NumNode ∗head,int fdata)
{
struct NumNode ∗p,∗q;
struct NumNode ∗newNode=(structNumNode∗)malloc(sizeof(struct NumNode));
newNode->data=fdata;
newNode->next=NULL;
p=head;
q=head;
if(head==NULL)
{
___①____
return head;
}
while(p!=NULL&&fdata>p->data)
{
q=p;
p=p->next;
}
if(p!=NULL)
{
if(head==p)
{
___②____
}
else
q->next=newNode;
___③____
}
else
{
}
___④____
return head;
}
void printList(struct NumNode∗head)
{
Struct NumNode ∗p=head;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
}
printf("\");
}
void main()
{
struct NumNode ∗head=NULL;
int i;
scanf("%d",&i);
while(i!=0)
{
___⑤____
}
}
printList(head);
scanf("%d",&i);
【答案】①head=newNode;②head=newNode;③newNode->next=p;④q->next=newNode;或p=newNode;⑤head=insertToList(head,i);
【解析】第①空:当head 为空链表时(第一次创建链表时,即读入第一个数据插入链表时),直接让head 指向新建结点newNode,应填写:head=newNode;。
第②空:考虑待插结点不是链尾(p!=NULL),而是链头(head==p)时的情况,应让head 头结点指向新结点:head=newNode;。
第③空:当待插结点不是链尾(p!=NULL),又已经让待插结点位置的前一个结点的next 指针指向新结点,还要让新结点的next 指针指向下一个结点时,应填写:newNode->next=p;。
第④空:当待插结点是链表末尾时,需将最后一个结点(最后一个结点由p 或q->next 指向)的next 指针指向新结点,应填写:q->next=newNode;或p=newNode;。
第⑤空:调用insertToList 函数创建链表,根据insertToList 函数的形参表填写insertToList 的实参表,应填写:head=insertToList(head,i);。
2.(2018)下列程序的主函数中,通过函数调用把N 名学生的成绩放入一个带头节点的链表中,h 指向链表的头节点。函数fun 的功能是:找出N 名学生中的最高分并返回,请补充程序。
#include <stdio.h>
#define N 8
struct slist! {
int s;
____①___
};
typedef struct slist STREC;
int fun(STREC ∗h){
int max=h->s;
while(____②___){
if(max<h->s) max=h->s;
____③___;
}
printf("%d",max);
return max;
}
STREC∗creat(int∗s){
STREC∗h,∗p,∗q; /∗h 表示链表的头部∗/
int i=0;
h=p=(STREC∗)malloc(sizeof(STREC));
p->s=0;
while(i<N){ /∗产生N 个节点的链表,各分数存入链表中∗}
q=(STREC∗)malloc(sizeof(STREC));
p->s=s[i++];
p->next=q;
____④___;
}
p->next=NULL;
return h;
}
int main(){
int s[N]={85,76,69,85,91,72,64,87},max;
STREC∗head;
____⑤___;
max=fun(head);
printf("max=%d\n",max);
return 0;
}
【答案】①struct slist ∗next ②h!=NULL ③h=h->next ④p=q ⑤head=creat(a)
【解析】第①空:创建链表的指针域,指针变量名必须是next(因为在源程序中用到了结点的指针域next),应填写:struct slist ∗next。
第②空:在链表中查找最高分,要从链表头开始,直到链表尾结束。在while 循环语句中查找最高分,循环条件就是当前结点不是链尾,应填写:h!=NULL。
第③空:每判断比较一个结点是否是最高分,都要往后移一个点(逐个比较每个结点),应填写:h=h->next。
第④空:创建新结点,需要将新结点的首地址保存在上一个结点的成员变量中,并且要随新结点的移动而移动,以便连接下一个新结点。应填写:p=q。
第⑤空:调用创建函数链表数creat,并把链表的头指针返回给主函数head。应填写:head=creat(a)。
3.(2019)程序功能是:输入一个整数n,建立链表,把0~n-1 中的整数作为链表结点键值,并把链表内容保存到文件Output.dat 中。如果n=5,则文件中存储的内容为“0→1→2→3→4”。
#include <stdio.h>
typedef struct ss{
int data;
____①___;
}NODE;
void fun(int n,char ∗filename){
NODE ∗h,∗p,∗s;
____②___;
int I;
h=p=(NODE ∗)malloc(sizeof(NODE));
h->data=0;
for(I=1;I<n;I++){
s=(NODE ∗)malloc(sizeof(NODE));
s->data=I;
____③___;
p=p->next;
}
p->next=NULL;
if((pf=fopen(filename,"w"))==NULL){
printf("Can not open Output.dat!");
exit(0);
}
____④___;
while(p){
fprintf(pf,"%3d",p->data);
if(p->next!=NULL)
fprintf(pf,"->");
p=p->next;
}
fprintf(pf,"\n");
fclose(pf);
p=h;
while(p){
s=p;
p=p->next;
____⑤_;/∗释放分配的内存空间∗/
}
}
main(){
char ∗filename="Output.dat";
int n;
printf("\nInput n:");
scanf("%d",&n);
fun(n,filename);
}
【答案】①struct ss∗next ②FILE ∗pf ③p->next=s ④p=h ⑤free(s)
【解析】第①空:定义链表的指针域,指针变量名必须是next(因为在源程序中用到了结点的指针域next),应填写:struct ss ∗next。
第②空:在源程序中用到了文件指针pf,需定义文件指针:FILE ∗pf。
第③空:创建好了新结点,并给新结点的数值域赋了值,需要把新结点的地址给前一个结点的指针域保存,形成链表,应填写:p->next=s。
第④空:使结构体指针变量p 再重新指向链表的头指针,以便在接下来的while 语句中用指针p 把链表的数值写入文件pf 中。应填写:p=h。
第⑤空:依次释放s 指向的内存空间:free(s)。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。