当前位置 博文首页 > HyDraZya的博客:【C语言基础】初步理解函数
目录
一、C语言中函数的分类
二、自定义函数
三、函数的参数?
四、函数的调用
????????练习
五、函数的嵌套调用和链式访问
????????嵌套调用
????????链式访问
六、函数的声明和定义
????????函数声明
????????函数定义
七、函数递归
????????练习
????????递归与迭代
1.库函数
2.自定义函数
函数放在main函数之前,不用+声明
C语言常用的库函数
strcpy:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "bit";
char arr2[20] = "############";
// bit->bit\0#########由于\0是结束标志所以后面的#不打印
strcpy(arr2, arr1);
printf("%s\n", arr2);
//strlen - string length - 字符串长度
//strcpy - string copy - 字符串拷贝
return 0;
}
memset:
memory(内存) +set(设置)
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "hello world";
memset(arr, '*', 5);
//'*'存入的数组的是ACSll码值,42,也是也是一个整型
printf("%s\n", arr);
return 0;
}
函数的组成:
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
例子:
#include <stdio.h>
//get_max函数的设计
int get_max(int x, int y)
{
if(x>y)
return x;
else
return y;
}
int main()
{
int a = 10;
int b = 20;
int max = get_max(a, b);
printf("max = %d\n", max);
return 0;
}
?用一个函数交换两个整型:
#include <stdio.h>
void Swap1(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
void Swap2(int* px, int* py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("a = %d b = %d\n", a, b);
Swap1(a, b);
//调用Swap1函数-传值调用
Swap2(&a, &b);
//调用Swap2函数-传址调用
printf("a = %d b = %d\n", a, b);
return 0;
}
实际参数(实参):
真是传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数两用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
?上面Swap1和Swap函数中的参数x. y. px. py都是形式参数。在mian函数中传给Swap1的num1,num2和传给Swap2函数的&num1,&num2是实际参数
传值调用:
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用
注:传值函数需要的只是最终的一个结果值,而传址函数才需要的是对实参进行一些实际操作,如交换
1. 写一个函数可以判断一个数是不是素数
#include <stdio.h>
#include <math.h>
//是素数返回1,不是素数返回0
int is_prime(int n)
{
//2->n-1
int j = 0;
for(j=2; j<=sqrt(n); j++)
{
if(n%j == 0)
return 0;
}
//if(j == n)
return 1;
}
int main()
{
int i = 0;
for(i=100; i<=200; i++)
{
//判断i是否为素数
if(is_prime(i) == 1)
printf("%d ", i);
}
return 0;
}
2. 写一个函数判断一年是不是闰年
#include <stdio.h>
int is_leap_year(int y)
{
if((y%4 == 0 && y%100 != 0) || (y%400 == 0))
return 1;
else
return 0;
}
int main()
{
int year = 0;
for(year= 1000; year<=2000; year++)
{
//判断yaer是否为闰年
if(1 == is_leap_year(year))
{
printf("%d ", year);
}
}
return 0;
}
3. 写一个函数,实现一个整形有序数组的二分查找
#include <stdio.h>
//本质上arr是一个指针
int binary_search(int arr[], int k, int sz)
{
//算法的实现
int left = 0;
int right = sz-1;
while(left<=right)
{
int mid = (left+right)/2;//中间元素的下标
if(arr[mid] < k)
{
left = mid-1;
}
else if(arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
//二分查找
//在一个有序数组中查找具体的某个数
//如果找到了返回,这个书的下标。找不到的返回-1
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int k = 7;
int sz = sizeof(arr)/sizeof(arr[0]);
//传递过去的是 arr[] 首元素的地址
int ret = binary_search(arr, k, sz);
if(ret == -1)
{
printf("找不到制定的数字\n");
}
else
{
printf("找到了,下标是:%d\n",ret);
}
return 0;
}
4. 写一个函数,每调用一次这个函数,就会将num的值增加1
#include <stdio.h>
void Add(int* p)
{
(*p)++;
}
int main()
{
int num = 0;
Add(&num);
printf("num = %d\n", num);
Add(&num);
printf("num = %d\n", num);
Add(&num);
printf("num = %d\n", num);
return 0;
}
函数和函数之间可以有机的组合的。
#include <stdio.h>
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for(i=0; i<3; i++)
{
new_line();
}
}
int main()
{
three_line();
getchar();
return 0;
}
把一个函数的返回值作为另外一个函数的参数。
#include <stdio.h>
#include <string.h>
int main()
{
//1
int len = 0;
len = strlen("abc");
printf("%d\n", len);
//2
printf("%d\n", strlen("abc"));
getchar();
return 0;
}
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43))); //4321
//打印顺序为从右括号最内的向左进行打印
//1.首先打印出43,
//2.因为43是2位数所以返回值为2,第二次打印2在43的后面,即此时为432
//3.又因为2是1位数所以返回值为1,第三次1打印在2的后面,所以最后打印结果为4321
return 0;
}
函数的定义是指函数的具体实现,交待函数的功能实现
头文件.h放函数声明,源文件.c放函数的定义,在配合函数调用多个文件运行
#ifndef -if not define
#define
#endif
递归函数:一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。
递归函数的主要思考方式在于——把大事化小
递归的两个必要条件:
递归常见错误:栈溢出
(1)接受一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:1234,输出 1 2 3 4
#include <stdio.h>
void print(int n)
{
if(n>9)
{
print(n/10);
}
printf("%d ", n%10);
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
print(num);
return 0;
}
(2)编写函数:不允许创建临时变量,求字符串的长度
while写法:
#include <stdio.h>
#include <string.h>
int my_strlen(char* str)
//str是指针变量
{
int count = 0;
while(*str != '\0')
{
count++;
str++;
//指针+1即指针指向下一个地址
}
return count;
}
int main()
{
char arr[] = "bit";
int len = my_strlen(arr);//arr是数组,数组传参,传过去的不是整个数组,而是第一个元素的地址
printf("len = %d", len);
return 0;
}
递归写法:
#include <stdio.h>
#include <string.h>
int my_strlen(char* str)
{
if(*str != '\0')
return 1+my_strlen(str+1);
else
return 0;
}
int main()
{
char arr[] = "bit";
int len = my_strlen(arr);//arr是数组,数组传参,传过去的不是整个数组,而是第一个元素的地址
printf("len = %d", len);
getchar();
return 0;
}
(3)求n的阶乘。(不考虑溢出)
while写法:
#include <stdio.h>
int Fac1(int n)
{
int i = 0;
int ret = 1;
for(i=1; i<=n; i++)
{
ret *= i;
}
return ret;
}
int main()
{
//求n的阶乘
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fac1(n);//循环的方式
printf("%d\n", ret);
return 0;
}
递归写法:
int Fac2(int n)
{
if(n<=1)
return 1;
else
return n*Fac2(n-1);
}
int main()
{
//求n的阶乘
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fac2(n);//循环的方式
printf("%d\n", ret);
return 0;
}
(4)求第n个斐波那契数。(不考虑溢出)
递归写法:
#include <stdio.h>
#include <stdlib.h>
int Fib(int n)
{
if(n<=2)
return 1;
else
return Fib(n-1)+Fib(n-2);
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
//TDD - 测试驱动开发
ret = Fib(n);
printf("ret = %d\n", ret);
return 0;
}
while循环:
#include <stdio.h>
int count = 0;
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while(n>2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fib(n);
printf("ret = %d\n", ret);
return 0;
}
cs