C语言----函数

1.函数的概念

函数:founction

c语言的程序代码都是函数组成的

c语言中的函数就是一个完成某项特定的任务的一段代码,这段代码有特殊的写法和调用方法

c语言中我们一般见到两种函数:

.库函数

.自定义函数

2.库函数

有对应的头文件

#include <math.h>
int main()
{
    double r = sqrt(16);
    printf("%lf\n", r);


    return 0;
}

用sqrt求平方根一定要添加头文件#include <math.h>

3.自定义函数

ret_type是用来表示函数计算结果的类型,

函数的参数可以是void,明确表示函数没有参数

//函数的定义
int Add(int x, int y)
{
    int z = 0;
    z = x + y;
    return z;// return z把z的值返回到c里面
}

int main()
{
    int a = 0;
    int b = 0;
    //输入
    scanf("%d %d", &a, &b);
    //计算
    //int c = a + b;
    int c = Add(a, b);//使用函数,调用函数,调用函数就跑到1~7行调用函数了,把a传给x,b传给y
    //输出
    printf("%d", c);

    return 0;
}

还有种更加简介的写法:
int Add(int x, int y)
{

    return x + y;// return z把z的值返回到c里面
}
直接返回x+y




void print(void)   //无参数、无返回值   ,前面的是没有返回值,后面的是不需要参数
{
    printf("hello world");
}
int main()
{
    print();//直接调用
    return 0;
}

返回类型的地方的void表示函数没有返回值
参数部分的void表示函数不需要参数

4.形参和实参

在函数的使用过程中,把函数分为形参和实参

int Add(int x, int y)   // 形参,形式上的存在
{

    return x+y;
}

int main()
{
    int a = 0;
    int b = 0;
    //输入
    scanf("%d %d", &a, &b);
    //计算
    //int c = a + b;
    int c = Add(a, b);//使用函数,调用函数
    //输出
    printf("%d", c);

    return 0;
}
在调用函数的时候,真实传递给函数额参数叫;实际参数,简称实参,
在这个代码里面,我们把第15行的a和b叫做实参
在函数定义部分,函数名后面的参数叫;形式参数,就是本代码里面的x和y
形参其实是实参的临时拷贝

5.return语句

return后面可以是一个数值,也可以是一个表达式,如果是表达式就先执行表达式,再返回表达式的结果

举个例子:return x + y;//令x=10,y=20,只有算完x+y才会返回值

int test()
{
    int a = 0;
    scanf("%d", &a);
    if (a > 0)
        return 1;
    else
        return -1;
}
int main()
{
    int ret = test();
    printf("%d\n", ret);
    return 0;
}


return 语句执行后,函数彻底返回,后面的代码不再执行

void test()
{
    printf("hehe\n");
    if (1)//条件为真
        return;//直接返回,
    printf("haha\n");//被跳过
}
int main()
{
    test();
    return 0;
}



返回值和返回类型不同会出现数据丢失

int test()
{
    return 3.14;//返回的是浮点数,但被转换成整型了,如果返回值和返回类型不统一则会出现数据丢失
}
int main()
{
    int r = test();
    printf("%d\n", r);
    return 0;
}

如果不想出现数据丢失,可以想强制将3.14改变成整型
return (int)3.14;



如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误
函数不写返回类型,默认返回的是整型
int test()
test()


函数的返回值没写的话,编译器会认为返回的是int类型的值
如果函数要求返回值,但是函数中没有使用return返回值吗,那具体返回什么就不确定了

6.数组做函数参数

void set_arr(int arr[10],int sz)//不需要返回值,所以加一个void,这里之所以用arr[10]是因为,下面把数组传过来了,我们要创建一个数组用来接受,sz也一样,同样需要一个形参去接受
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        arr[i] = -1;
    }
}




int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    //写一个函数将一个整型数组的内容,全部置为-1,
    int sz = sizeof(arr) / sizeof(arr[0]);   //算出数组元素的个数
    set_arr(arr,sz);//传数组    //set_arr设置数组,把arr数组中的sz个数组设置一下,这里不能写arr[10],因为arr[10]是数组中下标为10的那个数,如果要传数组的话,传数组名就行了



    return 0;
}




