【C语言】函数----函数的分类、库函数详解(strcpy、memset)、自定义函数的实现(找较大值、交换两个数)

简介: 【C语言】函数----函数的分类、库函数详解(strcpy、memset)、自定义函数的实现(找较大值、交换两个数)

一.函数是什么

维基百科中对函数的定义:子程序

1.在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method,

subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组

成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。

2.一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软

件库。



二.C语言中函数的分类

1.库函数

2.自定义函数



1.库函数

1.库函数是c语言库内已经写好的函数,只要我们引入相应的头文件就可以直接使用,比如在编写完一个代码后想打印在屏幕上看看,这个时候我们会频繁的使用一个功能:将信息按照一定的格式打印到屏幕上(printf)。

2.我们会频繁的做一些字符串的拷贝工作(strcpy).

3.计算某个数的n次方(pow)。

像上面非业务性的代码,我们在编写代码的时候用的都比较频繁,为了支持可移植性和提高程序的效率,所以C语言的基础库(标准库)中提供了一系列类似的库函数,方便程序员进行软件开发。


C语言中常用的库函数有:

IO函数:即输入()input输出(output)函数

字符串操作函数:strlen、strcmp

字符操作函数:大小写转换、字符分类

内存操作函数:memcpy、memmove、memset…

时间/日期函数:time

数学函数:pow、sqrt

其他库函数

使用库函数必须要包含它所对应的头文件

接下来我们来学习几个常用的库函数,掌握库函数的使用方法:

(1)strcpy()

char * strcpy ( char * destination, const char * source );

以上是strcpy()函数的函数原型,具体包含了:

1.返回类型:char*

2.函数名:strcpy

3.函数参数及其类型:两个参数,类型均为char* ,const是一个修饰符,具体含义之后会有总结

strcpy()函数的功能:将source内的字符串拷贝到destination字符数组中,包含‘\0’.

用以下代码来演示:

#include <stdio.h>
#include <string.h>
int main()
{
  char arr1[20] = { 0 };
  char arr2[] = "hello world";
  printf("%s\n", arr1);//拷贝前arr1内为空,什么都没有
  //将arr2中的字符串拷贝到arr1中
  strcpy(arr1, arr2);//arr1就是destination,arr2就是source,都表示的是字符的首地址
  printf("%s\n", arr1);
  return 0;
}

具体的实现细节:


代码结果:


(2)memset()

void * memset ( void * ptr, int value, size_t num );

1.返回类型:void*

2.函数名:memset

3.函数参数及其类型:三个参数,类型分别为void* 、int、size_t

memset()函数的功能为:把ptr指向的这块空间的前num个字节的数据设置成value这个值。

如下参数介绍:


返回值介绍:

简单来说就是设置内存,把一个字符串原本的内容覆盖掉,设置成我们想要的字符,比如将hello的前三个字符设置成字符*,如下代码:

#include <stdio.h>
#include <string.h>
int main()
{
  char arr[20] = "hello";
  printf("%s\n", arr);//设置前
  memset(arr, '*', 3);
  printf("%s\n", arr);//设置后
  return 0;
}

代码结果:


2.自定义函数

作为一个程序员,其实更重要的是自定义函数,我们需要自己设计函数名、参数、返回类型,需要我们自己完成函数体的具体功能,比如我们写一个函数能够找出两个数的最大值:

(1)找较大值

#include <stdio.h>
int get_Max(int a, int b)
{
  //一般方法
  /*if (a > b)
  {
    return a;
  }
  else
  {
    return b;
  }*/
  return a > b ? a : b;//比较大小,当a大于b返回a,否则返回b
}
int main()
{
  int a = 0;
  int b = 0;
  printf("请输入两个数:>");
  scanf("%d %d", &a, &b);
  int ret = get_Max(a, b);
  printf("%d较大\n", ret);
  return 0;
}

这里我们自己输入两个整数,将这两个整数作为函数的参数,返回两个数中的较大值,所以函数的参数类型为整型,返回类型也为整型,用到了两种基本的方法,具体可以参照注释理解。

以5和10进行验证:


(2)void的意义

void在不同的地方究竟有什么不同的含义呢?我们观察以下代码:

#include <stdio.h>
void test(void)
{
  printf("hello\n");
}
int main()
{
  test();
  return 0;
}

其实很容易理解,其中第一个void表示的是该函数执行完后什么都不需要返回,第二个void表示该函数不需要、不能传任何参数。


(3)交换两个数

我们输入两个整数,调用一个函数后交换这两个数:

错误代码:

#include <stdio.h>
void Swap(int m, int n)
{
  int tmp = m;
  m = n;
  n = tmp;
}
int main()
{
  int a = 0;
  int b = 0;
  printf("请输入两个数:>");
  scanf("%d %d", &a, &b);
  printf("交换前:a=%d b=%d", a, b);
  Swap(a, b);
  return 0;
}

我们将两个数传过去后,再打印两个数发现并没有改变,我们的思路没有问题,但却没有实现相应的功能。

其实在这里我们要注意一点:当函数调用的时候,实参传递给形参,形参是实参的一份临时拷贝,改变形参不影响实参。

我们来看看这段代码不成功的原因:

我们看到实际参数的两个数分别有各自的地址,形式参数同样有各自的地址,在调用这个函数的时候,只是把实际参数临时拷贝到形式参数中,Swap函数内部完成了两个数的交换,但实际参数并没有交换,因为这是两块独立的空间,互不干扰。

