c语言学习回顾4--- 函数

1、以下关于函数设计不正确的说法是________
A、函数设计应该追求高内聚低耦合
B、要尽可能多地使用全局变量
C、函数参数不宜过多
D、设计函数时,尽量做到谁申请的资源就由谁来释放
2、关于C语言函数描述正确的是_________
A、函数必须有参数和返回值
B、函数的实参只能是变量
C、库函数的使用必须包含对应的头文件
D、有了库函数就不需要自定义函数了
3、C语言规定,在一个源文件中,main函数的位置_______
A、必须在最开始
B、可以在库函数的后面
C、可以任意
D、必须在最后
4、下列叙述中不正确的是_________
A、在不同的函数中可以使用相同名字的变量
B、函数中的形式参数是在栈中保存
C、在一个函数内定义的变量只在本函数范围内有效
D、在一个函数内复合语句中定义的变量在本函数范围内有效(复合语句指函数中的成对括号构成的代码)
5、能把函数处理结果的两个数据传给主调函数,在下面的方法中不正确的是_________
A、return这两个数
B、形参用数组
C、形参用二个指针
D、用两个全局变量
6、关于函数调用说法不正确的是________
A、函数可以传值调用,传值调用的时候形参是实参的一份临时拷贝
B、函数可以传址调用,传址调用的时候,可以通过形参操作实参
C、函数可以嵌套定义,但是不能嵌套调用
D、函数可以嵌套调用,但是不能嵌套定义
7、在函数调用时,以下说法正确的是_____________
A、函数调用后必须带有返回值
B、实际参数和形式参数可以同名
C、函数间的数据传递不可以使用全局变量
D、主调函数和被调函数总是在同一个文件里
8、关于函数的声明和定义说法正确的是_______________
A、函数的定义必须放在函数的使用之前
B、函数必须保证先声明后使用
C、函数定义在使用之后,也可以不声明
D、函数的声明就是说明函数是怎么实现的
9、关于实参和形参描述错误的是_______________
A、形参是实参的一份临时拷贝
B、形参是在函数调用的时候才实例化,才开辟内存空间
C、改变形参就是改变实参
D、函数调用如果采用传值调用,改变形参不影响实参
10、函数调用exec((v1,v2),(v3,v4),v5,v6);中,实参的个数是________
A、3
B、4
C、5
D、6
11、编程题(乘法口诀表,实现一个函数,打印乘法口诀表,口诀表的行数和列数自己指定,比如:输入9,输出99口诀表,输入12,输出1212口诀表)

void print_table(int n)
{
	int i = 0, j = 0;//行和列,i行j列
	for (i = 1; i <= n; i++)
	{
		//打印一行
		for (j = 1; j <= i; j++)
		{
			//列
			printf("%d*%d=%2d ", j, i, i * j);
		}
		printf("\n");
	}
}
int main()
{
	int i = 0, j = 0, ret = 0;
	int n = 0;
	scanf("%d", &n);
	//函数的起名是非常关键的,名字最好能体现函数的功能 这里起名字为print_table
	print_table(n);
	return 0;
}

6
1*1= 1
1*2= 2 2*2= 4
1*3= 3 2*3= 6 3*3= 9
1*4= 4 2*4= 8 3*4=12 4*4=16
1*5= 5 2*5=10 3*5=15 4*5=20 5*5=25
1*6= 6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36

12、关于递归的描述错误的是________
A、存在限制条件,当满足这个限制条件的时候,递归便不再继续
B、每次递归调用之后越来越接近这个限制条件
C、递归可以无限递归下去
D、递归层次太深,会出现栈溢出现象
13、根据下面递归函数,调用函数Fun(2),返回值是多少________

int Fun(int n)
{
	if (n == 5)
		return 2;
	else 
		return 2 * Fun(n + 1);
}

A、2
B、4
C、8
D、16
14、编程题(使用递归实现字符串逆序)
编写一个函数reverse_string(char * string)(递归实现);
实现:将参数字符串中的字符反向排列,不是逆序打印。
要求:不能使用c库函数中的字符串操作函数

比如:char arr[]=“abcdef”;
逆序之后数组的内容变成fedcba
首先用正常的写法来写,看看是如何实现反向排列的。

