c语言鹏哥学习笔记(函数)

目录

函数

库函数

----strcpy

----memset内存设置

自定义函数

----交换两个变量的值(指针)(传址调用)

参数类型

函数的调用----传值调用与传址调用

----判断一个数是不是素数(函数)

----二分查找(函数)传数组

函数地嵌套使用和链式访问

嵌套使用

链式访问

函数的声明和定义

----函数的声明一般放在头文件中(分模块)

函数递归

----输入1234,输出1 2 3 4

递归两个必要条件

栈区、堆区

----求字符串长度

--------用了局部变量,指针后移

----没用局部变量(函数递归)

----求n的阶乘

----求第n个斐波那契数列

--------不用递归 斐波那契

----1到100的整数中间有多少个9

----计算1/1+1/2+1/3..........+1/100

----求10个数中最大值

----九九乘法表%2d

打印乘法口诀表(函数,行列自己指定)

 ----字符串逆序

--------正常

--------递归

 ----输入一个非负数 计算他的各位数字之和

----题的零碎知识点

--------逗号表达式


函数

函数分为:库函数  自定义函数

debug调试版本   release发布版本

库函数

io函数  输入输出函数  printf   scanf  getchar   putchar

字符串操作函数    strcmp   strlen

字符操作函数        toupper

内存操作函数       memcpy memcmp memset

时间/日期函数     time

数学函数   

其他库函数

----strcpy

strcpy(arr1,arr2) 

arr2内容放到arr1中

----memset内存设置

memset(arr,'x',5)   把arr前5个空间设置为x

自定义函数

函数名   返回值类型  函数参数

--------------------------------------------------

函数返回值类型    函数名(参数)      //无返回值用void

{

语句项

}

----------------------------------------------------

int get_max(int a, int b)
{
	if (a > b)
	{
		return a;
	}
	else
	{
		return b;
	}
}

int main()
{
	int a = 98;
	int aa = 8;

	int max = get_max(a, aa);
	printf("%d", max);
	return 0;
}

----交换两个变量的值(指针)(传址调用)

函数(传入的只是函数的值)

指针取地址改变外部变量

例:(交换两个变量的值)

void swp(int* x, int* y)//存放的是指针
{
	int t = 0;
	t = *x;
	*x = *y;
	*y = t;
}

int main()
{
	int a = 8;
	int b = 9;
	printf("%d %d\n", a, b);
	swp(&a, &b);//穿的是地址
	printf("%d %d", a, b);
	return 0;
}

参数类型

函数(实参

实参:真实传递给函数的参数   可以是常量,变量,表达式,函数等

不管是什么,必须要有确定的值

定义部分

返回值类型  函数名(形参

形参:函数调用完自动销毁

函数的调用----传值调用与传址调用

----判断一个数是不是素数(函数)

函数最好还是用返回值(不要打印)

//判断一个数是不是素数----函数
int panduan(int a)
{
	int i = 0;
	for (i = 2; i < a; i++)
	{
		if (a%i==0)
		{
			return 0;
		}
	}
	return 1;//不要打印,功能细分
}

一个函数不写返回类型默认返回int类型

----二分查找(函数)传数组

//二分查找(函数)

int two(int a[],int k,int z)//传数组,形参定义时左半
{
	int left = 0;
	int right = z - 1;//为什么要在里面定义?
	

	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (a[mid] ==k )
		{
			return mid ;
		}
		else if (k < a[mid])
		{
			right = mid - 1;
		}
		else if (k > a[mid])
		{
			left = mid + 1;
		}
	}
	if (left > right)
	{
		return -1;
	}
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10};

	int key = 0;//要查找的数
	printf("输入要查找的数->");
	scanf("%d", &key);

	int sz = sizeof(arr) / sizeof(arr[0]);

	int ii = two(arr, key, sz);
	if(ii!=-1)
	{
		printf("找到了,下标[%d]",ii);
	}
	else
	{
		printf("找不到");
	}
	return 0;
}

sz 要传值过去原因

参数arr 传过去的只是数组第一个元素的地址   sizeof等操作不能正确进行

函数地嵌套使用和链式访问

嵌套使用

不能嵌套定义,能嵌套调用

int test1()

{

test3();

}

链式访问

把一个函数返回值作为另一个函数的参数

test1(test2())

printf("%d", printf("%d", printf("%d", 43)));

输出4321