这时的结果为:


正确代码如下:

#include <stdio.h>
Swap(int* m, int* n)
{
  int tmp = *m;
  *m = *n;
  *n = tmp;
}
int main()
{
  int a = 0;
  int b = 0;
  printf("请输入两个数:>");
  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;
}

我们注意到,在传参的时候,实参前加了个&,函数形参类型也变为了int*,这是因为在进行函数操作的时候我们需要改变参数的内容,如果只把两个数值传给Swap函数,在执行Swap函数时虽然交换了两个数的值,但当函数执行完的一瞬间,它所执行的一系列操作都会返回给系统,相当于交换后又被销毁了,所以我们需要传两个数的地址,用int型的指针来接收,在交换的时候,用(解引用符号)*来进行交换,这样,即使函数调用完后被销毁,两个数地址内的内容已经被交换,函数的功能也已经实现了。

我们看一下最后的结果:


三、求素数

求100-200间的素数

代码如下:

#include <stdio.h>
#include <math.h>
int is_prime(int m)
{
  int j = 0;
  for (j = 2; j <= sqrt(m); j++)
  {
    if (0 == m % j)
    {
      return 0;
    }
  }
  return 1;
}
int main()
{
  int i = 0;
  for (i = 100; i <= 200; i++)
  {
    if (is_prime(i))
    {
      printf("%d ", i);
    }
  }
  printf("\n");
  return 0;
}

我们用了一个循环来实现,从100-200之间,每个数都进行判断,函数的实现功能是:是素数,返回1,不是素数返回0。而素数的判断条件是:从2到这个数开平方,只要这个数能被整除,就不是素数,否则就是素数。

运行结果:


return和break:

按上述代码来看,return是直接返回,而break是跳出循环,return比break更直接、彻底。


四、判断闰年

找出1000-2000年是闰年的并打印出来

代码如下:

#include <stdio.h>
int is_leap_year(int m)
{
  if (0 == m % 4 && 0 != m % 100 || 0 == m % 400)
    return 1;
  else
    return 0;
}
int main()
{
  int i = 0;
  for (i = 1000; i <= 2000; i++)
  {
    if (is_leap_year(i))
    {
      printf("%d ", i);
    }
  }
  printf("\n");
  return 0;
}

同样使用了for循环来遍历1000-2000,逐一进行判断,而闰年的判定规则是:能被4整除且不能被100整除或能被400整除,是闰年返回1,否则返回0。

运行结果:


五、用函数完成二分查找

写一个函数,完成二分查找

1.找到了,返回下标

2.找不到,返回-1

代码如下:

#include <stdio.h>
int binary_search(int arr[], int k, int sz)
{
  int left = 0;
  int right = sz - 1;
  while (1)
  {
    int mid = (left + right) / 2;
    if (arr[mid] > k)
    {
      right = mid - 1;
    }
    else if (arr[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 k = 7;
  int len = sizeof(arr)/sizeof(arr[0]);//获取元素个数
  int ret = binary_search(arr, k, len);
  if (-1 == ret)
  {
    printf("找不到!\n");
  }
  else
  {
    printf("找到了,下标是%d\n", ret);
  }
  return 0;
}

我们可以看出,这跟之前的简单二分查找思路基本一样,只是增加了一些参数。

运行结果:

sizeof的基本应用

我们先看一下下面的代码:

int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  printf("%d\n", sizeof(arr));//40
  printf("%d\n", sizeof(arr[0]));//4
  int len = sizeof(arr)/sizeof(arr[0]);//10

上面的sizeof(arr)是计算整个数组的大小,单位是字节,而sizeof(arr[0])计算的是数组中一个数的大小,单位是字节,arr[]是整型数组,内有10个元素,所以按字节来看就是40个字节,arr[0]是数组中一个元素的大小,一个整型大小为4个字节,所以我们可以通过sizeof(arr)/sizeof(arr[0])的方式来获取这个数组内的元素个数。

相关文章
|
3天前
|
安全 C语言
【C语言基础】:内存操作函数
【C语言基础】:内存操作函数
|
3天前
|
编译器 C语言 C++
【C语言基础】:字符函数和字符串函数-2
【C语言基础】:字符函数和字符串函数
|
3天前
|
C语言
【C语言基础】:字符函数和字符串函数-1
【C语言基础】:字符函数和字符串函数
TU^
|
3天前
|
编译器 程序员 Serverless
C语言之函数
C语言之函数
TU^
4 0
|
4天前
|
算法 Unix Linux
C语言随机数的产生(rand、srand、time函数细节讲解)
C语言随机数的产生(rand、srand、time函数细节讲解)
|
11天前
|
存储 C语言
C语言学习记录——动态内存函数介绍(malloc、free、calloc、realloc)
C语言学习记录——动态内存函数介绍(malloc、free、calloc、realloc)
19 1
TU^
|
3天前
|
机器学习/深度学习 C语言
C语言之函数递归
C语言之函数递归
TU^
6 1
|
3天前
|
C语言
C语言——字符串操作函数
C语言——字符串操作函数
5 0
|
3天前
|
机器学习/深度学习 算法 C语言
【C语言基础】:函数递归详解
【C语言基础】:函数递归详解
|
3天前
|
编译器 程序员 C语言
【C语言基础】:函数详解
【C语言基础】:函数详解