函数
- 在计算机科学中,函数又被称为子程序。子程序指的是一个大型程序中的某部分代码,由一个或多个语句块组成,它负责完成某项特定的任务,并且相较于其他代码而言,函数更具有相对独立性。
- 函数一般会有输入参数及返回值,并且提供了对过程的封装和对细节的隐藏。这些代码通常被集成为软件库。
- C语言中对于函数有两种分类: 1. 库函数;2.自定义函数。
- 实际参数(实参):实际传递给函数的参数叫做实参;实参可以是常量,变量,表达式,函数等。无论参数是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
- 形式参数(形参):形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用时才会实例化【分配内存单元】,所以叫形式参数。形式参数在函数调用完成之后就自动销毁,因此形式参数只在函数中有效。形参实例化之后相当于实际参数的一份临时拷贝。
库函数
- 在进行开发的过程中,总有部分用于封装基础性功能的函数会被程序员频繁调用,C语言为了支持其程序的可移植性和提高程序员编写程序的效率,便在其基础库中提供了一系列库函数,以便于程序员进行软件开发。
- 语言中提供的函数基本上可以概括为:1.IO函数(scanf,printf,getchar,putchar);2.字符串操作函数;3.字符操作函数;4.内存函数;5.日期/时间函数;6.数学函数;7,其他库函数;
- 库函数的使用必须包含其对应的头文件
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello world!";
strcpy(arr1, arr2);
char * ret = strcpy(arr1, arr2);//ret接收的是目标空间里所接收字符的起始位置
printf("%s\n", arr1);
printf("%s\n", ret);//字符串的打印只需要提供起始位置即可,打印到\0自动停止
return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
char arr[20] = "hello world!";
printf("%s\n", arr);
memset(arr,'x', 5);
printf("%s\n", arr);
return 0;
}
自定义函数
- 自定义函数与库函数一样,都需要函数名,函数参数,返回值类型。
- 传值调用:函数的实参和形参分别占用不同的内存块,对形参的修改不会影响实参。
- 传址调用:1.传址调用是把函数外部创建的变量的内存地址传递给函数形参的一种调用函数的方式。
2.这种传参方式可以让函数和函数外部的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
//写一个函数输出两个数中的较大值
#include <stdio.h>
int get_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int c = get_max(a, b);
printf("%d\n", c);
return 0;
}
//写一个函数输出两个数中的较大值
#include <stdio.h>
int get_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 0;
int b = 0;
int c = get_max(3, 4);
printf("%d\n", c);
return 0;
}
//写一个函数输出两个数中的较大值(数值表达式)
#include <stdio.h>
int get_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 0;
int b = 0;
int c = get_max(3+7, 4);
printf("%d\n", c);
return 0;
}
//写一个函数输出两个数中的较大值(逗号表达式)
include <stdio.h>
int get_max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 0;
int b = 0;
int c = get_max(get_max(3,7), 4);
printf("%d\n", c);
return 0;
}
//调用函数在屏幕上打印一个字符串
#include <stdio.h>
void test(void)
//前一个void指的是调用函数后无需返回,后一个void指的是这个函数没有参数,在调用时不能传参
{
printf("新春快乐!");
}
int main()
{
test();
return 0;
}
//交换两个变量中的数值
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a = %d,b = %d\n", a, b);
int tmp = 0;
tmp = a;
a = b;
b = tmp;
printf("交换后:a = %d,b = %d\n", a, b);
return 0;
}
//写一个函数交换两个变量中的数值
#include <stdio.h>
void Swap(int* pa, int* pb)
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a = %d,b = %d\n", a, b);
Swap(&a, &b);
printf("交换后:a = %d,b = %d\n", a, b);
return 0;
}
//使用函数的方式输出100--200之间的素数
#include <stdio.h>
#include <math.h>
int is_prime(int i)
{
int j = 0;
for (j = 2; j <= sqrt(i); j++)
{
if (i % j == 0)
{
return 0;
}
}
return 1;
}
int main()
{
int i = 0;
for (i = 100; i <= 200; i++)
{
if (is_prime(i) == 1)
{
printf("%d ", i);
}
}
return 0;
}
//使用函数的方式输出1000--2000年之间的闰年
#include <stdio.h>
int is_leap_year(int num)
{
if (num % 4 == 0 && num % 100 != 0)
{
return 1;
}
if(num % 400 == 0)
{
return 1;
}
return 0;
}
int main()
{
int num = 0;
for (num = 1000; num <= 2000; num++)
{
if (is_leap_year(num) == 1)
printf("%d ", num);
}
return 0;
}
//使用函数的方式输出1000--2000年之间的闰年
#include <stdio.h>
int is_leap_year(int x)
{
if (((x % 4 == 0) && (x % 100 != 0)) || (x % 400 == 0))
return 1;
else
return 0;
}
int main()
{
int i = 0;
for (i = 1000; i <= 2000; i++)
{
if (is_leap_year(i))
printf("%d ", i);
}
return 0;
}
//使用函数的方式输出1000--2000年之间的闰年
#include <stdio.h>
int is_leap_year(int x)
{
return (((x % 4 == 0) && (x % 100 != 0)) || (x % 400 == 0));
}
int main()
{
int i = 0;
for (i = 1000; i <= 2000; i++)
{
if (is_leap_year(i))
printf("%d ", i);
}
return 0;
}
//使用函数的方式完成对一个有序数组的二分查找
#include <stdio.h>
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()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int k = 7;
int pos = binary_search(arr, k, 10);
if(-1 == pos)
{
printf("找不到。\n");
}
else
{
printf("找到了,下标为:%d\n",pos);
}
return 0;
}
//使用函数的方式完成对一个有序数组的二分查找
#include <stdio.h>
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 (mid < k)
{
left = mid + 1;
}
else if (mid > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,17,18,19,20,21 };
int sz = sizeof(arr)/ sizeof(arr[0]);
int k = 21;
int pos = binary_search(arr, k, sz);
if (pos == -1)
printf("找不到");
else
{
printf("找到了,下标为:%d\n", pos);
}
return 0;
}
//利用指针变量远程控制主函数内创建的变量
#include <stdio.h>
void Add(int* p)
{
*p = *p + 1;
}
int main()
{
int num = 0;
Add(&num);
printf("%d\n", num);//1
Add(&num);
printf("%d\n", num);//2
Add(&num);
printf("%d\n", num);//3
return 0;
}
//利用指针变量远程控制主函数内创建的变量
#include <stdio.h>
void Add(int* p)
{
(*p)++;
}
int main()
{
int num = 0;
Add(&num);
printf("%d\n", num);
Add(&num);
printf("%d\n", num);
Add(&num);
printf("%d\n", num);
return 0;
}
函数的嵌套调用和链式访问
1、函数与函数之间可以根据实际情况进行组合,也就是相互调用。
2、函数可以嵌套调用,但是不可以嵌套定义。
#include <stdio.h>
void line(void)
{
printf("hehe\n");
}
void three_line(void)
{
int i = 1;
for (i == 1; i <= 3; i++)
{
line();
}
}
int main()
{
three_line();
return 0;
}
#include<stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43))); //4321
printf("%d", printf("%d ", printf("%d", 43))); //4322
return 0;
}
#include <stdio.h>
int Add(int a, int b); //函数声明
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int ret = Add(a, b);
printf("%d\n", ret);
return 0;
}
int Add(int a, int b)
{
return(a + b);
}
#include <stdio.h>
int Add(int a, int b)
{
return(a + b);
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int ret = Add(a, b);
printf("%d\n", ret);
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();
return 0;
}
#include <stdio.h>
int main()
{
printf("%d",printf("%d",printf("%d",43)));
//4321.printf函数返回的是在屏幕上打印的字符的个数
return 0;
}
函数的声明
函数的声明是用于告知编译器有一个函数,函数名是什么,参数是什么,返回类型是什么。但该函数是否真实存在,函数声明无法决定。
函数声明一半出现在函数出现之前,要满足先声明后定义的原则。
函数的声明一般放于头文件中。
#include <stdio.h>
int Add(int x, int y);
int main()
{
int a = 0;
int b = 0;
scanf("%d %d",&a,&b);
int ret = Add(a,b);
printf("%d\n",ret);
return 0;
}
int Add(int x, int y)
{
return x + y;
}
函数的定义
函数的定义是指函数的具体实现,用于交代函数的功能实现。
函数的定义是一种特殊的函数声明。
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d",&a,&b);
int ret = Add(a,b);
printf("%d\n",ret);
return 0;
}
函数递归
什么是递归?
程序调用自身的编程技巧称为递归。
递归作为一种算法在程序设计语言中被广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
递归策略:只需少量的程序就可描述出结题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小。
递归的两个必要条件:
1、存在限制条件时,当满足这个限制条件的时候,递归便不再继续。
2、每次递归调用之后越来越接近这个限制条件。
#include <stdio.h>
void Print(unsigned int n)
{
if(n > 9)
{
Print(n / 10);
}
printf("%d ",n % 10)
}
int main()
{
unsigned int num = 0;
scanf("%u",&num);
Print(num);
return 0;
}
//写一个函数求字符串的长度。
//非递归方式实现strlen库函数的功能
#include <stdio.h>
int my_streln(char* str)
{
int count = 0;
while (*str != 0)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int len = my_streln(arr);
printf("%d\n", len);
return 0;
}
//递归方式实现strlen库函数的功能
#include<stdio.h>
int my_streln(char* str)
{
if (*str != 0)
{
return 1 + my_streln(str + 1);
}
else
return 0;
}
int main()
{
char arr[] = "abcdef";
int len = my_streln(arr);
printf("%d\n", len);
return 0;
}
//用递归的方式求第n个斐波那契数
#include <stdio.h>
int Fib(int n)
{
if(n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d",&n);
int ret = Fib(n);
printf("%d\n",ret);
return 0;
}
#include <stdio.h>
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;
scanf("%d",&n);
int ret = Fib(n);
printf("%d\n",ret)
return 0;
}
//先写一个函数reverse_string实现字符数组内的内容交换
#include<stdio.h>
void reverse_string(char arr[])
{
int l = 0;
int r = strlen(arr) - 1;
while (l < r)
{
char tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
l++;
r--;
}
}
int main()
{
char arr[] = "abcdef";
reverse_string(arr);
printf("%s", arr);
return 0;
}
//先写一个函数reverse_string实现字符数组内的内容交换
#include <stdio.h>
void reverse_string(char* str)
{
int l = 0;
int r = strlen(str) - 1;
while (l < r)
{
char tmp = *(str + l);
*(str + l) = *(str + r);
*(str + r) = tmp;
l++;
r--;
}
}
int main()
{
char arr[] = "abcdef";
reverse_string(arr);
printf("%s\n", arr);
return 0;
}
//先写一个函数reverse_string实现字符数组内的内容交换
#include <stdio.h>
int Strlen(char* str)
{
int count = 0;
while(*str != '\0')
{
count++;
str++;
}
return count;
}
void reverse_string(char* str)
{
int l = 0;
int r = Strlen(str) - 1;
while (l < r)
{
char tmp = *(str + l);
*(str + l) = *(str + r);
*(str + r) = tmp;
l++;
r--;
}
}
int main()
{
char arr[] = "abcdef";
reverse_string(arr);
printf("%s\n", arr);
return 0;
}
//先写一个函数reverse_string实现字符数组内的内容交换
#include <stdio.h>
int Strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
void reverse_string(char* str)
{
int len = Strlen(str);
char tmp = *str;
*str = *(str + len - 1);
*(str + len - 1) = '\0';
if (Strlen(str + 1) >= 2)
reverse_string(str + 1);
*(str + len - 1) = tmp;
}
int main()
{
char arr[] = "abcdef";
reverse_string(arr);
printf("%s\n", arr);
return 0;
}