C语言期末复习练习及解析(1)

文档请见http://t.csdnimg.cn/99eA4

期末复习练习解析01

1、选择题(20分)

1.1 C语言unsigned char类型数据能表示的最大数值是:(

A、65535 B、128 C、127 D、255

答案:D

解析:

char为1字节(byte),8位(bit),unsigned char为无符号,因此8位中不需要预留符号位,8位都表示数据(二进制:1111 1111):28 - 1 = 255。

char:1字节(8位)

int:4字节 (32位,取值范围 -2^31 ~ 2^31-1)

unsigned int:4字节 (32位,取值范围 0 ~ 2^32-1)

long:4字节 (32位,取值范围 -2^31 ~ 2^31-1)

unsigned long:4字节 (32位,取值范围 0 ~ 2^32-1)

long long:8字节(64位,取值范围 -2^63 ~ 2^63-1)

1.2 执行下列int i = 0, for(;i<5;)i++; 程序段后,i值为:(

A、0 B、6 C、5 D、4

答案:C

解析:

i = 0时,满足循环条件(i<5),进入循环执行i++,i变成1;

i = 1时,满足循环条件(i<5),进入循环执行i++,i变成2;

i = 2时,满足循环条件(i<5),进入循环执行i++,i变成3;

i = 3时,满足循环条件(i<5),进入循环执行i++,i变成4;

i = 4时,满足循环条件(i<5),进入循环执行i++,i变成5;

i = 5时,不满足循环条件(i<5),退出循环。

1.3 关于C的整型常量说法正确的是:(

A、0812 B、\128 C、-0xfadu D、2e2

答案:C

解析:

A选项中,以0开头的数字为八进制,可以使用0-7的数字,但八进制中没有8。

B选项中,\为反斜杠,表示转义符,后面可以接一个特殊字符(譬如\n为换行)、可以接一个三位的八进制数(譬如\127表示ASCII表中的字符'W',十进制值为87)、可以个两位的十六进制数(譬如'\x57'表示ASCII表中的字符'W',十进制值为87)。B中\128八进制中没有8。

C选项中,以0x开头的数字为十六进制,可以使用0-9, A-F。最前面的是负号,负数以补码形式保存,符号位取1。末尾的u ,告诉编译器该常数的属性,作为无符号类型的数据进行处理。

D选项中,2e2,为科学计数法,即2*102  = 200。

1.4 C语言中的关键字是:(

A、sort B、char C、function D、=

答案:B

解析:char表示字符数据类型

1.5 执行double a, d = 3.4; int b; a = (b=d/2.0)/2; printf(%.2f,%d, a,b);代码段后的结果是:

A、0.00, 2 B、0.85, 1 C、0.85, 2 D、0.00, 1

答案:D

解析:

执行语句a = (b=d/2.0)/2;

  1. 先执行d/2.0,由于d= 3.4两个浮点数相除,得到1.7
  2. 再执行1.7赋值给b,由于b为整型数,因此1.7会去掉小数部分,b = 1
  3. 执行1/2,由于两个都是整型数,因此商0.5会去掉小数部分变成0,再赋值给a,由于a为double类型,所以a=0.000000。
  4. 输出a与b,输出a的格式符为%.2f,即保留2位小数精度,输出0.00。b的格式符为%d,输出1。

1.6 代码void f() {static int x = 1; }中关于变量x作用域说法正确的是:

A、块作用域 B、函数作用域 C、文件作用域 D、函数原型作用域

答案:B

解析:

作用域:描述了程序中可以访问一个标识符的一个或多个区域,即变量的可见性。

静态(static)局部变量作用域是在定义的函数内有效。static局部变量的生命周期和程序运行周期一样,同时staitc局部变量的值只初始化一次,但可以赋值多次。static局部变量若未赋以初值,则由系统自动赋值:数值型变量自动赋初值0,字符型变量赋空字符。

静态(static)全局变量:在函数外定义,作用范围被限制在所定义的文件中。不同文件静态全局变量可以重名,但作用域不冲突。static全局变量的生命周期和程序运行周期一样,同时staitc全局变量的值只初始化一次。

块作用域:譬如if(){}、while(){}、switch(){ case 1:{}} 等各种情况的{}即块作用域,在{}中定义的变量,作用域仅限定在{}中。

文件作用域:任何在代码块之外声明的标识符都具有文件作用域。

1.7 对于二维数组int a[3][5],下列表达式说法正确的是:

A. *++a是元素啊[1][0]的地址

B. a[0]是元素a[0][0]的地址

C. a[0]是首行的行地址

D. *a++是元素a[0][0]的地址

答案:B

解析:

a为数组名,是constant pointer,它的指向不能被修改,++a与a++都不能指向,A与D都不对。

a[0]等价于*a,即*(a+0)+0,取到了一次间访,表示某个元素的地址(二维数组中,取一次间访,取到某个元素地址,取两次间访,表示某个元素的内容)

行地址表示a+1表示第二行行地址,a+3表示第四行行地址。

1.8 关于函数,表达正确的是:

A. 执行语句return;函数返回值为0

B. 无return语句函数返回值为0

C. 函数参数传递本质上均是值传递

D. 函数可以嵌套定义

答案:C

解析:

A选项中,return; 退出函数,无返回值;

B选项中,如果函数中无return语句,该函数不返回值。

C选项,函数参数传递包括:传值和传地址。传值传递了原值的一个拷贝,原值不会被修改;传地址,传递了一个地址的拷贝,通过该地址,可以修改原值。

D选项:函数不可以在另一函数中进行定义,不能嵌套定义,但可以嵌套调用。

1.9 定义#define s(r) 3.14*r*r计算圆面积,则printf(%6.2f, s(s(1)+2))的值:

A. 18.14 B. 28.26 C.7.14 D. 82.96

答案:A

解析:

宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。宏替换只是单纯的替换,因此对s(s(1)+2)替换时,先替换s(1),变成s(3.14*1*1+2),再进一步替换:3.14*3.14*1*1+2*3.14*1*1+2 = 18.14。

注意,第二步替换的结果并不是3.14*(3.14*1*1+2)*(3.14*1*1+2)+2 = 82.96,如果希望这样,宏定义时,表达式要加上小括号:#define s(r) (2.14*r*r)

1.10 若声明int year表示年份,则判断闰年的表达式是:

A. year%4==0 && year%100!=0

B. Year%400==0

C. Year%4==0 && !(year%100) || year%400 == 0

D. Year%4==0 && year%100 || year%400 == 0

答案:D

解析:

闰年判断条件:能被4整除,但不能被400整除;或者能被400整除。

year%4 == 0 表示能被4整除

year%100!=0表示不能被100整除

year%100为真,表示不能被100整除

  1. 程序阅读题(28分)

2.1

#include<stdio.h>

void main(){

    int i, n = 30;

    long a = 1, b = 1, tmp;

    for(i = 0; i< n; i++)

        tmp = a, a = b, b +=tmp;

    printf("%.3f  %.3f\n", (double)a/tmp, (double)tmp/a);

}

答案: 1.618   0.618  

解析:列举多次循环下,tmp, a, b的不同取值,可以发现,tmp和a满足斐波那数列,即

tmp: 1 1 2 3 5 8  13 21 34 55 89   ......

a: 1 2 3 5 8 13 21 34 55 89 144  ......

并不需要计算出i=29时的a与b值,再进行除法运算。

分析可得,a/tmp为数列中后项与前项的比值

          tmp/a为数列中前项与后项的比值

可以发现,这个比值,随着项数的增加,会趋向一个常数(黄金比)。

取144/89和89/144计算即可。

自己可以编码验证一下:

#include <stdio.h>

int fac(int n){

    if(n == 0 || n ==1)

        return 1;

    return fac(n-1)+ fac(n -2);

}

int main() {

    printf("%.3f %.3f", (double)fac(30)/fac(29),

           (double)fac(29)/fac(30));

    return 0;

}

2.2

#include<stdio.h>

void main(){

    int i, j, s, x[4][4]={1,2,3,4,3,4,5,6,5,6,7,8,7,8,9,10};

    for(i = 0; i< 4; i++)    {

        s = 0;

        for(j = 0; j< 4; j++)        {

            if(i>=j) continue;

            s+=*(x[i]+j);        

        }

        printf("%d\t",s);

    }

}

答案:   9      11     8     0  

解析:

if(i>=j) continue; 表示当左下角的数字不进行累计求和。右上角(不包括对角线上的数)的数,每一行的数据分别累计求和。

第一行:2+3+4==9

第二行:5+6=11

第三行:8

第四行:0

2.3

#include<stdio.h>

void f1(float x, float y){

    float tmp;

    tmp = x, x = y, y = tmp;

}

void f2(float *x, float*y){

    float * tmp;

    tmp = x, x = y, y = tmp;

}

void f3(float *x, float * y){

    float tmp;

    tmp = *x, *x = *y, *y = tmp;

}

void main(){

    float x = 3.14, y = 6.28, *p1 = &x, *p2= &y;

    f1(*p1, *p2), printf("%5.2f  %5.2f\n", x,y);

    f2(p1, p2), printf("%5.2f  %5.2f\n", x,y);

    f3(&x, &y), printf("%5.2f  %5.2f\n", x,y);

}

答案:

  3.14     6.28

  3.14     6.28

  6.28     3.14  

解析:

函数f1传值方式,不能实现交换功能

函数f2传指针方式,但函数的实现逻辑不能实现交换功能

函数f3传指针方式,能实现交换功能。

f1(*p1, *p2)函数调用时,实参为间访,函数f1为传值方式,不能实现交换功能

f2(p1, p2)函数调用时,实参为两个指针,但f2函数的实现逻辑不能实现交换功能

f3(&x, &y)实参为两个地址,能实现交换功能

2.4

#include<stdio.h>

char n = 65;

void f(){

    static char a = 'A';

    char b = 'B';

    a+=2, b+=5, n+=3;

    printf("%c\t%c\t%c\n", a,b,n);

}

void main(){

    char a = 'A', b = 'B';

    printf("%c\t%c\t%c\n", a,b,n);

    f();

    printf("%c\t%c\t%c\n", a,b,n);

}

答案:

  A     B     A  

  C     G     D   

  A     B     D  

解析:

常用字母的ASCII值:A-->65, Z-->90, a-->97, z-->122, 0-->48, 9-->57

char n = 65; n为全局变量,ASCII码值65对应字符A。函数f()中n+=3,n被修改为D

函数f()中,a为静态局部变量,b为局部变量,a与b的作用域为函数f(),a+=2, b+=5,修改a,b的值只在f()函数中起作用。

main函数中,

a与b为局部变量,作用域为main函数中。

第一句printf("%c\t%c\t%c\n", a,b,n); a = 'A', b = 'B,n= A

执行f()函数,输出f()函数中的a,b,n值,分别为a = 'C', b = 'G,n= D

第二句printf("%c\t%c\t%c\n", a,b,n); ,a = 'A', b = 'B,由于n已经在f()函数中被修改n= D

2.5

#include<stdio.h>

#include<string.h>

void main(){

    char tmp[81], a[6][81] = {"chemical", "biotech", "materials",

                            "computer", "information", "public admin"};

    int i,j,k;

    for(i=0; i<5; i++){

        k = i;

        for(j = i+1; j<6; j++)

            if(strcmp(*(a+j), *(a+k))>0) k = j;

        strcpy(tmp, *(a+i));

        strcpy(a[i], a[k]);

        strcpy(*(a+k),tmp);

    }

    for(i = 0; i<3; i++) puts(a[i]);

}

答案:

  public admin   

  materials      

  information     

解析:

二维数组a为字符串数组;字符数组tmp为字符串。

代码中采用了选择排序方法,对字符串数组进行降序排序。排序中字符串的比较与交换需要使用strcmpstrcpy函数。间访*(a+j),也可以表示为a[j],表示第j+1个字符串。

puts函数用于输出字符串,代码中输出了前三个字符串。

  1. 程序填空题(12分)
    1. 【程序说明】下列函数用于在升序排列的数组v中找出x的位置。

int binSearch(int x, int v[], int n){

    int low =0, high = n-1, mid;

    while (low <= high){

        mid =        (1)          ;

        if(x <v[mid])

            high =         (2)        ;

        else if (x > v[mid])

            low =       (3)          ;

        else

            return mid;

    }

    return -1;

}

答案:

(1)   (low + high) / 2   (2)    mid  1     (3)     mid + 1    

解析:

本函数为二分法查找算法。x为待搜索的数字,v为已经排好序的数组,n为数组元素个数。

二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。

二分法查找的思路如下:

(1)首先,从数组的中间元素(下标为:mid = (low+high)/2)开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。

(2)如果目标元素小于中间元素,则在数组小于中间元素的那一半区域查找(修改high = mid - 1),然后重复步骤(1)的操作。

3)如果目标元素大于中间元素,则在数组大于中间元素的那一半区域查找(修改low = mid + 1),然后重复步骤(1)的操作。

4)如果某一步数组为空(low > high),则表示找不到目标元素,返回-1值

可以执行下面代码验证:

#include<stdio.h>

int binSearch(int x, int v[], int n){

    int low =0, high = n-1, mid;

    while (low <= high){

        mid = (low + high)/2;

        if(x <v[mid])

            high = mid -1;

        else if (x > v[mid])

            low = mid+1;

        else

            return mid;

    }

    return -1;

}

void main(){

    int a[10] = {1,2,7,8,9,10,11,90,98,109};

    int result = binSearch(90, a, 10);

    printf("%d", result);

}

    1. 【程序说明】校区信息保存在新飞行对象中,要求找出学生最多的校园,请根据代码中上下文信息补充所缺内容。

#include <stdio.h>

struct campus {float area;  int students; char name[50];};

void main() {

struct campus univ[4] ={{414, 3000, "朝晖"},{2150, 15000, "屏峰"},

{990, 5000, "莫干山"},{222, 7500, "之江"}};

    struct campus *p = univ;

    int num = univ->students;

    for(int i = 1; i< sizeof(univ)/sizeof(struct campus);i++) {

        if(       (1)         ){

                   (2)         ;

                   (3)         ;

        }

    }

    printf("%s %d %.0f\n",   (4)    ,   (5)    ,   (6)    );

}

答案:

(1) univ[i].students > num  (2) p = univ+i   (3) num = p->students 

(4)        p->name           (5) p->students  (6)  p->area  

解析:

题目中定义了结构体类型campus,在main函数中定义了结构体类型数组univ、结构体类型指针p。指针p用于保存找到的学生最多的校园,num用于保存最大学生数目。

for循环对数组里面的每一个校区进行遍历,if语句需要判断当前遍历到的校区,它的人数是不是大于num ,如果大于num,就用p记录该校区,它的学生人数也赋值给num。

当for循环执行结束后,p指向了数组中学生最多的校园。通过printf函数,输出该校区的相关信息。

由于p是指针,它的成员运算符要使用->。

  1. 程序设计题(40分)

4.1 已知某公司员工的保底薪水为800元,某月所接工程的利润profit(整数)与利润提成的关系如下(计量单位:元):

           profit <= 1000   没有提成

    1000 < profit <= 2000   提成10%

    2000 < profit <= 5000   提成15%

    5000 < profit <= 10000  提成20%

           profit >  10000  提成25%

编写程序计算该公司员工该月的薪水。(10分)

答案:

#include <stdio.h>

void main() {

int profit, grade;

double salary = 800;

printf("请输入本月利润:");

scanf("%d", &profit);

grade = (profit-1) / 1000;

switch(grade) {

case 0: break;

case 1: salary += profit*0.1; break;

case 2:

case 3:

case 4: salary += profit*0.15; break;

case 5:

case 6:

case 7:

case 8:

case 9: salary += profit*0.2; break;

default: salary += profit*0.25; }

printf("本月薪水:%.2f", salary);

}

答案:

#include <stdio.h>

#include <math.h>

void main() {

double x, fx, gx;

scanf("%lf", &x);

gx = x*x - 2;

if (x >= gx)

fx = gx - sin(x) - x;

else

fx = gx + sin(x) + x + 4;

printf("%8.2f\n", fx);

}

4.3 现有数列 1,1/(1+2),1/(1+2+3),1/(1+2+3+4),编写程序计算并输出误差小于给定ε(如0.00001,要求从标准输入设备输入)的数列和。10分)

#include <stdio.h>

void main() {

int i, j, t;

double s=0, delta, epsilon;

scanf("%lf", &epsilon);

for (i=1;;i++) {

t = 0;

for (j=1; j<=i; j++) t += j;

delta = 1.0 / t;

if (delta < epsilon) break;

s += delta; }

printf("误差小于%.2e的数列和: %8.6f\n", epsilon, s);

}

4.4 编写函数进行数据读取,左右反转和输出操作,函数原型为:

       void scanArray(float [], int);    void myReverse (float*, int);

       void printArray(float *, int);

  在main函数中分别调用上述函数输入10个实数,执行左右翻转并输出。(10分)

答案:

#include <stdio.h>

void scanArray(float [], int);

void printArray(float *, int);

void myReverse(float *, int);

void main() {

float a[10];

scanArray(a, 10);

myReverse(a, 10);

printArray(a, 10);

}

void scanArray(float x[], int n) {

int i;

for (i=0; i<n; i++) scanf("%f", x+i);

}

void printArray(float *p, int n) {

int i;

for (i=0; i<n; i++) printf("%.2f  ", *p++);

printf("\n");

}

void myReverse(float *p, int n) {

int i;

float temp;

for (i=0; i<n/2; i++) temp = p[i], p[i] = p[n-1-i], p[n-1-i] = temp;

}

  • 5
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
说明:答案必须填写在答题卡的相应位置上,否则不得分。 1.C语言中字符型(char)数据在内存中的存储形式是________。 A、原码 B、反码 C、补码 D、ASCII码 2.C语言中基本的数据类型包括________。 A、整型、实型、逻辑型 B、整型、实型、字符型 C、 整型、字符型、逻辑型 D、整型、实型、逻辑型、字符型 3.在C语言中,int类型数据在内存中占用________。 A、2字节 B、4字节 C、由编译系统决定 D、由用户决定 4.运算符有优先级,C语言中关于运算符优先级的正确叙述是________。 A、逻辑运算符高于算术运算符,算术运算符高于关系运算符; B、算术运算符高于关系运算符,关系运算符高于逻辑运算符; C、算术运算符高于逻辑运算符,逻辑运算符高于关系运算符; D、关系运算符高于逻辑运算符,逻辑运算符高于算术运算符。 5.下面关于C语言语句的叙述,错误的是________。 A、C语言一行可以允许写多条语句; B、C语言语句用分号结束; C、语句一行写不下时,可以用逗号换行 ; D、语句一行写不下时,可在任意一空格处回车换行 。 6.下面数据中不属于字符型常量的是________。 A、“\n” B、‘\0’ C、‘A’ D、‘\t’ 7.11.以下选项中,当x为大于1的奇数时,值为0的表达式__________ 。 A、 x%2==1 B、 x/2 C、x%2!=0 D、x%2==0 8.C语言源程序名的后缀是__________ 。 A 、 .exe B、 .C C、 .obj D、 .cp 9.设所有变量均为int型,则表达式(a=5,b=2,b++,a-b)的值是________。 A、7 B、8 C、6 D、2 10.若有说明语句:int a;float b;,以下输入语句正确的是________。 A、scanf("%f%f",&a,&b); B、scanf("%f%d",&a,&b); C、scanf("%d,%f",&a,&b); D、scanf("%6.2f%6.2f",&a,&b);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Enza、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值