int my_strlen(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
char reverse_sring(char* str)
{
	int len = my_strlen(str) - 1;
	int i = 0, j = len;
	//i、j分别是数组的最左边和最右边的元素下标
	char b = "";
	while(i<j)
	{
		b = str[j];
		//b=*(str+j),这种写法与b = str[j]的写法一模一样
		str[j] = str[i];
		str[i] = b;
		i++;
		j--;
	}
}
int main()
{
	char arr[] = "abcdef";//数组名arr是数组arr首元素的地址
	reverse_sring(arr);
	//printf("%s\n",reverse_sring(arr));
	printf("%s\n", arr);
	return 0;
}

代码的运行结果如下:

fedcba

交换变量的那部分可以用指针的形式来改写一下:

char reverse_sring(char* str)
{
	int len = my_strlen(str) - 1;
	//i、j分别是数组的最左边和最右边的元素下标
	int i = 0, j = len;
	char b = "";
	while (i < j)
	{
		b = *(str + j);
		*(str + j)= *(str + i);
		*(str + i) = b;
		i++;
		j--;
	}
}

运行代码的结果跟之前是一模一样的。
那么使用递归的方法怎么做呢?

int my_strlen(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
void reverse_string(char* str)
{
	char tmp = *str;//将数组首地址所在的元素放在tmp里面
	int len = my_strlen(str) ;//计算字符串的长度
	*str = *(str+len-1);//将最后一个字符放到第一个的位置
	*(str + len - 1) = '\0';//并且最后一个字符给它设置成结束符
	//递归的条件判断
	if (my_strlen(str+1)>=2)
	{
		reverse_string(str + 1);//递归
	}
	
	*(str + len - 1) = tmp;//此时将tmp中放置的第一个字符a放到最后一个字符的位置
}
int main()
{
	char arr[] = "abcdef";//数组名arr是数组arr首元素的地址
	reverse_string(arr);
	//printf("%s\n",reverse_sring(arr));
	printf("%s\n", arr);
	return 0;
}

代码的整体思路是:
abcdef的逆序可以理解为a和f的交换加上bcde的逆序,bcde的逆序又可以理解为b和e的交换(递归)加上cd的逆序,cd的逆序就是cd的交换(递归),cd中间没有元素或者只有一个元素的时候(此时cd中间没有元素了),就没有必要再进行交换逆序了,所以就有了递归的条件判断为:

if (my_strlen(str+1)>=2)
	{
		reverse_string(str + 1);//递归
	}

在这里插入图片描述
15、编程题(计算一个数的每位之和),题目内容:写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和。例如:调用DigitSum(1729),则应该返回1+7+2+9,它的和是19.

代码的“大事化小”的整体思路:
DigitSum(1729)=》DigitSum(172)+9=》DigitSum(17)+2+9=》DigitSum(1)+7+2+9=》1+7+2+9
int DigitSum(int n)
{
	int count = 0;
	
	if (n>9)
	{
		return DigitSum(n/10) + n%10;
	}
	else
	{
		return n;
	}
	
}
int main()
{
	int n = 0;
	scanf("%d",&n);
	int sum =  DigitSum(n);
	printf("%d\n",sum);
	return 0;
}

代码的运行结果为:

1729
19

16、编程题(递归实现n的k次方),题目内容:编写一个函数实现n的k次方,使用递归实现。

double POW(int i,int j)
{
	//POW(m,n)=m * POW(m,n-1),当k>0的时候
	//POW(m,n)=1,当k=0的时候
	if (j == 0)
	
		return 1.0;
	
	else if (j > 0)
	
		return  i * POW(i, j - 1);
	
	else
		return 1.0 / (POW(i,-j));//k为负数
}
int main()
{
	int i = 0,j = 0;
	scanf("%d %d", &i, &j);
	double ret = POW(i,j);
	printf("%lf\n",ret);
	return 0;
}

代码的运行测试结果如下:

2 3
8.000000

2 -2
0.250000

3 0
1.000000

答案解析

1、B
A、高内聚低耦合是指这个函数足够的独立;B、全局变量其实在函数设计的时候使用是非常危险的,如果这个变量被改动,在函数内部就不能唯一地控制它了。C、一般参数不多于4个,特殊情况特殊对待。
2、C
函数无参数也是可以的,比如有很多时候main函数就是无参—int main(),但是返回类型是必须要写的,即使不返回什么具体类型也要写void空类型;B项说法错误;A和C好像都正确,但是C项更正确一些。
3、C
4、D
A、各个函数是在自己的局部范围内的,用相同的名字也不冲突,A是正确的说法;B、内存分为栈区(放置局部变量、函数形参)、堆区(动态内存分配的 malloc/free calloc realloc)以及静态区(放置全局变量),B选项正确;C选项正确,就是说的作用域问题;D项错误,看下面的代码:

void test()
{
	{
		int a = 10;
	}
	printf("%d\n",a);//err
}
int main()
{
	return 0;
}

想要在test函数里面打印a是打印不了的,因为a在它自己的大括号范围内
5、A
A选项,直接一起返回两个数字是不可能的,return 1,2;?,这样肯定是不对的,return只能返回一个数字。
6、C
7、B
A、有的函数它不需要返回;B、实参和形参的名字可以是相同的;D、主调函数和被调函数不一定是同一个文件,其它文件里的想用就包含一下或者声明一下也是可以用的。
8、B
A、可以这么做,但是要声明;C、不声明会报错;D、函数的声明只是声明函数名、函数参数以及函数的返回类型,关于它是怎么实现的对于函数的声明是不重要的。
9、C
C选项:形参和实参是两块不同的空间,改变形参不会影响实参。
10、B
(v1,v2)是逗号表达式,由逗号隔开的语句称为逗号表达式,逗号表达式会从左到右依次计算,整个逗号表达式的结果是最后一个表达式的结果,所以该式子的结果的v2的结果;
那么整条语句就相当于是:exec((v1,v2),(v3,v4),v5,v6);—》exec(v2,v4,v5,v6);,里面有四个实参
12、C
13、D
补全代码,可以做一下验证

int Fun(int n)
{
	if (n == 5)
		return 2;
	else 
		return 2 * Fun(n + 1);
}
int main()
{
	printf("%d\n", Fun(2));
	return 0;
}

得到的结果是16.
在这里插入图片描述
栈区:局部变量、函数参数、调用函数时返回值等临时的变量都是在栈区存放的;堆区是用来进行动态内存分配的;静态区是用来存放全局变量、全局变量的
每一次的函数调用都会在内存中申请栈区上的空间。执行程序的main函数的时候,就会在栈区申请一块空间,main函数调用Fun函数,就会在栈区为Fun函数开辟一块空间,un函数内部又调用了Fun函数,就再次给Fun函数开辟一块空间,当递归不再继续的时候,就开始返回了,返回的时候,返回一次,为Fun开辟的空间就销毁一个,直到回到main函数的时候,之前为Fun函数开辟的空间就都还给操作系统了,栈空间就又腾出来了。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值