期末复习练习解析02
1、选择题
1.1 一个 C 程序的执行是从: (A)
A、main 函数开始,到 main 函数结束。
B、第一个函数开始,到最后一个函数结束。
C、main 函数开始,到最后一个函数结束。
D、第一个函数开始,到 main 函数结束。
解析: main函数时程序的入口,一个工程只能有一个main函数。正常情况下,程序从main进入,到main函数结束为止。
1.2 x、y 和 z 是 int 型变量,且 x=3, y=4, z=5; 则下面表达式中值为 0 的是:(D)
A、’x’&&’y’
B、x<=y
C、x||y+z&&y–z
D、!((x<y)&&!z||1)
解析: 选项A中,两个字符取逻辑与,为真。选项B中3<=4为真。选项C中,根据优先级x||(y+z&&y–z),逻辑与取到真,x=3为非0值,表达式为真。
1.3 以下语句的执行结果是: (C)
char s[20]="2022杭州欢迎你!";
printf("%d",strlen(s));
A、20 B、14 C、15 D、10
解析: 汉字占2个字节,数字占一个字符,感叹号占一个字符。
1.4 用宏名定义一个字符串,下列表述中哪一个是正确的: (C)
A、#define pi=3.14159 B、define pi=3.14159
C、#define pi "3.14159" D、#define pi(3.14159)
解析:宏定义,define定义常量
1.5 能正确表示 a 和 b 同时为正或同时为负的逻辑表达式是: (D)
A、(a>=0‖b>=0)&&(a<0‖b<0)
B、(a>=0&&b>=0)&&(a<0&&b<0)
C、(a+b>0)&&(a+b<=0)
D、a*b>0
解析: B改成(a>=0&&b>=0)||(a<0&&b<0)才正确
1.6 数组定义为 int a[4][5],下列引用中错误的是: (B)
A、*a B、++a C、&a[2][3] D、 *(*(a+2)+3)
解析:数组名为constant pointer,不能被修改
1.7 若 ch 是大写字母则转换为对应的小写字母,下列语句中正确的是: (B)
A、if(ch>='A'&ch<='Z') ch=ch-32
B、if(ch>='A'&&ch<='Z')ch=ch+32
C、ch=(ch>='A'&&ch<='Z')?ch+32:''
D、ch=(ch>'A'&&ch<'Z')?ch+32:ch
解析:常用字母的ASCII值:A-->65, Z-->90, a-->97, z-->122, 0-->48, 9-->57。小写字母在大写字母的后面。
1.8 能够将变量 a、b 中最大值赋值到变量 c 的是: (B)
A、if(a>b)c=a;c=b B、c=a; if(b>a)c=b
C、a>b? a:b D、a>=b? a:b
解析:选项B中,a首先赋值给c,如果b>a,则把b赋值给 c,这样c取到了a,b中国的大值。
1.9 若有解析语句: int a[ ][3]={1,2,3,4,5,6,7,8,9,10}; ,则 a 数组的行数为:(A)
A、4 B、3 C、不确定 D、5
解析:二维数组中,列下标界不能省,因为二维数组按行保存。在题目中,列下标界为3,取三个为一行,最后不足三个的用0补。
1.10 下列语句定义 p 为指向 float 类型变量 d 的指针,其中正确的是: (D)
A、float d,*p=d;
B、float d,p=d;
C、float *p=&d,d;
D、float d,*p=&d;
解析:d需要先声明,才能执行取地址操作,并赋值给指针p。
- 程序阅读题
2.1 switch/case,do-while
#include <stdio.h>
int main(){
int k=0,n=0;
char c='A';
do{
switch (c++){
case 'A':
k++;
break;
case 'B':
k--;
case 'C':
k+=2;
break;
case 'D':
k=k%2;
break;
case 'E':
k=k*10;
break;
default:
k=k/3;
}
n++;
}
while(c<'G');
printf("n=%d\n", n);
printf("c=%c\n", c);
return 0;
}
解析:执行次序如下:
--> 进入case A,k= 1,n = 1;c需要后置自增,变为B,满足c<G
--> 进入case B, 因为case B中没有break,连续执行case B和case C,k=2,n = 2;此时c为C,满足c<G
--> 进入case C,k= 4,n = 3;此时c为D,满足c<G
--> 进入case D,k= 0,n = 4;此时c为E,满足c<G
--> 进入case E,k= 0*10=0,n = 5;此时c为F,满足c<G
--> 进入default,k= 0/3=0,n = 6;此时c为G,不满足c<G退出while循环,输出结果。
通过本题,熟练switch/case的使用。
输出:
n=5
C=G
可以练习下面的程序的运行结果:
#include <stdio.h>
void main( )
{ int k=0;
char c='A';
do {
switch (c++) {
case 'A': k++; break;
case 'B': k--;
case 'C': k+=2; break;
case 'D': k=k%2; break;
case 'E': k=k*10; break;
default: k=k/3;
}
k++;
} while(c<'G');
printf("k=%d\n", k);
}
输出:k=8
初始值k=0, c = A
--> 进入case A,k= 1;退出switch执行k++后,此时c为B,k=2,满足c<G
--> 进入case B, 因为case B中没有break,连续执行case B和case C,k=3;退出switch执行k++后,此时c为C,k=4,满足c<G
--> 进入case C,k= 6;退出switch执行k++后,此时c为D,k=7,满足c<G
--> 进入case D,k= 1;退出switch执行k++后,此时c为E,k=2,满足c<G
--> 进入case E,k= 2*10=20;退出switch执行k++后,此时c为F,k=21,满足c<G
--> 进入default,k= 21/3=7;退出switch执行k++后,此时c为G,k=8,不满足c<G退出while循环,输出结果,k=8。
2.2 字符串处理
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void f(char *s){
int i=0;
while(s[i]!='\0')
if (s[i]==s[i+1]&&(!isalpha(s[i])))
{
strcpy(s+i,s+i+1);
puts(s);
}
else
i++;
}
int main(){
char x[20]="a*bb*ccc***def";
f(x);
return 0;
}
输出:a*bb*ccc*def
解析:本题的功能是,如果字符串中非字母字符重复多次,只保留一个。
isalpha()判断是否为字母。strcpy()字符串复制
通过本题,熟悉字符串的操作
2.3 二维数组的处理
#include <stdio.h>
int main(){
int a[4][4]= {{2,5,7,9},{4,3,1,2},{6,9,8,7},{0,5,4,2}},i,j,ii;
for(j=0; j<4; j++){
ii=0;
for(i=1; i<4; i++) if(a[i][j]>a[ii][j]) ii=i;
printf("(%d,%d)\n",ii,j);
}
return 0;
}
解析:ii用来记录当前列中的最大值得行坐标。代码功能:输出每一列中的最大值的下标。通过本题,熟悉二维数组的元素操作。
输出:
(2,0)
(2,1)
(2,2)
(0,3)
2.4 static变量、全局变量、局部变量
#include <stdio.h>
int k=1;
void f(int c){
static int a=0;
a+=2;
c-=2;
k*=2;
printf("a=%d,",a);
}
int main(){
int i,n,b=5;
for (i=0; i<2; i++) {
f(b);
printf("b=%d,k=%d\n",b,k);
}
return 0;
}
解析:k为全局变量,a为静态变量,b为局部变量。k与a在两次函数调用过程中,值保留下来了,b值保持不变。通过本题,熟悉static变量与全局变量的使用,此知识点要考。
输出:
a=2,b=5,k=2
a=4,b=5,k=4
2.5 结构
#include <stdio.h>
int main(){
struct student {
char name[10];
int k1;
int k2;
} a[3]= {{"he",90,80,},{"wang",95,80},{"wu",90,98}},*p=a;
printf("name:%s scr:%d\n",p->name,p->k1+p->k2);
printf("total:%d\n", a[0].k2+a[1].k2+a[2].k2);
return 0;
}
解析:指针p指向数组的第一个元素,因此,第一个printf输出的是第一位学生的姓名和成绩总和;第二个printf输出所有学生第二门成绩总和。
输出:
name:he scr:170
total:258
3、程序填空
3.1 输出一个[3,1000]范围内的整数,判断其是否是素数。
#include <stdio.h>
#include <math.h>
int main(){
int n,i;
while(scanf("%d",&n), n<3 || n>1001 );
for(i=2; i<=sqrt(n); i++)
if( n%i==0 )
break;
if( i>sqrt(n) )
printf("%d 是素数\n",n);
else
printf("%d 不是素数\n",n);
return 0;
}
解析:熟悉素数的判断方法、break的使用、sqrt的使用
本代码功能是判断一个数是不是素数。
第一个空在main函数前面,这个位置可能是定义一个全局变量,也可能是包含头文件。分析代码,后面用到了sqrt函数,因此需要包含math.h头文件。
第二个空在循环读数中,在while中包含一个逗号表达式,第一个表达式为读数,第二个表达式为判断是否满足范围条件。题目要求输入的数为[3,1000]范围,因此需要对输入的n进行判断是否属于该范围,如果不在这个范围,继续读数,直到满足范围要求为止。因此填入n<3 || n>1001
第三空if的逻辑体为break,因此属于找到了n的某个因子的情况,即n%i==0
第四空if逻辑题为输出结论:n为素数。说明通过for循环,没有找到任何一个因子,即循环是在循环上限退出的,即i>sqrt(n)。
3.2 下列程序求 n(n 的值由运行时确定)个正整数的最小公倍数。
#include <stdio.h>
#include <stdlib.h>
int main(){
int *p,i,n,gbs;
scanf("%d",&n) ;
p= (int*)malloc(n*sizeof(int)) ;
for(i=0; i<n; i++) scanf("%d",p+i);
gbs=*p;
do {
for(i=1; i<n; i++)
if( gbs%*(p+i)!=0 )
{
gbs+=*p;
break ;
}
}while (i!=n);
printf("%d\n",gbs);
return 0;
}
解析:熟悉动态内存分配方法、最小公倍数的求解方法。
第一空,读入n值。
第二空,动态分配内存。注意malloc函数的使用方法
第三空,求最小公倍数的基本思路是:以第一个数为基础,不断的扩大该数(1倍、2倍、3倍......),直到能被其他数整除。在这个过程中,一旦有一个不能整除,即刻停止剩下数的整除判断,再次扩大该数,重新判断整除性。
4编程题
#include <stdio.h>
int main()
{
int a[10][10]= {{0}},i,j,n;
while( scanf("%d",&n),n<1||n>10);
for(i=0; i<n; i++)
a[i][i]=a[i][0]=1;
for(i=2; i<n; i++)
for(j=1; j<i; j++)
a[i][j]=a[i-1][j]+ a[i-1][j-1];
for(i=0; i<n; i++)
{
for(j=0; j<=i; j++) printf("%4d",a[i][j]);
putchar('\n') ;
}
}
解析:熟悉图形输出题型的分析方法(按行输出、逐步输出一行中的多个字符、需要分析每个字符的变化规律)、二维数组的定义、二维数组的元素操作。
整体思路:先用一个二维数组构造保存杨辉三角形的各行值,然后再输出该数组中元素。
(1)杨辉三角中,第一列(a[i][0])和对角线(a[i][i])上的元素都为1,单独设置。
(2)从第三行(i=2)开始,每一行中,中间的数字,为上一行正上方(a[i-1][j])、左上方(a[i-1][j-1])两个数字的和(a[i][j] = a[i-1][j-1]+a[i-1][j])
(3)按照上面的方法,构造杨辉三角形中每个元素,并保存在数组中。
(4)输出数组元素即可。
4.2 输入一串字符(长度不超过 80 个),把首字符及所有空格后面的第一个字符改成大写
后输出。如输入:“six months out of sight of land!”,输出:“Six Months Out Of
Sight Of Land!”。
#include <stdio.h>
#include<string.h>
#include<ctype.h>
int main(){
int i=0,k=0;
char c[81];
gets(c);
c[0]=toupper(c[0]);
for (i=1; i<strlen(c); i++)
{
if ((c[i]==' ')&&(islower(c[i+1])) )
c[i+1]=toupper(c[i+1]);
}
puts(c);
}
解析:
通过本题,可以熟悉字符串的操作:字符串保存在数组中、字符串的读取、如何循环取到字符串里的每一个字符。
toupper函数将字符转换为大写。islower函数用来判断字符是不是小写。
4.3 文件 e:\c.txt 中,每行存储:学号、成绩、交作业次数,各字段之间用空格间隔。编 程,将所有考试成绩小于 55 分且交作业次数少于 4 次的学生记录从文件中删除。
#include <stdio.h>
void main(){
FILE *f1,*f2;
char xh[9];
int cj,cs;
f1=fopen("e:\\c.txt","r");
f2=fopen("e:\\d.txt","w");
while(fscanf(f1,"%s%d%d",xh,&cj,&cs)!=EOF)
if(cj>=55 && cs>=4 ) fprintf(f2,"%s %d %d\n",xh,cj,cs);
fclose(f1);
fclose(f2);
remove("e:\\c.txt");
rename("e:\\d.txt","e:\\c.txt");
}
解析:
文件操作相关知识:FILE *定义、fopen函数、fprintf输出、fclose关闭文件、remove删除文件、rename改文件名。
4.4 给定一个 4 行 5 列的整数二维数组,从键盘输入所有的数,编写一个从小到大的排序
函数(自定义函数原型 void px(int a[],int n),在主程序中,调用该排序函数,把每行
的整数分别排序后,输出该二维数组。
#include <stdio.h>
void px(int a[],int n){
int i,j,k,t;
for(i=0; i<n-1; i++){
k=i;
for(j=i+1; j<n; j++){
if (a[k]>a[j]) k=j;
}
t=a[k];
a[k]=a[i];
a[i]=t;
}
for(i=0; i<n; i++)
printf("%5d",a[i]);
printf("\n");
}
int main(){
int i,j,a[4][5], b[5],p=0;
for(i=0; i<4; i++)
for(j=0; j<5; j++)
scanf("%d",&a[i][j]);
for(i=0; i<4; i++){
p=0;
for(j=0; j<5; j++){
b[p]=a[i][j];
p++;
}
px(b,5);
}
}
解析:熟练二维数组的定义、读入数据保存到数组中、数组元素的比较、排序算法