printf()返回值是输出字符的个数

函数的声明和定义

编译器从前到后扫描

当函数定义在后面时,要先声明后使用

int main()
{
	int a = 1;
	int b = 9;
	int add(int, int);//函数的声明

	int c = add(a, b);
	printf("%d", c);
	return 0;
}
add(int a, int b)
{
	return a + b;
}

函数的声明

函数类型 函数名(参数类型)(也可以加上参数名)

int add(int,int)

----函数的声明一般放在头文件中(分模块)

项目一般分模块 

一个模块函数的声明放头文件中.h,函数的本体放.c中

调用时在主函数前    

#include "函数名"  

例:

计算器的加法模块

代码放add.c   声明放头文件add.h 调用在test.c中

#include " add.h"

卖代码,不想让别人知道代码内容(了解即可)

右击解决方案下面的,改为静态库

 运行  到Debug路径下 .lib文件就是静态库

卖家使用

买了一个  .h  .lib

.lib放项目路径下

----导入静态库

#pragma comment(lib,"sub.lib")

                                    静态库名字

函数递归

函数直接或间接调用自己的一种方法

大事化小

----输入1234,输出1 2 3 4

思路: 先输出最高位的 一直/10 当<10 时%10  依次递归

void print_han(int a)
{
	if (a > 9)
	{
		print_han(a / 10);
	}
	printf("%d  ", a % 10);
}

int main()
{
	int a = 0;
	scanf("%d", &a);
	print_han(a);

	return 0;
}

递归两个必要条件

存在条件限制,当满足这个限制条件的时候,递归便不再继续

每次递归调用之后越来越接近这个限制条件

栈区、堆区

 每次函数调用都要在栈区调用空间

递归太深就会栈溢出

----求字符串长度

编写函数,不用局部变量求字符串长度

--------用了局部变量,指针后移

思路:字符串结尾'\0'

*str 指针   str++指针后移

//求字符串长度
int my_strlen(char* arr)//相当于接受了一个元素的地址
{
	int count = 0;

	while (*arr != '\0')//这是字符,不是字符串可不用strcmp
	{
		arr++;//指针后移
		count++;
	}
	return count;
}


int main()
{
	char arr[20] = { 0 };
	scanf("%s", arr);

	int a=my_strlen(arr);//传入的是arr首元素的地址

	printf("\n%d", a);
	return 0;
}

----没用局部变量(函数递归)

思路:

限制条件:结尾是否为 \0

每次接近:指针后移(str+1)

int my_strlen(char * arr)
{
	if (*arr!='\0')
	{
		return 1 + my_strlen(arr + 1);//不用arr++是因为其是先++后使用
	}
	else
	{
		return 0;
	}
}

int main()
{
	char arr[20] = { 0 };
	scanf("%s", arr);
	
	printf("   %d", my_strlen(arr));
	return 0;
}

----求n的阶乘

限制条件:a>0

接近:a-1

//求n的阶乘
int jie(int a)
{
	if (a > 0) 
	{
		return a * jie(a - 1);
	}
	else
	{
		return 1;
	}
}

int main()
{
	int a = 0;
	scanf("%d", &a);

	printf(" %d",jie(a));
	return 0;
}

----求第n个斐波那契数列

1  1  2  3  5  后面的数等于前面两个数的和

限制条件:第一个  第二个为1

接近:n-1

//斐波那契数列
int feibo(int a)
{
	if (a == 1 ||a==2)
	{
		return 1;
	}
	else
	{
		return feibo(a - 1) + feibo(a - 2);
	}

}

int main()
{
	int a = 0;
	scanf("%d", &a);
	printf("第%d个斐波那契数是%d", a, feibo(a));

	return 0;
}

效率低,大数要计算好几分钟

--------不用递归 斐波那契

1     1     2    3    5    8    13     21    34    55

 |      |      | 

a      b     c

原理:a=1   b=1

c=a+b      一直向前推进

//斐波那契数列(不用递归 效率高)
int feibo(int n)
{
	int a = 1;//前面的指针
	int b = 1;//后面的
	int c = 1;
	while (n > 2)//n为1,2时.c为1
	{
		c = a + b;
		a = b;
		b = c;//前移

		n--;//控制次数
	}

	return c;
}

int main()
{
	int n = 0;
	scanf("%d",&n);

	printf("第%d个斐波那契数是%d", n,feibo(n));
	return 0;
}