改变:你想赋什么就赋什么,在46行括号内加上你想要赋的值,然后传到函数里面的set,然后通过34行就可以实现了
void set_arr(int arr[10],int sz,int set)//不需要返回值,所以加一个void,这里之所以用arr[10]是因为,下面把数组传过来了,我们要创建一个数组用来接受,sz也一样,同样需要一个形参去接受
{
    int i = 0;
    for (i = 0; i < sz; i++)//通过循环使每一个值都赋上值
    {
        arr[i] = set;
    }
}
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    //写一个函数将一个整型数组的内容,全部置为-1,
    int sz = sizeof(arr) / sizeof(arr[0]);   //算出数组元素的个数
    set_arr(arr,sz,-1);//传数组    //set_arr设置数组,把arr数组中的sz个数组设置一下,这里不能写arr[10],因为arr[10]是数组中下标为10的那个数,如果要传数组的话,传数组名就行了



    return 0;
}










void set_arr(int arr[10],int sz,int set)//不需要返回值,所以加一个void,这里之所以用arr[10]是因为,下面把数组传过来了,我们要创建一个数组用来接受,sz也一样,同样需要一个形参去接受
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        arr[i] = set;
    }
}
void print_arr(int arr[10],int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)//sz=10,i<sz就是<=9,也就是标号为9的数字,也就是最后一位数字
    {
        printf("%d", arr[i]);
    }
    printf("\n");
}

int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    //写一个函数将一个整型数组的内容,全部置为-1,
    int sz = sizeof(arr) / sizeof(arr[0]);   //算出数组元素的个数
    print_arr(arr, sz);//设置之前数组内数字的大小没有变化
    set_arr(arr,sz,-1);//传数组    //set_arr设置数组,把arr数组中的sz个数组设置一下,这里不能写arr[10],因为arr[10]是数组中下标为10的那个数,如果要传数组的话,传数组名就行了

    //打印数组的函数
    print_arr(arr, sz);


    return 0;
}

输出结果为:
12345678910   //改变前
-1-1-1-1-1-1-1-1-1-1    //改变后

数组在传参的时候,实参就写数组名,形参也是数组的形式

实参和形参的名字是可以一样的

函数在设计的时候,一定要功能单一,不要要过于复杂

数组在传参的时候,形参的数组和是实参的数组是同一个数组

形参如果是一维数组,数组大小可以省略不写

形参如果是二维数组,行可以省略,但是列不能省略

//二维数组的案例
void print(int arr[3][5], int r, int c)//这里的3可以省略,但是5不能省略
//这里的r和c是元素个数  
{
    int i = 0;
    for (i = 0; i < r; i++)//几行//这里的r和c是元素个数,这是个循环
    {
        int j = 0;
        for (j = 0; j < c; j++)//一行有几列
        {
            printf("%d ",arr[i][j]);//这里就要用下标访问了,这里的i和j 就是下标,下标的大小要比元素的数小1
        }
        printf("\n");
    }
}



int main()
{
    int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };//定义时是3行5列,这里是元素个数
    //打印二维数组的内容
    print(arr, 3, 5);

    return 0;
}

7.嵌套调用和链式访问

//假设我们某年某月有多少天
//只有闰年的2月有29天,需要对y判断是否是闰年

//函数只有两种返回
//是闰年
//不是闰年
int  is_leap_year(int y)
{
    if(((y%4==0)&&(y%100!=0)||(y%400==0)))//闰年的判断,
        return 1;//如果是闰年就返回1
    else
        return 0;//不是闰年就返回0
}


int get_days_of_month(int y ,int m)//接受年和月//这里我们需要返回一个整型
{
    int days[] = {0,  31,28,31,30,31,30,31,31,30,31,30,31 };
    //             0  1  2  3  4  5  6  7  8  9  10  11      下标
    int day = days[m];
    if (is_leap_year(y) == 1 && m==2)//如果是闰年就返回一,表示为真的,并且m是二月
    {
        day++;//闰年二月的时候,天数+1,为29天
    }
    return day;//如果不是二月就返回day


}



int main()
{
    int month = 0;
    int year = 0;
    scanf("%d %d", &year, & month);
    //计算某年某月有多少天
    int day =get_days_of_month(year, month);//这个函数传了年和月
    printf("%d\n", day);
    return 0;
}



//main函数调用get_days_of_month去计算某年某月有多少天
//get_days_of_month这个函数内部又要通过is_leap_year判断输入的数是否是闰年
//17行的==1可以不写





做出改变,用布尔类型来做:
bool  is_leap_year(int y)    //布尔类型,判断真假
{
    if (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)))//闰年的判断,
        return true;//如果是闰年就返回true
    else
        return false;//不是闰年就返回false
}
所谓链式访问就是将一个函数的返回值作为另一个函数的参数,像链条一样将函数串起来就是函数的链式访问

