C语言学习—基础篇—“组件”函数

文章目录

前言

二、函数的声明、定义、调用

(一)函数声明一般格式:

(二)函数的定义

(三)函数的调用

三、函数的嵌套与递归

(一)嵌套调用

(二)递归调用

总结 


前言

记录编程语言——c语言的学习过程,基础篇——c语言“组件”:函数


一、函数是什么

自我理解:一段代码(分程序),函数体包含处理问题的过程,调用只需输入参数,输出结果,利于程序模块化设计

二、函数的声明、定义、调用

准则:C语言中的实体(函数、变量等)必须先声明、后定义、再调用

常用格式

1、函数声明放在文件开头(主函数之前),函数定义在主函数之后;

次用格式(不常用)

1、函数声明在主函数内,在调用之前,函数定义在主函数之后;

2、函数定义在主函数之前,在主函数内调用。

鸡肋格式

    函数定义在前,声明在后。

错误格式

    函数定义在主函数之后,调用前未声明。

(一)函数声明一般格式:

注:合法调用的前提:

  • 对库函数,需包含库函数对应的头文件,即 .h 文件;
  • 对自定义函数,源程序中需有函数声明。

(二)函数的定义

完成函数体的代码实现

一般格式:

 

(三)函数的调用

根据给定的实参执行函数体并返回执行结果。

1、一般格式:

注意:

  • 函数执行结果可用函数名返回,也可用参数返回;
  • 函数调用可以是独立语句,也可以是表达式(以值的形式输出)
  • 参数返回,使用方式为:指针或引用(C++)

2、调用方式——传值调用、传地址调用、引用调用(c++)

①传值调用

形参(虚):函数定义首行括号内的参数表。

例(类型1 参数1,类型2 参数2 …类型n 参数n);

实参:调用时赋值给形参。

 

虚实结合的传值调用过程:

1、调用执行时形参分配空间;

2、将实参的值 以复制(拷副本)的形式传给形参

3、使用形参在函数体内进行计算;

4、调用返回时将形参空间释放

虚实结合传值调用特点:——用时分配,不用释放

形参与实参占用不同内存空间,单向传递,且调用结束时,形参空间被释放,即形参的值发生改变时不会影响到实参

②传地址(值)调用

主调函数中的实参一定是通过复制实参的值传递到函数形参

传地址调用:传的是实参存储的地址值;

适用于多参数返回值的情形;

指针(地址)型形参(虚):类型为指针(地址)的虚拟参数;

指针(地址)型实参:类型为指针(地址)的实参。

传递过程:

1、执行时为形参分配空间;

2、将地址型值复制到形参空间;

3、函数体内用地址值访问对象实体

4、返回时释放地址型形参空间。

特点:

  • 传递的是实体(变量等)地址
  • 函数体内通过形参实际调用外部实体,从而改变实参的值,双向传递
  • 返回时,形参空间释放,所指对象的值被保留

实例:

#include<stdio.h>

void swap(int *p1,int *p2)    //形参表
{
    int p;                    //借用中间变量交换过程
    p=*p1;
    *p1=*p2;
    *p2=p;
}
int main(void)
{
    int x,y;                  //实参  
    scanf("%d,%d",&x,&y);
    printf("x=%d,y=%d\n",x,y);
    printf("swapped:\n");
    swap(&x,&y);              //传地址值
    printf("x=%d,y=%d\n",x,y);
    return 0;
}

③引用调用(c++内容)

引用:被引用对象的别名,能够被编译器逆向引用常量型指针

   常用于函数参数表、函数返回值的传递,也可独立使用。

基本规则:

1、引用被创建时,必须被初始化为指向一个存在的实体;

2、一旦一个引用被指向一个实体,就不能被改变指向另一个实体;(唯一性)

3、不能有NULL(空)引用

引用型形参:类型为引用(常量型指针)的虚拟参数

实参:实际参数

传递过程:

1、执行时为形参分配空间;

2、实参传递到引用型形参,进行别名(指向实参);

3、函数体内用形参引用实参值

4、返回时释放引用型形参空间。

实例:别名型引用参数(a,b是实参x,y的别名)

#include<stdio.h>
void swap(int &a,int &b)    //别名型形参
{
    int t;                  //借用中间变量交换过程
    t=a;
    a=b;
    b=t;
}
int main(void)
{
    int x,y;                //实参
    scanf("%d,%d",&x,&y);
    printf("x=%d,y=%d\n",x,y);
    printf("swapped:\n");
    swap(x,y);             //别名引用方式
    printf("x=%d,y=%d\n",x,y);
    return 0;
}

三、函数的嵌套与递归

(一)嵌套调用

函数定义时不可嵌套,调用时可以嵌套。

(二)递归调用

自己调用自己,两种方式:直接、间接递归调用

①直接递归

②间接递归

注:对函数递归调用层数没有限制,但递归次数过多,空间浪费很大,程序运行缓慢,且容易引起堆栈溢出。

实例1:递归求n!

#include<stdio.h>

int fact(int num)
{
    if(num<=1)
        return 1;
    else return num*fact(num-1);    //直接递归调用
}

int main()
{
    int n,nSum;    //nSum=n!
    printf("please input a number:");
    scanf("%d",&n);
    if(n>0)
    {
        nSum=fact(n);
        printf("The %d!=%d\n",n,nSum);
    }
    else
        printf("n 必须大于0!\n");
    return 0;
}

思考方法:

1)寻找基本项

2)x归纳项

实例2 求解Hanoi塔问题

程序代码:

#include<stdio.h>
#include<stdlib.h>

void dsk_move(int n,char cA,char cB);        //将杆A上的盘n移到杆B
void hanoi(int n,char cA,char cC,char cB);   //将杆A上n张盘通过杆B移到杆C

int main()
{
    int num;                                 //待移动的盘
    printf("请输入要移动的盘的张数:");
    scanf("%d",&num);
    hanoi(num,'A','C','B');
    system("pause");
    return 0;
}

void dsk_move(int n,char cA,char cB)
{
    printf("从%c到%c移动盘%d\n",cA,cB,n);
}

void hanoi(int n,char cA,char cC,char cB)
{
    if(n>0)
    {
        hanoi(n-1,cA,cB,cC);    //将杆A上的n-1张盘通过杆C移动到杆B
        dsk_move(n,cA,cC);      //将杆A上盘n直接移到杆C
        hanoi(n-1,cB,cC,cA);    //将杆B上的n-1张通过杆A移动到杆C
    }
}

运行结果:

总结 

文章参考了程序设计基础教程——C语言版(冯山/主编)科学出版社及其视频教程

本文主要为C语言学习笔记,若出现错误,请谅解,欢迎大佬们指正~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值