n-- 原因:当n为3时,计算一次    n>3时,需要计算n-2次

正好n>2退出

数字太大会错,(因为整型下放不下这么大的数)

----1到100的整数中间有多少个9

//1到100有多少个整数9
int main()
{
	int count = 0;
	int i = 0;
	for (i = 1; i <= 100; i++)
	{
		if (i%10==9)//个位数是9
		{
			count++;
		}
		if (i/10==9)//十位是9
		{
			count++;
		}
	}

	printf("%d", count);
	return 0;
}

----计算1/1+1/2+1/3..........+1/100

//计算1/1+1/2+....1/100
int main()
{
	int i = 0;
	double he = 0;

	for (i = 1; i <= 100; i++)
	{
		he = he + 1.0 / i;//1.0防止整数除法结果只有整数
	}

	printf("%lf", he);
	return 0;
}

加减交替

int main()
{
	int i = 0;
	double he = 0;
	int flag = 1;

	for (i = 1; i <= 100; i++)
	{
		he = he + 1.0*flag / i;//1.0防止整数除法结果只有整数
		flag = -flag;
	}

	printf("%lf", he);
	return 0;
}

加上一个flag

----求10个数中最大值

//求十个数中的最大值
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int i = 0;
	int max = arr[0];//

	for (i = 0; i <= 9; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}

	printf("%d", max);
	return 0;
}

注意比较数max要用数组内的数(如果max开始就比数组内所有数都大,比较失败)

----九九乘法表%2d

int main()
{
	int i = 1;
	int ii = 1;
	for (i = 1; i <= 9; i++)
	{
		for (ii = 1; ii <= i; ii++)
		{
			printf("%d*%d=%d ", i, ii, i * ii);
		}
		printf("\n");
	}

	return 0;
}

要<=i  防止1*9  9*1  等同时存在

%2d(强制打印2个,不够用空格代替)

%2d(同上,不过不得空格在右边)

打印乘法口诀表(函数,行列自己指定)

void print_c(int n)
{
	int i = 0;
	int ii = 0;
	for (i = 1; i <= n; i++)
	{
		for (ii = 1; ii <= i; ii++)
		{
			printf("%d*%d=%-2d ", ii, i, i * ii);
		}
		printf("\n");
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);

	print_c(n);
	return 0;
}

 ----字符串逆序

--------正常

//字符串逆序实现
int my_sizeof(char* str1)
{
	int count = 0;
	while (*str1!='\0')
	{
		count++;
		str1++;
	}
	return count;
}

void reverse_str(char* str)
{
	int left = 0;
	int right = my_sizeof(str)-1;

	while (left <= right)
	{
		char tmp = str[right];
		str[right] = str[left];
		str[left] = tmp;
		left++;
		right--;
	}
	printf("%s", str);
}

int main()
{
	char arr[] = "abcdefgh";
	reverse_str(arr);//reserve是保留;reverse是相反

	return 0;
}

--------递归

a b c d e f

传入的指针指向a  交换af  f处暂时放上\0(递归为一个字符串)  递归  f处放上f的值

//字符串逆序
int my_strlen(char* ar)
{
	int count = 0;
	while (*ar != '\0')
	{
		ar++;
		count++;
	}
	return count;
}

void re_str(char* str)
{
	int sz = my_strlen(str);
	char tmp = *(str);
	*str = *(str + sz - 1);//最后一个元素
	*(str + sz - 1) = '\0';
	if (my_strlen(str+1) != 0)
	{
		re_str(str + 1);
	}
	*(str + sz - 1) = tmp;

}

int main()
{
	char arr[] = "abcdefg";
	re_str(arr);

	printf("%s", arr);
	return 0;
}

 ----输入一个非负数 计算他的各位数字之和

//输入非负数字计算各位之和
int sum(int a)
{
	if (a>9)
	{
		return sum(a / 10)+(a%10);
	}
	return a;
}

int main()
{
	int a = 0;
	scanf("%d", &a);

	printf("%d", sum(a));
	return 0;
}

----题的零碎知识点

return只能返回一个数     return1,2 起不到效果

函数必须先声明,再使用

exec((v1,v2),(v2,v3),v5,v6)中实参的个数是

--------逗号表达式

(v1,v2)这叫做逗号表达式  从左到右计算,最后一个表达式的结果是表达式的值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值