int main()
{
    //printf("%d", printf("%d", printf("%d ", 43)));//输出结果是4321
    /*int r = printf("hehe");
    printf("%d\n", r);*///输出结果是hehe4,返回的是4个字符

    printf("%d", printf("%d ", printf("%d ", 43)));
    //printf("%d", 43)这个打印出来的是43,打印两个字符返回值是2
    //printf("%d", printf("%d", 2));
    //printf("%d", 2)   再屏幕上打印2,打印一个字符返回值是1
    //printf("%d", 1);打印就是1
    //所以最终的结果是4321
    /*先打印43,再打印2,最后打印1*/
    //如果在中间和后面的两个printf里面的%d后面添加一个空格,输出结果就不一样了,变为43 3 2
    //这种情况的话最先的打印是43加一个空格,返回3个字符
    //然后第二次打印就是打印3和一个空格,返回2个字符
    //然后就变成了printf("%d",2),打印2
    //最终结果就变成43 3 2
    return 0;
}

8.函数的声明和定义

函数或者变量都要满足,先声明后使用

声明后面要加分号,定义后面不用加分号

//函数的定义是一种特殊的声明
/*int  is_leap_year(int y);*///函数的声明,只要函数提前声明了,不管函数定义在前面还是后面,都能使用
int  is_leap_year(int );//函数声明的另一种写法,在声明内容中形参的名字是可以不用写的
 int main()
 {
     int year = 0;
     scanf("%d", year);
     if (is_leap_year(year)==true)//函数的调用
     {
         printf("%d 是闰年", year);
     }
     else
     {
         printf("%d 不是闰年", year);
     }



     return 0;
}

 //函数的定义
 int  is_leap_year(int y)    //布尔类型,判断真假
 {
     if (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)))//闰年的判断,
         return 1;//如果是闰年就返回true
     else
         return 0;//不是闰年就返回false
 }
新创建一个源文件add.c
新创建一个头文件add.h
源文件add.c放函数的定义实现
头文件add.h放函数的声明
如果要使用的话,就写出头文件打代码
#include "add.h"
写出这行代码,头文件就能正常使用了

这样就把函数的声明和定义拆散了,函数定义放在.c文件
函数声明放在头文件

我们要把add.h和add.c当做一个模块,只要想使用这个模块,包含头文件即可

 

把大型复杂的程序,拆分成多个文件的好处

1.团队协作

2.代码模块化,逻辑更加清晰

3.代码的隐藏

局部变量的作用域就是变量所在的局部范围



//int main()
//{
//    {
//        int a = 100;//定义的a只在这个括号内使用,出了这个括号就用不了了 
//        printf("1 a=%d\n", a);
//    }
//    //printf("2 a=%d\n", a);
//
//
//    return 0;
//}
int main()
{
    int a = 100;//把a的定义放在外围的括号内处于这个括号的打印都能用
    {
        //定义的a只在这个括号内使用,出了这个括号就用不了了 
        printf("1 a=%d\n", a);
    }
    printf("2 a=%d\n", a);


    return 0;
}
全局变量的作用域是整个工程



int a = 100;
int main()
{    
    {

        printf("1 a=%d\n", a);
    }
    printf("2 a=%d\n", a);
    return 0;
}
static是静态的意思,可以用来:
1.修饰局部变量
2.修饰全局变量
3.修饰函数

extem是用来声明外部符号的




ertem:
在ass.c定义int a = 100;这就是定义的全局变量




//extern是用来声明外部符号的
笔记.c
extern int a;//变量的声明
int main()
{    
    {

        printf("1 a=%d\n", a);
    }
    printf("2 a=%d\n", a);
    return 0;
}
add.c
int a = 100;

extern是声明外部符号的,只要这个符号是来自外部的,只要用extern 就可以调用了

声明一各变量的方式,知道类型和名字就行了
//void test()//进入函数
//{
//    int a = 1;/*将a赋值为1局部变量*/
//    a++;//a直接新创建一个值
//    printf("%d", a);
//}
//
//int main5()
//{
//    for (int i = 0; i < 5; i++)//i从0开始,循环5次
//    {
//        test();
//    }
//    return 0;
//}
//为什么这个函数输出是2
//因为每次调用test函数的时候,我们就会定义一次a并赋值为1,然后就是2,
//第二轮循环也一样,在每个循环的开始a都是以1出现的,所以最后打印的结果就是5个2




void test()//进入函数
{
    static int a = 1;//在局部变量前面加static\
    //输出结果截然不同,结果为:23456
    a++;
    printf("%d", a);
}

