广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言中函数的介绍及用法
  • 380
分享到

C语言中函数的介绍及用法

2023-06-20 19:06:33 380人浏览 薄情痞子
摘要

本篇内容介绍了“C语言中函数的介绍及用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录函数定义库函数定义介绍Example 1 strc

本篇内容介绍了“C语言中函数的介绍及用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

目录
  • 函数

    • 定义

  • 库函数

    • 定义

    • 介绍

    • Example 1 strcpy

    • Example 2 memset

  • 自定义函数

    • Example 1

    • Example 2 两数交换

    • 链式访问

    • Example 1

    • 函数声明

  • 函数递归

    • Example 1

    • Example 2

    • 函数迭代

    • Example 3

    • Example 4

函数

定义

程序里的函数又被叫做子程序,他作为一个大型程序的部分代码,有一或多个语句项组成。函数负责完成某项特定任务,提供了对过程的封装和对细节的隐藏,这样的代码通常会被集成为软件库。

特点:

具备相对的独立性一般有输入值和返回值功能单一且灵活

函数的分类有:库函数和自定义函数。

库函数

定义

库函数,顾名思义,放在库里供他人使用的函数。如打印输出这样的基础功能,他不是业务性的代码,在开发过程中使用率高且可移植性强,故C语言的基础库里提供了这样的一系列基础功能的代码。

一般库函数有:

io函数(input&output)—— printf scanf getchar putchar …字符串操作函数 —— strlen strcmp strcat strcpy …字符操作函数 —— tolower toupper …内存操作函数 —— memcpy menset memmove memcmp …时间/日期操作函数 —— time …数学函数 —— sqrt abs fabs pow …其他库函数

介绍

为了掌握库函数的使用方法的学习,我们可以参照权威网站 cplusplus 的解析为样本,一般在不同的平台上也是大同小异。一般都是按照这样的顺序对函数进行解析。

函数的基本信息功能描述函数参数返回值例子拓展

Example 1 strcpy

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

C语言中函数的介绍及用法

C语言中函数的介绍及用法

当然这里 strcpy 函数的返回值是目标空间的首地址,故接收是也可以使用函数的返回值。char arr1[20] = { 0 };char arr2[] = "damn it!";//1.    char* ret = strcpy(arr1, arr2);printf("%s\n", ret);//2.printf("%s\n",strcpy(arr1, arr2));

Example 2 memset

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

C语言中函数的介绍及用法

char arr[20] = "damn it!";memset(arr, 'x', 2);//1.printf("%s\n", arr);//2.printf("%s\n", (char*)memset(arr, 'x', 2));

memset函数是以字节为单位,去修改我们的地址中的内容。

int arr[30] = { 0 };memset(arr, 1, 5 * sizeof(int));

C语言中函数的介绍及用法

这样的话只能把整型变量中每一个字节都变成1,而若想用此法置零则是可行的。

就按照这样的方式去读网站上对函数的解析内容。

注意

  • 每次使用库函数都有引用#include头文件

自定义函数

定义

库函数虽好,但不可贪杯哦~ 库函数虽多,但是毕竟不能实现所有功能,所以还是需要自定义函数来满足我们的各种各样的需求。自定义函数和库函数一样,有函数名、返回类型和函数参属,但不同的是这些都由我们自己来设计。

形式

