函数
什么是函数? 通俗易懂的来说,函数就是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
C语言函数的分类: 库函数 、自定义函数
库函数: 存放在函数库中的函数。库函数具有明确的功能、入口调用参数和返回值。C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。
库函数
库函数的分类: (1)I/O 函数。包括各种控制台I/O、缓冲型文件I/O和UNIX式非缓冲型文件I/O操作。 需要的包含文件:stdio.h 例如: getchar,putchar,printf,scanf,fopen,fclose,fgetc,fgets,fprintf,fsacnf,fputc,fputs,fseek,fread,fwrite等。 (2)字符串、内存和字符函数。包括对字符串进行各种操作和对字符进行操作的函数。 需要的包含文件:string.h、mem.h、ctype.h或string.h 例如:用于检查字符的函数:isalnum,isalpha,isdigit,islower,isspace等。用于字符串操作函数:strcat,strchr,strcmp,strcpy,strlen,strstr等。 (3)数学函数。包括各种常用的三角函数、双曲线函数、指数和对数函数等。 需要的包含文件:math.h 例如:sin,cos,exp(e的x次方),log,sqrt(开平方),pow(x的y次方)等。 (4)时间、日期和与系统有关的函数。对时间、日期的操作和设置计算机系统状态等。 需要的包含文件:time.h 例如:time返回系统的时间;asctime返回以字符串形式表示的日期和时间。 (5)动态存储分配。包括"申请分配"和"释放"内存空间的函数。 需要的包含文件:alloc.h或stdlib.h 例如:calloc,free,malloc,realloc等。 (6)目录管理。包括磁盘目录建立、查询、改变等操作的函数。 (7)过程控制。包括最基本的过程控制函数。 (8)字符屏幕和图形功能。包括各种绘制点、线、圆、方和填色等的函数。 (9)其它函数。
在学习库函数,我们可以使用 http://www.cplusplus.com/reference/ 这个网站进行库函数的相关学习。
下面我们举两个常见的库函数的例子:
strcpy
char * strcpy ( char * destination, const char * source );
int main()
{
char arr1[20] = { 0 };
char arr2[10] = "hello bit";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
memset
void * memset ( void * ptr, int value, size_t num );
int main()
{
char arr[] = "hello bit";
memset(arr, 'x', 5);
printf("%s\n", arr);
return 0;
}
但是库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件。
自定义函数
自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是自定义函数都是程序员自己来设计。
函数的组成:
ret_type fun_name(para1, * )
{
statement;
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
举例:写一个函数可以找出两个整数中的最大值。 示例1:
int get_max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int a = 10;
int b = 20;
int max = get_max(a, b);
printf("%d\n", max);
return 0;
}
举例:写一个函数可以交换两个整形变量的内容。 示例2:
void swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("%d\n", a);
printf("%d\n", b);
swap(&a, &b);
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
函数的参数
实际参数: 真实传给函数的参数,叫实参。 实参可以是:常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。 形式参数: 形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。 注意: 形参实例化之后其实相当于实参的一份临时拷贝。
函数的调用
传值调用 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。 传址调用 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。 牛刀小试: 1.写一个函数可以判断一个数是不是素数。
int is_prime(int n)
{
int j = 0;
for (j = 2; j < n; j++)
{
if (n%j == 0)
{
return 0;
}
}
return 1;
}
int main()
{
int i = 0;
int count = 0;
for (i = 100; i <= 200; i++)
{
if (is_prime(i) == 1)
{
count++;
printf("%d ", i);
}
}
printf("%d\n", count);
return 0;
}
- 写一个函数判断一年是不是闰年。
int is_leap_year(int n)
{
if (n % 4 == 0 && n % 100 != 0 || n % 400 == 0)
{
return 1;
}
return 0;
}
int main()
{
int y = 0;
int count = 0;
for (y = 1000; y <= 2000; y++)
{
if (is_leap_year(y) == 1)
{
printf("%d是闰年!\n",y);
count++;
}
}
printf("%d\n", count);
return 0;
}
- 写一个函数,实现一个整形有序数组的二分查找。
int bin_search(int a[],int k,int s)
{
int left = 0;
int right = s - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (a[mid] > k)
{
right = mid - 1;
}
else if (a[mid]<k)
{
left = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int key = 7;
int sz = sizeof(arr) / sizeof(arr[0]);
int ret = bin_search(arr,key,sz);
if (ret == -1)
{
printf("找不到\n");
}
else
{
printf("找到了,下标是%d\n", ret);
}
return 0;
}
- 写一个函数,每调用一次这个函数,就会将num的值增加1。
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);
Add(&num);
printf("%d\n", num);
Add(&num);
printf("%d\n", num);
return 0;
}
函数的声明和定义
函数声明:
- 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
- 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
- 函数的声明一般要放在头文件中的。
int Add(int x,int y);
函数定义: 函数的定义是指函数的具体实现,交待函数的功能实现。
int Add(int x,int y)
{
return x+y;
}
递归
程序调用自身的编程技巧称为递归。 递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。 递归的主要思考方式在于:把大事化小。
递归的两个必要条件: 1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。 2.每次递归调用之后越来越接近这个限制条件。
递归练习 练习1: 接受一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:1234,输出 1 2 3 4.
void print(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;
}
练习2: 编写函数不允许创建临时变量,求字符串的长度。
模拟实现strlen函数(2种)
1.创建临时变量了,计数器的方法:
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
str++;
count++;
}
return count;
}
int main()
{
char arr[] = { "bit" };
printf("%d\n", my_strlen(arr));
return 0;
}
2.没有创建临时变量,递归的方法:
int my_strlen(char* str)
{
if(*str != '\0')
{
return 1 + my_strlen(str + 1);
}
else
{
return 0;
}
}
int main()
{
char arr[] = { "bit" };
printf("%d\n", my_strlen(arr));
return 0;
}
|