int main()
{
    for (int i = 0; i < 5; i++)//i从0开始,循环5次
    {
        test();
    }
    return 0;
}
//为何在局部变量前面添加static后,结果变得不一样了
//static修饰局部变量改变了变量的声明周期
//在test函数中没有static的话,局部变量 是进入这个函数开始,出去这个函数生命周期结束
//没有被static修饰,局部变量的位置是在栈区的,进入这个函数生成,出去这个函数销毁
//被static修饰修饰的变量就不放在栈区了,就放在静态区了,static修饰修饰的变量叫静态变量
//存储在静态区的变量和全局变量一样的,声明周期就和程序的生命周期一样了
//但是本代码中的a的作用域不变,
//ststic修饰的变量,在第二轮循环的时候,使用的变量就是上一次留下来的,而不是新建的变量

//如何使用static去修饰变量
//:未来一个变量出了函数,我们还想保留值,等下次进入函数继续使用,就可以使用static去修饰这个变量

//如何使用static去修饰局部变量

//:未来一个变量出了函数,我们还想保留值,等下次进入函数继续使用,就可以使用static去修饰这个变量

// 将全局变量放到其他文件
//函数要先声明再使用,变量也一样
//一个全局变量,要想在其他文件中使用,只需要用extern声明外部符号,就可以使用了
//全局变量是默认带有外部链接属性的,只要用extern引用就行了
extern int g_val;//对变量进行声明
int main()
{
    printf("%d\n", g_val);



    return 0;
}
//但是如果想引用其他文件夹的全局变量,但是这个全局变量被static修饰了,
//  那么这个全局变量就不能被引用


//static修饰全局变量的时候,改变了全局变量的链接属性
//使得外部链接属性,变成了内部链接属性
//这种变量只能在自己所在的.c文件中使用,其他的.c文件中无法使用

//使用建议:如果一个全局变量,只想在所在的源文件内部使用,不想被其他文件发现,
// 就可以使用static修饰
//函数在另一个文件


//extern Add(int, int);//声明外部符号就可以使用了
//函数也具有外部链接属性的,只要在其他的.c文件中正确的声明,也可以直接使用

int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    int c = Add(a, b);
    printf("c=%d\n", c);
    return 0;
}

//Add(int x, int y)//static修饰函数,让函数外部链接属性变为内部链接属性
// 只能在自己所在的.c文件中使用,其他.c文件中无法使用
//{
//    return x + y;
//}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/586759.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python | Leetcode Python题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; class Solution:def getPermutation(self, n: int, k: int) -> str:factorial [1]for i in range(1, n):factorial.append(factorial[-1] * i)k - 1ans list()valid [1] * (n 1)for i in range(1, n 1):order k // factorial[n - …

大数据分析与内存计算学习笔记

一、Scala编程初级实践 1.计算级数&#xff1a; 请用脚本的方式编程计算并输出下列级数的前n项之和Sn&#xff0c;直到Sn刚好大于或等于q为止&#xff0c;其中q为大于0的整数&#xff0c;其值通过键盘输入。&#xff08;不使用脚本执行方式可写Java代码转换成Scala代码执行&a…

【面试经典 150 | 回溯】单词搜索

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;回溯 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

C语言实验-循环结构和选择结构

一&#xff1a; 求和:1(14)(149)(14916)…(14916…n2)? 其中n的值由键盘输入&#xff1b; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>int main() {int sum 0;int n 0;printf("请输入一个整数");scanf("%d", &n);for (int i 0; i &l…

【记录】Python3| 将 PDF 转换成 HTML/XML(✅⭐pdfminer.six)

本文将会被汇总至 【记录】Python3&#xff5c;2024年 PDF 转 XML 或 HTML 的第三方库的使用方式、测评过程以及对比结果&#xff08;汇总&#xff09;&#xff0c;更多其他工具请访问该文章查看。 注意&#xff01;pdfminer.six 和 pdfminer3k 不是同一个&#xff01;&#xf…

Java 写一个死锁的例子

public class DeadLock {public static void main(String[] args) {Object lock1 new Object();Object lock2 new Object();new Thread(new A(lock1,lock2),"线程A").start();new Thread(new B(lock1,lock2),"线程B").start();} }class A implements Run…

JAVAEE—servlet的概念及使用,使用servlet接口实现一个表白墙

文章目录 servlet的概念静态页面和动态页面servlet的作用 写出一个servlet程序目录的创建设置smart tomcat编写helloworld servlet的概念 首先我们要搞明白什么是servlet&#xff0c;servlet是一种实现动态页面的技术&#xff0c;他是由tomcat提供给程序员的一组API可以帮助程…

新版多功能在线生成收款码系统源码

