C:5.1-5.7 函数、封装和调用、形参实参、局部变量、函数声明

  • 函数使用原因:避免代码冗长、模块化的设计思路、按功能划分,每个函数代表一个功能
  • 函数在使用前必须先定义
  • 函数三要素
  • 1.函数名——体现功能
  • 2.参数列表——z=f(x,y),x、y就是参数
  • 3.返回值——y是根据x、y的值以及 f 的功能执行后的结果
  • 定义无参函数一般形式:                                                                                                                         
    #include <stdio.h>
    
    /*
      无参函数的写法与调用
    */
    void printfWelcome() //1.()内为空表示没有参数(无x等),即无参函数,也可写为(void)
                         //2.printfWelcome前面的void代表没有返回值,即计算结果
    {
    	puts("===============");
    	puts("欢迎来到我的程序--1");
    	puts("===============");
    	puts("");
    }
    
    int main()
    {
    	
    	printf("===============\n");
    	printf("欢迎来到我的程序--2\n");
    	printf("===============\n");
    	
    	printfWelcome();  //先执行main函数,再调用函数,因此先输出--1,再输出--2
    	                  //调用时直接输入函数名,然后函数最终值会返回主函数进行输出
    	
    	return 0;
    }
    D:\C语言\第五章>gcc test_().c
    
    D:\C语言\第五章>a.exe
    ===============
    欢迎来到我的程序--2
    ===============
    ===============
    欢迎来到我的程序--1
    ===============
    
  • 定义形参函数:
    #include <stdio.h>
    /*
      知识点:
           部分函数与主函数变量名相同与否无所谓,调用时只关心数据和值
    	  (也就是上面的部分data换为y,a换为x与main里x、y重合也无所谓,
    	    因为只是将x值传递给a,然后将data值传递给y,因此变量名不重要)
    */
    void printfWelcome()  //因该部分函数没有返回值,即计算结果,因此用void 
    {
    	puts("===============");
    	puts("欢迎来到我的程序");
    	puts("===============");
    	puts("");
    }
    
    int getDataFromX(int a) //形式参数,书写时需要包含变量类型和变量名
    {
      //书写方法一:
    	int data;    //这里的a和data只作用于getDataFromX函数部分
    	data = a-10;
    	return data;  //将计算出的data值返回给该部分函数的int,然后赋值给main函数的y
    	              //也就是将data值赋值给主函数中的y
    /*
      //书写方法二:
    	return a-10;  //也可写为x-10;
    */
    }
    
    int main()
    {
    
    	int x;
    	int y;  //x、y只作用与main函数部分
    
    	printfWelcome();
    /*	
    	int x;   //x、y定义在这个位置也可以
    	int y;
    */	
    	puts("请输入一个数:");
    	scanf("%d",&x);
    	y = getDataFromX(x);  //在这里跳入到上面的函数部分,这里的x与上面的a不一样
    	                      //只是遇到getDataFromX会跳转然后计算,输入的x值带入上面a里计算
    	printf("x=%d,y=%d\n",x,y);
    	
    	puts("输出结束");
    	return 0;
    }
    D:\C语言\第五章>gcc test_(int).c
    
    D:\C语言\第五章>a.exe
    ===============
    欢迎来到我的程序
    ===============
    
    请输入一个数:
    9
    x=9,y=-1
    输出结束
  • 利用封装和调用计算加法
    #include <stdio.h>
    
    //练习:利用封装和调用计算z=x+y值
    
    int add(int x,int y)  //函数原型,与main函数格式对比书写
                          //部分函数要在()内定义清楚参数(所有需要计算的变量)类型
    {
    	int z;            //在该add函数里必须定义z,否则会报错,同样和下面的xyz不等同,只传递值
    	z = x+y;
    }
    
    int main()
    {
    	int x;
    	int y;
    	int z;  //这里定义的z作用于main函数,与add函数无关
    	int fret;
    	
    	puts("请输入第一个数:");
    	scanf("%d",&x);
    	puts("请输入第二个数:");
    	scanf("%d",&y);
    	
    	z = add(x,y);  //=后面的内容是什么,调用函数里就写什么,加上()外计算类型和()内参数类型即可
    	fret = add(x,y)+100;   //函数也可以当作表达式,用的也是它(z)返回来的值,即等同于z+100
    	
    	puts("");
    	printf("%d+%d=%d\n",x,y,add(x,y));  //最终输出结果在main函数里书写
    	printf("FRET=%d\n",fret);
    	
    	return 0;
    }
    D:\C语言\第五章>gcc ex1_add(x+y).c
    
    D:\C语言\第五章>a.exe
    请输入第一个数:
    -1
    请输入第二个数:
    2
    
    -1+2=1
    FRET=101
  • 定义空函数:调用函数里书写为 void ****() {},也就是返回值和参数均为空,即函数名前为void并且()和{}内均为空,用于程序设计时占坑用。

  • 形参、实参的区别:
  • 局部变量:
    #include <stdio.h>
    /*
      知识点:
         1.变量四要素:名 类型 值 地址
    	 2.形参:被调函数  实参:主调函数
    	 3.形参和实参数值相同,但地址不同  
         4.局部变量:在某部分函数里定义的变量只在该部分函数里作用
         5.形式参数生命周期:只存在于从开始调用到调用结束这个过程	 
    */
    int test(int x)  //被调函数为形式参数,需包含变量名和变量类型
                     //生存周期:栈空间,被调用时才为形式参数申请内存,调用结束时内存又被系统释放
    {	
        printf("test函数里地址为:%p,数值为:%d\n",&x,x); //这里x地址与main函数里x地址不同
    	return 5;
      //return y;  //该写法会报错,因为被调函数里没有定义y,因此无法识别(局部变量)
    }
    
    int main()
    {
    	int x;
    	int y;  //该y只作用与main函数部分,与add函数中的y不是同一个对象(类似不同班的同名同学,对象不同)
    	
    	puts("请输入一个数:");
    	scanf("%d",&x);
    	
    	printf("main函数里地址为:%p,数值为:%d\n",&x,x);
    	y = test(x);   //主调函数为实际参数,可为:变量、常量、表达式
    	printf("x=%d,y=%d\n",x,y);  //因为在add函数里最后返回的是5.因此y=5
    	
    	return 0;
    }
    D:\C语言\第五章>gcc test_main_add.c
    
    D:\C语言\第五章>a.exe
    请输入一个数:
    9
    main函数里地址为:000000000061FE18,数值为:9
    test函数里地址为:000000000061FDF0,数值为:9
    x=9,y=5
  • 练习:用函数调用实现较大值输出
    #include <stdio.h>
    
    //练习:输入两个整数,用函数实现输出较大值
    int max(int x,int y)
    {
    	int z;
    /*方法一:
    	if(x<y)
    	{
    		z=y;
    	}
    	else{
    		z=x;		
    	}
    */
     //方法二:
    	z = x<y?y:x;  //三目运算符———表示:x是否小于y,如果是z即为x值,否则z为y的值	
    	return z;
    /*
     //方法三:(作为整体返回表达式)
        return x<y?y:x;  //此时x<y?y:x所有部分的数值返回并赋值给main函数里的z
    */
    }
    
    int main()
    {
    	int x;
    	int y;
    	int z;
    	
    	puts("请输入两个整数:");
    	scanf("%d%d",&x,&y);  //scanf里输入的数字之间不添加任何内容,后半部分用取地址符号&
      //scanf("%d,%d",&x,&y);  //例如这里添加的,会被判别为输入内容,因此逗号后面的y值赋值错误
      
    	z = max(x,y);
    	
    	printf("较大值为:%d(x=%d,y=%d)\n",z,x,y);
      //printf("较大值为:%d(x=%d,y=%d)\n",x<y?y:x,x,y);	 //对应方法三
    	return 0;
    }
    D:\C语言\第五章>gcc ex2_max.c
    
    D:\C语言\第五章>a.exe
    请输入两个整数:
    -2 8
    较大值为:8(x=-2,y=8)
  • 练习:用函数调用实现较大字符输出
    #include <stdio.h>
    
    //练习:输入两个字符,用函数实现输出较大字符
    char GetFromcharmax(char x,char y)
    {
    	return x>y?x:y;  //x>y?x:y比较的值返回给main函数printf里的max或者x>y?x:y
    }
    int main()
    {
    	char x;
    	char y;
    	char max;
    	
    	puts("请输入两个字符:");
    //方法一:
    	scanf("%c%c",&x,&y);  //字符用%c 浮点数%f(%.2f)
    	                      //且scanf里的代码和编译里的输入内容间不能有其它内容,例:%c%c和cu
    //方法二:
    //  x=getchar();
    //	y=getchar();
      
    	max = GetFromcharmax(x,y);
    	
    	printf("较大字符为:%c(x=%c,y=%c)\n",max,x,y);
    	printf("较大字符为:%c(x=%c,y=%c)\n",x>y?x:y,x,y);
    	
    	return 0;
    }
    D:\C语言\第五章>gcc ex3_max_char.c
    
    D:\C语言\第五章>a.exe
    请输入两个字符:
    az
    较大字符为:z(x=a,y=z)
    较大字符为:z(x=a,y=z)
  • 函数原型声明:
  • 练习:用函数调用实现较小字符输出
    #include <stdio.h>
    /*
      知识点:
         1.内存空间:在定义函数中指定的形参未出现调用时并不占用存储单元,发生调用时才分配
    	 2.值传递:实参对应的值传递给形参
    	 3.值返回:通过return将值带回主函数(注:返回值类型与函数类型一致)
    	 4.内存释放:调用结束,形参单元释放,实参单元仍维持原值不变
    	             如果在执行一个被调函数时,形参值会改变,但主调函数实参值不变,因为存储单元不同
    	 5.函数原型声明
    */
    //练习:输入两个字符,用函数实现输出较小字符
    
    char GetFromcharmin(char x,char y);  //函数原型声明:书写为被调函数后加封号(;)
        //当被调函数在主函数后面放置时,在主函数前面进行声明,否则编译不会错,但会提示识别不到
    
    int main()
    {
    	char x;
    	char y;
    	char min;
    	
    	puts("请输入两个字符:");
        x=getchar();
    	y=getchar();
      
    	min = GetFromcharmin(x,y);
    	
    	printf("较小字符为:%c(x=%c,y=%c)\n",min,x,y);
    	printf("较小字符为:%c(x=%c,y=%c)\n",x<y?x:y,x,y);
    	
    	return 0;
    }
    
    char GetFromcharmin(char x,char y)
    {
    	return x<y?x:y;  
    }
    1.没有声明:
    
    D:\C语言\第五章>gcc ex4_min_char.c
    ex4_min_char.c: In function 'main':
    ex4_min_char.c:25:8: warning: implicit declaration of function 'GetFromcharmin' [-Wimplicit-function-declaration]
      min = GetFromcharmin(x,y);
            ^~~~~~~~~~~~~~
    ex4_min_char.c: At top level:
    ex4_min_char.c:33:6: error: conflicting types for 'GetFromcharmin'
     char GetFromcharmin(char x,char y)
          ^~~~~~~~~~~~~~
    ex4_min_char.c:25:8: note: previous implicit declaration of 'GetFromcharmin' was here
      min = GetFromcharmin(x,y);
            ^~~~~~~~~~~~~~
    
    D:\C语言\第五章>a.exe
    请输入两个字符:
    ba
    较小字符为:a(x=b,y=a)
    较小字符为:a(x=b,y=a)
    
    
    
    2.正确声明:
    
    D:\C语言\第五章>gcc ex4_min_char.c
    
    D:\C语言\第五章>a.exe
    请输入两个字符:
    mn
    较小字符为:m(x=m,y=n)
    较小字符为:m(x=m,y=n)


版权声明:本文为qq_43667606原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。