ret_type fun_name(para1,...){    statment;//语句项}ret_type//返回类型fun_name//函数名para//参数

有了这样的形式模板,我们就可以照葫芦画瓢了。

Example 1

找出两个数的最大值

C语言中函数的介绍及用法

如图所示,写函数,函数名、参数、返回类型都要对应。

Example 2 两数交换

先看再程序设计中如何进行两数交换,用酱油、醋和空瓶举例。

C语言中函数的介绍及用法

先把a赋值给t,那么现在t里面存有a的值现在再把b赋值给a,这样a还在t里不会被覆盖最后把t(里的a)赋值给b,这样就完成了a和b的互换。
void Swap1(int x, int y) {int t = 0;t = x;x = y;y = t;}void Swap2(int* px, int* py){int t = 0;t = *px;*px = *py;*py = t;}int main(){int a = 10;int b = 20;    Swap1(a,b);printf("Swap1:a=%d,b=%d\n", a, b);Swap2(&a, &b);printf("Swap2:a=%d,b=%d\n", a, b);return 0;}

Swap1和Swap2那个函数能够实现这样的功能呢?

Swap1仅仅是把a和b传值给x和y,此时去修改x和y是影响不到a和b的。

Swap2是把a,b的地址传给指针变量px和py,这样的话,再函数内去将px和py解引用再修改,就可以指向a,b的内容了。简而言之,通过指针指向实参的地址使得形参与实参同时发生变化。

C语言中函数的介绍及用法

由图可知,px和py内部存储的是变量a和b的地址,这样对px和py解引用就可以修改a和b的值。

由右图的监视可看出,Swap1函数x和y确实发生了交换,但并没有影响到a和b,Swap2函数的px、py和&a、&b是一个意思。

参数

函数参数分为实际参数和形式参数两种,

实际参数又叫实参,实参可以是任意有确定值的形式,以便在进行函数调用时,将其传给形参。形式参数又叫形参,只有当函数调用时,他们才被分配确定值以及内存单元,调前不存在,调后销毁,所以形参只是形式上存在。

函数调用

传值调用

形参实例化之后相当于实参的一份临时拷贝,并且形参和实参占用不同的内存单元,本质上是两个不同的变量,形参的修改不影响实参。

传址调用

将外部变量的地址传给函数参数,这样的调用可使函数内外建立真正的联系,即形参实参建立联系。

练习

写一个函数能够判断素数

#include <math.h>int is_prime(int n){//试除法int j = 0;for (j = 2; j <= sqrt(n); j++){if (n % j == 0)return 0;}return 1;}

函数的功能要单一且灵活,判断素数就是判断素数,打印的操作留给其他函数,这样的话,写出来的代码才能够很好的互相配合。

写一个函数判断一年是否为闰年

//是闰年返回1,不是闰年返回0int is_leap_year(int y){return (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0));}

不可以将两个或者的条件分开成if…else…的形式,这样的话1200,1600,2000这样可整除400,也可整除100的数据就在第一轮判断就淘汰了,进入不了第二个条件的判断。

写一个函数实现整型有序数组的二分查找

int binary_search(char arr[], int k, int sz){int left = 0;int right = sz - 1;while (left <= right)    {int mid = (left+right)/2;if (arr[mid] > k)        {right = mid - 1;}else if (arr[mid] < k)        {left = mid + 1;  }elsereturn mid;}return -1;}

而在主程序中是这样的

int main(){char arr[20] = { 1,2,3,4,5,6,7,8,9,10 };int key = 7;    int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数int ret = binary_search(arr, key, sz);//TDD - 测试驱动开发//找到返回下标0~9//找不到返回-1    if (ret == -1)        printf("找不到\n");else        printf("找到了,下标为%d", ret);return 0;}

在主程序编写代码时,把binary_search函数当成库函数一样写,并将函数的实现逻辑实现规定好,最后再去写函数实现。

这样的方法叫TDD(test drive develop)—测试驱动开发。

写一个函数每调用一次,就将num的值加1

int Add(int num){num++;}int main(){int num = 0;num = Add(num);return 0;}

讲到这里基本内容就讲完了,下面开始进一步的深入。

嵌套调用

函数可不可以嵌套定义?

当然是不可以的,函数与函数是平等的,是并列关系,不可以在任意函数(包括主函数)中定义其他函数。

但是函数是可以互相调用的。

void fun1(){    printf("hanpidiaoyong\n");}void fun2(){    fun1();}int main(){    fun2();    return 0;}

如代码所示,main函数调用fun2函数,fun2函数又调用fun1函数,最终在屏幕上打印憨批调用字样/[doge]。

链式访问

链式访问(chain access),顾名思义,把一个函数的返回值作为另一个函数的参数。像是用链子把函数首尾相连拴起来。

如:

int main(){    printf("%d\n",strlen("abcde")); //把strlen的返回值作为printf的参数       return 0;}
int main(){char arr1[20] = "xxxxxxx";char arr2[20] = "abcde";//strcpy(arr1,arr2);printf("%s\n", strcpy(arr1, arr2));//strcpy函数的返回值是目标空间首元素地址return 0;}

Example 1

如果觉得掌握了的话,可以看看这个经典例子。

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

请问这条语句输出什么?

想要知道这个,那必然要先了解 printf 函数的返回值是什么,通过MSDN或者cplusplus.com网站去查找。

可以看到 printf 函数的返回值是打印字符的个数,如果发生错误,则返回负值。(ps:scanf的返回值是输出字符的个数)

首先可以看出第三个printf打印了43;

然后第二个printf打印了第三个printf的返回值为2;

最后第一个printf打印第二个printf的返回值1;

所以屏幕上打印了4321。

笔者良心说一句,如果学校里有人说自己C语言不错,那么请拿这题考考他。

函数声明

代码是从前往后执行的,如果函数定义在后面的话,调用时便会发出警告:函数未定义,若想消除警告,我们便需要在前面声明一下。

void test();int main(){test();}void test(){}

定义:声明就是把函数定义在加个;,目的是告诉编译器函数的返回类型、函数名、参数这些具体信息。

特点

函数的声明一般出现在函数使用之前。

函数的声明一般放在头文件中。

在工作的时候,一般是把函数的声明、定义和使用放在三个不同的文件内,方便所有人协作。如:

C语言中函数的介绍及用法

链接:两个.c的源文件编译之后,会分别生成.obj的目标文件,然后再链接起来,最后生成.exe的可执行文件。

在C语言,不提供源码,也可以使用文件的内容,怎么做的呢?

请移步至我的其他博客:关于vs2019的各种使用问题及解决方法(随即更新)

头文件引用

#include的预编译指令是在预编译阶段将头文件内的所有内容拷贝到源文件内。

所以,头文件中的内容若是内容重复包含则会造成效率降低。那么,怎么解决这件事呢?

  • 头文件中包含语句#pragma once使得头文件中不会重复包含其他头文件;

  • 添加这样的代码,将语句包含起来。

#ifndef __ADD_H__// if not define #define __ADD_H__//define//Add函数声明extern int Add(int x, int y);#endif//end if

早期都是用第二种方法的,这两种方法是完全等价的。

函数递归

什么叫函数递归呢?

程序自身调用自身的编程技巧叫递归。

特点

大型复杂问题层层转化为小规模的问题少量程序描述除多次运算

递归的思维方法在于:大事化小。

Example 1

接收一个无符号整型值,按照顺序打印其每一位。如输入:1234,输出:1 2 3 4 .

那我们创建一个函数叫print,若print(1234),则剥离一位变成print(123)+4,再剥离一位成print(12)+3+4,再来一位就是print(1)+2+3+4,最后只有一位了,那就全部用printf 函数打印。如:

C语言中函数的介绍及用法

我们发现只要将数字1234模10就可以得到4,除10便可以得到123,如此模10除10循环往复,可以将1 2 3 4全部剥离出来。

//函数递归void print(size_t n){if (n > 9)//只有1位便不再往下进行{print(n / 10);}printf("%d ", n%10);}

具体流程可参考下面这张图。

C语言中函数的介绍及用法

红线部分即在返回的时候,n是本次函数n,而不是前一次调用的n。

递归递归,就是递推加回归。

现在有两个问题

  • if(n > 9)这个条件没有行不行?没有会怎么样?

自然是不行的,我们在上面的推到中发现,最后1<9条件不成立,就结束了递归,否则会永远递归下去,造成死循环且耗干了栈区。

  • 或者是我们不论代码的正确性,将print(n / 10)改成print(n)会怎么样?

改成print(n)的话每次递归都是相同的值,递归也会无止境的延续下去。

这样便引出了我们递归的两个重要的必要条件:

必要条件

  • 必须存在限制条件,满足条件时,递归不在继续

  • 每次递归调用后必须越来越接近限制条件 函数栈帧

在第一个问题中,如果我们要去试验的话,编译器会报出这样的错误:

C语言中函数的介绍及用法

Stackoverflow(栈溢出)。

C语言中函数的介绍及用法

内存粗略的划分为栈区,堆区,静态区。

栈区主要存放:局部变量,形参(形参和局部变量差不多)动态内存分配:malloc calloc等函数开辟空间静态区主要存放:全局变量,static修饰的静态变量

若是把栈区放大细看的话,如图所示,有为main函数开辟的空间和print函数开辟的空间,为函数开辟的空间叫函数栈帧也可以叫运行时堆栈。

程序开始执行时开辟空间,程序结束时销毁空间函数每调用一次就在栈上开辟一次空间,递归返回时,空间会被回收

Example 2

不创建临时变量,实现Strlen函数

int my_strlen1(char* pa){    int count = 0;while (*pa++ != '\0'){//pa++;count++;}return count;}
//my_strlen求字符串长度int my_strlen(char* pa){if (*pa == 0){return 0;}return 1+my_strlen(pa + 1);//直接返回长度}

具体的思考方式呢,就是只要第一个字符不是0,那我们就在外面+1并且跳到下一个字符,直到找到‘\0',那么我们返回0。

ps:

字符指针+1,向后跳一个字节
整型指针+1,向后跳四个字节
指针+1都是向后跳一个元素的地址,指针类型不同向后跳的字节也不同

C语言中函数的介绍及用法

C语言中函数的介绍及用法

函数迭代

递归、迭代的区别?

递归是重复调用函数自身实现循环。

迭代是函数内某段代码实现循环,循环代码中变量既参与运算同时也保存结果,当前保存的结果作为下一次循环计算的初始值。

递归循环中,遇到满足终止条件的情况时逐层返回来结束。

迭代则使用计数器结束循环。

当然很多情况都是多种循环混合采用,这要根据具体需求。

Example 3

求n的阶乘

int fac(int n){if (n <= 1)return 1;elsereturn n * fac(n - 1);}

Example 4

求第n个斐波那契数

int fib(int n){if (n <= 2)return 1;elsereturn fib(n - 1) + fib(n - 2);}

但是这个方法效率是非常低的,当数字特别大时,层层拆分下来,时间效率是 O ( 2 n ) O(2^n) O(2n)。

根据公式可知,第三个斐波那契数可由前两个得到,我们利用这个规律

int fib(int n){int a = 1;int b = 1;int c = 1;while (n >= 3){c = a + b;a = b;b = c;n--;}return c;}

上一个c变成了b,上一个b变成了a。如此循环往复。

利用迭代的方式,计算一个数只需要计算n-2次,这样的话时间复杂度就是 O ( n ) O(n) O(n)。效率大大提高。

有这两题我们可以发现,什么时候用递归简单呢?

有公式有模板的时候
2.递归简单,非递归复杂的时候
3.有明显问题的时候

“C语言中函数的介绍及用法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: C语言中函数的介绍及用法

本文链接: https://www.lsjlt.com/news/299552.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言中函数的介绍及用法
    本篇内容介绍了“C语言中函数的介绍及用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录函数定义库函数定义介绍Example 1 strc...
    99+
    2023-06-20
  • C语言中数组的介绍及使用
    这篇文章主要讲解了“C语言中数组的介绍及使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中数组的介绍及使用”吧!目录数组一维数组初始化使用总结:内存存储二维数组创建初始化数组越界问题...
    99+
    2023-06-20
  • C语言中qsort函数的介绍与用法实例
    目录一.qsort函数是什么 二.使用qsort排序-以升序为例1.整形数组排序2.字符数组排序3.字符指针数组排序4.结构体数组排序5.浮点型数组排序三.使用冒泡排序思想...
    99+
    2022-11-12
  • C语言中操作符的介绍及用法
    这篇文章主要讲解了“C语言中操作符的介绍及用法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中操作符的介绍及用法”吧!目录操作符分类算术操作符移位操作符整数存储规则左右移位规则赋值操作...
    99+
    2023-06-20
  • 介绍C语言中tolower函数的实例
    C语言tolower函数用于把大写字母转换为小写字母。 在本文中,我们先来介绍tolower函数的使用方法,然后编写一个自定义的_tolower函数,实现与tolower函数相同的功...
    99+
    2022-11-12
  • C语言rand和srand函数使用方法介绍
    目录前言随机数的本质重新播种生成一定范围内的随机数连续生成随机数前言 在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌。 在C语言中...
    99+
    2023-02-11
    C语言rand和srand C语言rand方法 C语言srand方法
  • C语言中.与->的用法介绍
    目录(一)基础(二)例子(三)总结(一)基础 结构体用点,结构体指针用箭头。 a->b 的含义是 (*a).b 。  现代的标...
    99+
    2023-05-20
    C语言中.与->的区别 C语言->用法
  • go语言中函数与方法介绍
    在C#或者Java里面我们都知道,一个Class是要包含成员变量和方法的,对于GO语言的Struct也一样,我们也可以给Struct定义一系列方法。 一、怎么定义一个方法? Go的方...
    99+
    2022-11-13
  • C语言中字符函数和字符串函数介绍
    本篇内容介绍了“C语言中字符函数和字符串函数介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录前言求字符串长度strlen介绍strle...
    99+
    2023-06-20
  • C++中strtok()函数的用法介绍
    函数原型:char *strtok(char *s, const char *delim);Function:分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。D...
    99+
    2022-11-15
    strtok C++
  • C语言make和Makefile介绍及使用
    1:make和Makefile的介绍: 概念 在软件的工程中的源文件是不计其数的,其按照类型,功能,模块分别放在若干个目录中,哪些文件需要编译,那些文件需要后编译,那些文件需要重新编...
    99+
    2022-11-12
  • C语言一看就懂的选择与循环语句及函数介绍
    目录选择语句循环语句while语句for循环do while函数选择语句 什么是选择语句呢?只要是你学过编程语言的,就知道选择语句是程序的灵魂之一,差不多大多是的程序都需要用到这个语...
    99+
    2022-11-13
  • C语言中static的使用介绍
    目录1.static 可以修饰局部变量2. static 可以修饰全局变量3.static 可以修饰函数总结1.static 可以修饰局部变量 首先让我看看这段代码 #inclu...
    99+
    2022-11-12
  • C#中内联函数的用法介绍
    C++ 中有个内联函数,使用 inline 来修饰函数,编译器就会对其进行优化,将此函数作为代码判断插入到调用处。 函数调用在执行时,首先要在栈中为形参和局部变量分配存储空间,然后还...
    99+
    2022-11-13
  • C语言switch语句和if用法介绍
    目录switch语句switch和if的区别1.switch语句结构示意图2.if语句结构示意图switch的高级(灵活)运用switch的嵌套实现循环及循环的两个关键字什么是循环结...
    99+
    2022-11-12
  • R语言的一个加法函数使用介绍
    我就废话不多说了,大家还是直接看代码吧~ ## R语言中的加法函数 add4 <- function(x, y) { x + y } 一个复杂一些的R语言程序 #...
    99+
    2022-11-12
  • C语言函数栈帧的创建和销毁介绍
    在初学c语言中,很多时候要记的内容有点多,有时候并不能深入的了解它。关于函数的栈帧可以帮助我们深入了解函数传参的过程,让我们了解c语言。 以下是我们平时接触过,但不了解的问题: 1...
    99+
    2022-11-12
  • C/C++中虚函数详解及其作用介绍
    目录概述使用方法关联静态关联动态关联案例1未使用虚函数使用虚拟类案例2总结概述 虚函数 (virtual function) 指可以被子类继承和覆盖的函数. 使用方法 基类声明成员...
    99+
    2022-11-12
  • C语言文件操作与相关函数介绍
    目录1.操作的准备2.文件的打开3.文件的使用方式4.相关的函数4.1 fputc4.2 fgetc4.3 fputs4.4 fgets4.5 fprintf4.6 fscanf4....
    99+
    2022-11-13
  • R语言which函数介绍及Rcpp改写详解
    目录引言which 函数的介绍which函数的一些小例子which函数的改进以及时间对比总结引言 首先来介绍一下R语言which函数的作用:which函数在向量、矩阵、数据框,列表、...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作