第六章 函数
1.选择题
(1)以下关于函数的说法中正确的是(A)。
A.调用函数时,只能把实参的值传送给形参,形参的值不能传送给实参
B.一个函数可以定义在其他函数中
C.函数必须有返回值和参数
D.一个函数只能调用定义在其之前的函数
B中,不允许函数嵌套定义,B错误;C中,函数返回值和参数都可以为空,C错误;D中,调用定义在其后的函数,可以先声明再调用,D错误。
(2)C语言中函数返回值的类型是由以下( B )决定的。
A.return语句中的表达式类型
B.函数定义时指定的类型
C.调用该函数时实参的数据类型
D.形参的数据类型
C语言中函数返回值的类型是由以下函数定义时指定的类型决定的。
(3)对于声明为void func(char ch, double x);的函数,以下能调用该函数的语句是(C)。
A.func("abc", 3.0);
B.func('65',10.5);
C.func('A', 10.5);
D.int t = func('a', 65);
A中,函数首个参数要求为char,"abc"不符合,A错误;B中,'65'为多字符字面量(multicharacter literal),以int储存,调用过程中在转换为char时会发生截断,只保留后面符合大小的部分,这里只保留'5',故部分编译器只会警告而不报错,然亦失其调用本意(将'65'作为'A'传入,这是我猜的 (●′ω`●) ),所以B错误;C正确;函数func无返回值,不能实现 t 的初始化,无法成功调用,D错误。
(4)已知整型数组a和b都只有一个元素0且函数f定义如下,则执行f(a,b[0])后数组a和b中的元素分别为(C)。
void f(int a[], int b)
{
a[0]=1;
b=1;
}
A. 1和1
B. 0和0
C. 1和0
D. 0和1
题中,实参a作为数组名传入,函数实际接受的为数组a的首地址,实参和形参指向同一数组,故函数体内对形参数组a的更改会产生实际作用。而实参b[0]作为变量值的传入,函数中形参b为b[0]的映射,b的变化,不会对b[0]产生作用。
(5)用数组名作为函数调用时的实参,则传递给形参的是(A)。
A.数组首地址
B.数组的第一个元素值
C.数组中全部元素的值
D.数组元素的个数
用数组名作为函数调用时的实参,则传递给形参的是数组首地址。
(6)以下能够声明函数void fun(int arr[], int n){}的语句是(B)。
A. fun(int arr[], int n);
B. void fun(int [], int);
C. void fun(int arr[],n);
D. void fun(int, int);
函数声明中的形参名可省略,B正确。A中未表明函数的返回值类型,B、C中未正确表明函数参数类型。
(7)关于函数的递归调用,以下说法错误的是(D)。
A.递归可以分为直接递归和间接递归
B.递归函数中一定有递归出口
C.通常使用选择结构设置结束递归或继续递归的条件
D.递归函数的效率比功能相同的非递归函数更高
当计算量小或递归中存在大量的重复计算时,递归的效率可能比非递归低,D错误。
(8)以下说法中不正确的是(D)。
A.在不同的函数中可以定义相同名字的变量
B.形式参数是函数内的局部变量
C.在函数内定义的变量只在该函数范围内可访问
D.在函数内的复合语句中定义的变量在整个函数范围内都可访问
在一个函数内定义的变量是局部变量,只在函数体内可以访问,D错误。
(9)已知:#define fun(a,b) a*b,则:fun(1+2,3+4)的值为(D)。
A.21
B.15
C.13
D.11
宏调用在编译之前把参数记号传递给程序,而非参数的值,故fun(1+2,3+4)的值为 1+2*3+4,计算结果为11,D正确。
(10)函数f定义如下,执行语句“sum=f(5)+f(3);”后,sum的值应为(C)。
int f( int m )
{
static int i=0;
int s=0;
for( ; i<=m; i++)
s+=i;
return s;
}
A.21
B.16
C.15
D.8
i为静态变量,只进行一次初始化,即二次调用时,i值不会被赋予0,在f(3)调用时,i值为6,故f(3)值为0,sum值为15,C正确。
2.填空题
(1)程序执行的入口点、不能被其他函数调用的是 main() 函数。
(2)若函数没有返回值语句,则函数的返回值类型说明符为 void 。
参数和返回值都不是函数必需的
(3)函数由 函数首部 和函数体两个部分组成。
(4)若函数类型缺省没定义,则隐含的函数返回值类型是 int 。
(5)已知函数的定义为int fun(int a, double b){…},则声明函数的语句为 int fun(int a, double b); 。
也可忽略形参名:int fun(int, double);
(6)声明一个局部变量用静态方式存储的关键字是 static 。
(7)以下程序的输出结果是 7,14 。
#include<stdio.h>
int func(int a, int b)
{
static int m = 1, i = 2;
i += m;
m = i + a + b;
return m;
}
int main(void)
{
int k = 3, m = 1, p;
p = func(k, m);
printf("%d,", p);
p = func(k, m);
printf("%d\n", p);
return 0;
}
func()中i、m都为静态变量,首次调用时,p=m=3+3+1,输出为7,第二次时,p=m=10+3+1,输出为14。
(8)以下程序的输出结果是 1 2 。
#include<stdio.h>
#include<string.h>
int count(char str[], char c);
int main(void)
{
char s[] = "I love C programming!\n\0 I love China!";
printf("%d %d\n", count(s, 'I'), count(s, 'o'));
return 0;
}
int count(char str[], char c)
{
int i, t = 0;
for (i = 0; i < strlen(str); i++)
{
if (str[i] == c)
{
t++;
}
}
return t;
}
count()意在记录字符数组str中有几个c字符,而传入的字符数组s中带'\0',strlen()不会算上" I love China!"的长度,故'I'有 1 个,'o'有 2 个。
(9)以下程序的输出结果是 a=48 。
#include<stdio.h>
int f(intd[], int m)
{
int j, s = 1;
for (j = 0; j < m; j++)
{
s = s*d[j];
}
return s;
}
int main(void)
{
int a, z[] = { 2,4,6,8,10 };
a = f(z, 3);
printf("a=%d\n", a);
return 0;
}
f()意在计算数组intd的前m项的累乘。
(10)以下程序的输出结果是 654321 。
#include<stdio.h>
void func(int n)
{
printf("%d", n % 10);
if (n >= 10)
{
func(n / 10);
}
else
{
printf("\n");
}
}
int main(void)
{
func(123456);
return 0;
}
func()意在从末位依次输出各位的数字。输出末位后,通过n/10进行递归。
3.编程题
(1)编写函数,将一个仅包含整数(可能为负)的字符串转化为对应的整数。
#include <stdio.h>
int f(char s[]);
int main(void)
{
int res;
char s[20];
gets(s);//获取字符串
res = f(s);
printf("%d\n", res);
return 0;
}
int f(char s[])
{
int res = 0, flag = 1;
for (int i = 0; i < strlen(s); i++)
{//遍历数组,非'-'号转换为int
if (s[i] != '-')
{
res = res * 10 + (s[i] - '0');
}
else
{
flag = 0;
}
}
if (flag == 0) res *= -1;//若曾遇'-',改变res
return res;
}
(2)编写一个能比较字符串大小的函数,将两个字符串中第一个不相同字符的ASCII码值之差作为返回值。
#include <stdio.h>
int f(char s1[], char s2[]);
int main(void)
{
char s1[20], s2[20];
int res;
printf("字符串1:");
gets(s1);
printf("\n字符串2:");
gets(s2);
res = f(s1, s2);
printf("差值为%d", res);//输出差值
return 0;
}
int f(char s1[], char s2[])
{
int i;
for (i = 0; s1[i] == s2[i]; i++)
{//比较直到不同之处
if (s1[i] == '\0')
{
printf("字符串1等于字符串2\n");
return 0;
}
}
if (s1[i] > s2[i])
{//利用下标i时,s1和s2不同,再进行比较具体的大小
printf("字符串1大于字符串2\n");
return (s1[i] - s2[i]);
}
else
{
printf("字符串1小于字符串2\n");
return (s2[i] - s1[i]);
}
return 0;
}
(3)编写程序,从键盘输入10个整数,用函数实现将其中最大数与最小数的位置对换,输出调整后的数组。
#include <stdio.h>
void f(int s[]);
int main(void)
{
int s[10];
for (int i = 0; i < 10; i++)
{
scanf("%d", &s[i]);
}
f(s);
}
void f(int s[])
{
int max = 0, min = 0;
for (int i = 1; i < 10; i++)
{//寻找最大值、最小值
if (s[max] < s[i])
{
max = i;
}
if (s[min] > s[i])
{
min = i;
}
}
s[max] += s[min];//交换最大值和最小值位置
s[min] = s[max] - s[min];
s[max] -= s[min];
for (int i = 0; i < 10; i++)
{
printf("%d\n", s[i]);
}
}
(4)编写函数,对给定的二维数组(3×3)进行转置(即行列互换)。
#include <stdio.h>
void f(int s[3][3]);
int main(void)
{
int s[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
scanf("%d", &s[i][j]);
}
}
f(s);
}
void f(int s[3][3])
{
int res[3][3];//用res记录转换后的数组
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
res[i][j] = s[j][i];
printf("%d ", res[i][j]);
}
printf("\n");
}
}
(5)编写函数,用冒泡法对输入的字符(不超过10个)按从小到大顺序排序。
#include <stdio.h>
void f(char s[]);
int main(void)
{
char s[20];
printf("输入不超过10个的字符:");
gets(s);
while (strlen(s) > 10)
{
printf("字符过多,重新输入:");
gets(s);
}
f(s);
}
void f(char s[])
{
int k = 0;
for (int i = 0; i < 9; i++)
{
for (int j = 9; j > i ; j--)
{
if (s[j] < s[j - 1])
{//交换
s[j - 1] += s[j];
s[j] = s[j - 1] - s[j];
s[j - 1] -= s[j];
}
}
}
printf("%s", s);
}
(6)编写程序,输出3~10000内的可逆质数。可逆质数是指:一个质数将其各位数字的顺序倒过来构成的反序数也是质数。如157和751均为质数,它们是可逆质数。要求调用两个函数实现。
#include <stdio.h>
#include <math.h>
int prime(int n);
int invert(int n);
int main(void)
{
for (int i = 3; i < 10001; i++)
{//遍历3~10000
if (prime(i) && invert(i))
{
printf("%d\n", i);
}
}
return 0;
}
int prime(int n)
{
if ((n + 1) % 6 == 0 || (n - 1) % 6 == 0)
{//利用大于等于5的质数一定和6的倍数相邻性质
for (int i = 2; i < (int)sqrt(n) + 1; i++)
{//判断是否可为2到其平方根+1整除
if (n % i == 0)
{
return 0;
}
}
return 1;
}
else
{
if (n == 3)
{
return 1;
}
}
return 0;
}
int invert(int n)
{//翻转并判断是否为质数
int res = 0;
while (n != 0)
{
res = res * 10 + n % 10;
n /= 10;
}
if (prime(res))
{
return 1;
}
return 0;
}
(7)编写函数,将一个十进制数转换成八进制数。
#include <stdio.h>
void f(int n);
int main(void)
{
int n;
scanf("%d", &n);
f(n);
return 0;
}
void f(int n)
{
char res[20];
int k = 0;
while (n != 0)
{
res[k] = (n % 8) + '0';
n /= 8;
k++;
}
for (int i = k - 1; i >= 0; i--)
{
printf("%c", res[i]);
}
}
(8)从键盘输入一个正整数,逆序输出。要求使用循环和递归两种方法分别实现。
#include <stdio.h>
void f1(int n);
void f2(int n);
int main(void)
{
int n;
scanf_s("%d", &n, sizeof(n));
f1(n);
printf("递归:");
f2(n);
return 0;
}
void f1(int n)//循环
{
int res = 0;
while (n != 0)
{
res = res * 10 + n % 10;
n /= 10;
}
printf("循环:%d\n", res);
}
void f2(int n)//递归
{
printf("%d", n % 10);
n /= 10;
if (n != 0)
{
f2(n);
}
}
(9)定义带参数的宏,计算三角形的周长和面积。
#include <stdio.h>
#include <math.h>
#define cir(a, b, c) (a + b + c)
#define s(a, b, c) sqrt((a+b+c)/2*((a+b+c)/2-a)*((a+b+c)/2-b)*((a+b+c)/2-c))
int main(void)
{
float a = 0, b = 0, c = 0;
printf("输入三边长\n");
printf("a:");
scanf("%f", &a);
printf("b:");
scanf("%f", &b);
printf("c:");
scanf("%f", &c);
printf("\n周长为:%.2f\n", cir(a, b, c));
printf("面积为:%.2f\n", s(a, b, c));
return 0;
}
(10)定义函数,参数分别表示行数、列数和字符,输出由该行该列该字符构成的以下这种空心图形。
* * * * *
* *
* *
* * * * *
#include <stdio.h>
void f(int row, int column, char c);
void col(int column, char c, int flag);
int main(void)
{
int row, column;
char c;
printf("输出行数");
scanf("%d", &row);
printf("输出列数");
scanf("%d", &column);
printf("输出字符");
getchar();// 清除输入缓冲区中的换行符
scanf("%c", &c);
f(row, column, c);
return 0;
}
void f(int row, int column, char c)
{
for (int i = 0; i < row; i++)
{
int flag = i == 0 || i == row - 1;
if (flag)
{
for (int i = 0; i < column; i++)
{
printf("%c ", c);
}
printf("\n");
}
else
{
for (int i = 0; i < column; i++)
{
if (i == 0 || i == column - 1)
{
printf("%c ", c);
}
else printf(" ");
}
printf("\n");
}
}
}
如有错误不足之处,恳请批评指正。
题目来源:C程序设计教程与实验(第3版) 吉顺如主编
答案参照微信公众号:程序设计及信息技术学习平台