相信大家已经听说过收款码三合一这个概念&#xff0c;并且在很多场景中都看到过商家开始使用这样的收款码。前台放置着一个二维码&#xff0c;上边写着“支付宝、微信、QQ扫码付款”&#xff0c;不管使用哪个软件扫码&#xff0c;都能正确识别。但是&#xff0c;我们平台发现使…

Linux 的静态库和动态库

本文目录 一、静态库1. 创建静态库2. 静态库的使用 二、动态库1. 为什么要引入动态库呢&#xff1f;2. 创建动态库3. 动态库的使用4. 查看可执行文件依赖的动态库 一、静态库 在编译程序的链接阶段&#xff0c;会将源码汇编生成的目标文件.o与引用到的库&#xff08;包括静态库…

2024五一数学建模竞赛(五一赛)选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B>A>C&#xff0c;开放度&#xff1a;AB<C。 以下为A-C题选题建议及初步分析&#xff1a; A题&#xff1a;钢板最优切割路径问题 l 难度评估&#xff1a;中等难度。涉及数学建模和优化算法&#xff0c;需要设计最优的…

创新指南|以患者为中心的DTC战略3大趋势推动医疗保健新增长

随着消费者愈发重视个性化和优质的医健体验,医健行业亟需直达消费者DTC重塑服务模式。本文着眼于医健领域的三大消费趋势:消费者在医健领域的支出不断增加,但对整体体验并不满意;消费者信任医健机构处理个人数据,但医疗机构利用数据提升体验的做法有限;消费者在选择医健服务时正…

树莓派4B、树莓派5使用 Debian 12(bookworm) 的配置

最新的系统Debian 12&#xff08;bookworm&#xff09;目前的一些配置发生了一些改变&#xff0c;同时树莓派5的硬件也做了一部分调整。 这里均以系统 Debian 12 对不同的配置做简单记录。 树莓派4B使用旧系统的配置见【树莓派】专栏。 新系统中的配置文件 config.txt 和 cmd…

第11章 数据库技术(第一部分)

一、数据库技术术语 &#xff08;一&#xff09;术语 1、数据 数据描述事物的符号描述一个对象所用的标识&#xff0c;可以文字、图形、图像、语言等等 2、信息 现实世界对事物状态变化的反馈。可感知、可存储、可加工、可再生。数据是信息的表现形式和载体&#xff0c;信…

github托管静态页面

免费在线上空间&#xff0c;不用简直就是浪费&#xff0c;关键还不限流量赶紧去折腾一下 这是搭建的GitHub托管网页&#xff0c;由于是GitHub的服务器&#xff0c;国内访问会非常&#xff01;慢 下载 Watt Toolkit 这里我建议下载一个软件 Watt Toolkit 它是一个开源跨…

QT——简易计算机(从0开始)

目录 一、题目描述&#xff1a; 二、创建工程&#xff1a; 三、UI界面设计&#xff1a; 四、程序编写&#xff1a; 五、总程序&#xff1a; 六、windows可执行文件 七、实现效果 一、题目描述&#xff1a; 创建一个简单的图形用户界面(GUI),包括一个文本框用于显示计算结…

Linux(Centos 7)环境下安装wget,并且更换阿里云镜像

Linux(Centos 7) Minimal 安装后&#xff0c;由于没有预装wget&#xff0c;在使用wget命令去下载安装相关应用时&#xff0c;提示&#xff1a;“wget: command not found” 先在Linux服务器窗口中&#xff0c;输入如下命令&#xff0c;检查Linux服务器有没有安装过wget。 rpm -…

【网站项目】戒烟网站

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

如何在Linux上安装Python?2024Python安装教程

在Linux上安装Python并不难&#xff0c;对于Ubuntu或Debian系统&#xff0c;使用命令sudo apt install python3&#xff1b;对于CentOS、Red Hat或Fedora系统&#xff0c;使用命令sudo yum install python3。 如何在Linux上安装Python&#xff1f; 确切的安装步骤有所不同&am…

【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解

一、线程概念 线程是进程的一个执行分支&#xff0c;是在进程内部运行的一个执行流。下面将从是什么、为什么、怎么办三个角度来解释线程。 1、什么是线程 上面是一张用户级页表&#xff0c;我们都知道可执行程序在磁盘中无非就是代码或数据&#xff0c;更准确点表述&#xff0…

Python基础学习之记录中间文件

倘若想记录代码运行过程中的结果文件&#xff0c;那么以下函数仅供参考 代码示例&#xff1a; import os import datetime import sys import pandas as pd# 定义总的文件夹路径 base_folder E:\\D\\log\\product_data_compare_log# 定义一个函数来创建带时间戳的文件夹 def…
最新文章