C#学习笔记(十):函数和参数

函数

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace m1w3d1_function_parm_overload_oop
{
    class Program
    {
        static void Main(string[] args)
        {
            #region 函数的参数
            //为什么我们给一个变量给到方法,方法的确没有去改变这个变量的值?
            //方法使用的是 形参
            //方法本质上是把你传给他的参数,行进一份拷贝(复制)一份在方法体里进行运算
            //所以这个复制的参数,叫做形参,并不是你传进的参数本体,叫做实参,形参并不是实参
            //如果我需要改实参,我们应该怎么做
            //对象我,你,在计算机中数据是存放在内存,这一块数据实际存放的内存地址就是他的实体
            //如果我们方法中能拷贝实际内存地址我们就可以正常改变实参的值
            #endregion
            #region ref关键字
            //在定义方法时 使用 参数修饰 ref 我们可以传递一个地址
            //1,定义方法参数使用ref关键字,调用时同时也可使用
            //2,调用时,实际参数必须有被赋值
            #endregion
            #region ref关键字的练习
            //给圆赋值
            Circle circle = new Circle();
            circle.r = 5;
            GetCircle(ref circle);
            Console.WriteLine("周长是:{0}", circle.p);
            Console.WriteLine("面积是:{0}", circle.a);
            //交换钱数
            int myMoney = 10;
            int yourMoney = 50;
            ChangeMoney1(yourMoney, myMoney);
            Console.WriteLine("我的钱:{0}", myMoney);
            Console.WriteLine("你的钱:{0}", yourMoney);
            ChangeMoney2(ref yourMoney, ref myMoney);
            Console.WriteLine("我的钱:{0}", myMoney);
            Console.WriteLine("你的钱:{0}", yourMoney);
            //战士攻击减血
            Fighter attacker = new Fighter();
            Fighter defender = new Fighter();
            attacker.attack = 4;
            defender.health = 10;
            Attack(ref attacker, ref defender);
            Console.WriteLine("血:{0}", defender.health);
            #endregion
            #region 函数的重载
            //函数允许我们重名,重名函数在重载的情况下是允许的
            //参数列表不一样时构成重载
            //重载函数有助我们统一理解
            //1、参数个数不一样
            //2、类型和顺序不一样
            Console.WriteLine(SumOverload(1, 2.0f));
            Console.WriteLine(SumOverload(1.0f, 2));
            Console.WriteLine(SumOverload("aaa", "bbb"));
            #endregion
            #region 递归的调用
            //函数递归 指 函数自身 调用自身的 一种算法
            //在算法没有写错的情况 所以他有可能会造成 堆栈溢出异常
            //一般用递归解决子问题就是父问题的问题
            //边界 在递归过程中,我们必须得有一种已知情况
            //边界参数要交给自己
            //边界参数要无尽的趋向边界
            //求阶乘    6!。 1 * 2 * 3 *4 *5 * 6 * ... * n;
            //n! =  n * n - 1!   
            Console.WriteLine(Factorial(6));
            //求1!+2!+3!+... + 10!(两个递归)
            Console.WriteLine(Sum(10));
            //一根竹竿长100m,每天砍掉一半,问第10天它的长度是多少。
            //long = f(day,n)
            //f(10)=f(9)*0.5f;
            //f(9)=f(8)*0.5f;
            //f(n)=f(n-1)*0.5f;
            //f(n)=f(n+1)*2;
            //n<=1 long=100m
            Console.WriteLine(GetBamboo(10));
            //一根绳子长100m,每天减断一半,问第1天它是多长,问第20天它是多长
            Console.WriteLine(Cut(1));
            Console.WriteLine(Cut(10));
            Console.WriteLine(Cut(20));
            #endregion
            #region 函数复习
            //语句 ;
            //代码块 {}
            //计算两个数字的和
            int a = 20;
            int b = 10;
            //容易产生重复,产生代码冗余
            int c = Add(a, b);
            Console.WriteLine(c);
            Add(-10, 9.0f);
            Console.WriteLine("1111");
            int x = 6;
            int y = 9;
            Swap(6, 9);
            Console.WriteLine("传进来的变量a:{0},b:{1}", x, y);
            //传给ref的实参必须初始化
            int x1 = 6;
            int y1 = 9;
            //值类型与引用类型的存储方式:
            //引用类型:引用类型存储在堆中。类型实例化的时候,会在堆中开辟一部分空间存储类的实
            //例。类对象的引用还是存储在栈中。
            //值类型:值类型总是分配在它声明的地方,做为局部变量时,存储在栈上;类对象的字段时,
            //则跟随此类存储在堆中。
            //https://www.cnblogs.com/zd1994/p/4424329.html
            int[] nums = { 1, 2, 3 };
            Swap(nums);
            foreach (var item in nums)
            {
                Console.WriteLine(item);
            }
            #endregion
        }
        #region 函数复习
        //函数定义的位置
        //返回类型 方法名(参数列表){方法体}
        //为什么要加static,静态的函数只能调用静态的函数
        static int Add(int a, int b)
        {
            return a + b;//结束当前函数,有返回值
        }
        //函数重载
        //参数个数不同
        //参数个数相同,类型不同
        //参数类型不同
        //重载跟返回类型无关
        //void没有返回值
        static void Add(int a, float b)
        {
            if (a + b < 0) return;//结束当前函数,没有返回值
            Console.WriteLine(a + b);
        }
        static void Swap(int a, int b)//交换的是形式参数
        {
            Console.WriteLine("传进来的变量a:{0},b:{1}", a, b);
            int temp = a;
            a = b;
            b = temp;
            Console.WriteLine("传进来的变量a:{0},b:{1}", a, b);
        }
        static void Swap(int[] array)//交换的是
        {
            int temp = array[0];
            array[0] = array[1];
            array[1] = temp;
        }
        public struct Circle
        {
            public float r;
            public float p;
            public float a;
        }
        #endregion
        #region ref关键字的练习
        //给圆赋值
        static void GetCircle(ref Circle circle)
        {
            var PI = 3.14f;
            var r = circle.r;
            circle.p = r * 2 * PI;
            circle.a = r * r * PI;
        }
        //交换钱数(形参)
        static void ChangeMoney1(int myMoney, int yourMoney)
        {
            int temp = 0;
            temp = myMoney;
            myMoney = yourMoney;
            yourMoney = temp;
        }
        //交换钱数(实参)
        static void ChangeMoney2(ref int myMoney, ref int yourMoney)
        {
            int temp = 0;
            temp = myMoney;
            myMoney = yourMoney;
            yourMoney = temp;
        }
        //战士属性
        struct Fighter
        {
            public int attack;
            public int health;
        }
        //攻击减血
        static void Attack(ref Fighter attaker, ref Fighter defender)
        {
            defender.health -= attaker.attack;
        }
        #endregion
        #region 函数的重载
        static int SumOverload(int a, float b)
        {
            Console.WriteLine("这是浮点和整型的重载");
            return (int)(a + b);
        }
        static float SumOverload(float a, int b)
        {
            Console.WriteLine("这是浮点的重载");
            return a + b;
        }
        static string SumOverload(string a, string b)
        {
            return a + b;
        }
        #endregion
        #region 递归的函数
        //6!。 1 * 2 * 3 *4 *5 * 6 * ... * n;
        static long Factorial(long sum1)
        {
            if (sum1 <= 1) return 1;//边界
            return sum1 * Factorial(sum1 - 1);
        }
        //求1!+2!+3!+... + 10!(两个递归)
        static long Sum(long sum)
        {
            long sum1 = 0;
            for (int i = 1; i <= sum; i++)
            {
                sum1 = sum1 + Factorial(i);
            }
            return sum1;
        }
        //一根竹竿长100m,每天砍掉一半,问第10天它的长度是多少。
        static float GetBamboo(int day)
        {
            if (day <= 0) return 100;
            return GetBamboo(day - 1) * 0.5f;
        }
        //一根绳子第十天长100m,每天减断一半,问第1天它是多长,问第20天它是多长       
        static float Cut(int day)
        {
            if (day < 1) return Cut(1);
            if (day == 10) return 100;
            if (day > 10) return Cut(day - 1) * 0.5f;
            return Cut(day + 1) * 2;
        }
        #endregion
    }
}

 

#region out 参数修饰符
//用来修饰函数的参数
//一般情况下我们用out来返回一个检测结果
//因为out要求在函数体内一定要给参数赋值(原有的值不可用)
#endregion


#region params 参数修饰符
//可变参数修饰符,将一个 数组参数 变成允许调用者直接用数组元素传参的形式
//在定义时必须params,调用时直接填数组元素
//params参数必须是最后一个参数
//不用定义数组变量,直接调用函数时传参
#endregion

 

 

函数复习
变量名,存在栈里
数组名,存在栈里(保存的是数组元素首字母的地址)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _2_函数
{
    class Program
    {
        static void Main(string[] args)
        {
            // 语句  ;
            // 代码块     { }
            // 计算两个数字的和
            // int a = 20;
            // int b = 10;
            //int c = Add(a, b);
            // Console.WriteLine(c);
            //Add(-10, 9.0f);
            //Console.WriteLine("1111");
            //int a = 10;
            //int b = 20;
            //// 传给ref的实参必须初始化
            //Swap(ref a, ref b);
            ////Console.WriteLine("变量a:{0}, b:{1}", a, b);
            //int[] nums = { 1, 2, 3 };
            //Swap(nums);
            //foreach (var item in nums)
            //{
            //    Console.WriteLine(item);
            //}
            string num = "123";
            int result;
            //int a = int.Parse(num);
            if (int.TryParse(num, out result))
            {
                Console.WriteLine("转换成功 :" + result);
            }
            //else
            //{
            //    Console.WriteLine("转换失败 :" + result);
            //}
        }
        // out 参数 --- 输出型参数
        // ref 参数 --- 叫 引用型参数
        static void Swap(ref int a, ref int b)  // 形式参数   值传递  加ref变成 传引用
        {
            Console.WriteLine("传进来的变量a:{0}, b:{1}", a, b);
            int tmp = a;
            a = b;
            b = tmp;
            Console.WriteLine("交换后的变量a:{0}, b:{1}", a, b);
        }
        static void Swap(int[] array)     // 引用传递
        {
            int tmp = array[0];
            array[0] = array[1];
            array[1] = tmp;
        }
        // 参数个数不同
        // 参数个数相同,类型不同
        // 参数类型不同
        // 重载跟返回类型无关
        // 定义的位置
        // 返回类型 方法名(参数列表) { 方法体}
        static int Add(int a, int b)
        {
            return a + b;   // 结束当前函数
        }
        static void Add(int array, float b)
        {
            if (array + b < 0) return;  // 结束当前函数
            Console.WriteLine(array + b);
        }
    }
}

 

out练习

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _1_out练习
{
   
    class Program
    {
        /*
            1. 返回给用户一个登录结果,并且还要单独的返回给用户一个登录信息。
            如果用户名错误,除了返回登录结果之外,还要返回一个“用户名错误”、“密码错误”
            2. 写一个方法,返回一个数组的总和、最大值、最小值、平均值
        */
        static void Main(string[] args)
        {
            #region 练习1
            //UserInfo userInfo = new UserInfo();
            //string loginInfo;
            //Console.WriteLine("请输入用户名:");
            //userInfo.usr = Console.ReadLine();
            //Console.WriteLine("请输入密码");
            //userInfo.pwd = Console.ReadLine();
            //TryLogin(userInfo, out loginInfo);
            //Console.WriteLine(loginInfo);
            #endregion
            #region 练习2
            var nums = new[] { 2, 4, 9, 4, 6, 3 };
            //// 解法1调用
            ResultInfo result = GetResult(nums);
            Console.WriteLine($"** 和:{result.sum}, 最大值:{result.max}, 最小值:{result.min},平均值:{result.average}");//$符号,{}里可以直接填变量
            // 解法2调用
            //int sum, max, min, average;
            //GetResult(nums, out sum, out max, out min, out average);
            //Console.WriteLine($"## 和:{sum}, 最大值:{max}, 最小值:{min},平均值:{average}");
            // 解法3
            int[] array = GetResult1(nums);
            Console.WriteLine($"** 和:{array[0]}, 最大值:{array[1]}, 最小值:{array[2]},平均值:{array[3]}");
            #endregion
        }
        #region 练习1
        /*
         *  1. 返回给用户一个登录结果,并且还要单独的返回给用户一个登录信息。
            如果用户名错误,除了返回登录结果之外,还要返回一个“用户名错误”、“密码错误”
         */
        struct UserInfo
        {
            public string usr;
            public string pwd;
        }
        static bool TryLogin(UserInfo user, out string loginInfo)
        {
            if (user.usr == "user" && user.pwd == "1234")
            {
                loginInfo = "登录成功";
                return true;
            }
            else
            {
                if(user.usr == "user")
                {
                    loginInfo = "密码错误";
                }
                else if(user.pwd == "1234")
                {
                    loginInfo = "用户名错误";
                }
                else
                {
                    loginInfo = "用户名和密码错误";
                }
                return false;
            }
        }
        #endregion
        #region 练习2
        /*
            2. 写一个方法,返回一个数组的总和、最大值、最小值、平均值
         */
        struct ResultInfo
        {
            public int sum;
            public int max;
            public int min;
            public int average;
        }
        // 解法1
        static ResultInfo GetResult(int[] arr)
        {
            ResultInfo result = new ResultInfo();
            result.max = result.min = arr[0];
            foreach (var item in arr)
            {
                result.sum += item;
                if (result.max < item) result.max = item;
                if (result.min > item) result.min = item;
            }
            result.average = result.sum / arr.Length;
            return result;
        }
        // 解法2
        static void GetResult(int[] arr, out int sum, out int max, out int min, out int average)
        {
            sum = 0;
            max = min = arr[0];
            foreach (var item in arr)
            {
                sum += item;
                if (max < item) max = item;
                if (min > item) min = item;
            }
            average = sum / arr.Length;
        }
        static int[] GetResult1(int[] arr)
        {
            int[] nums = new int[4];  // 0 sum  1 max 2 min 3 average
            foreach (var item in arr)
            {
                nums[0] += item;
                if (nums[1] < item) nums[1] = item;
                if (nums[2] > item) nums[2] = item;
            }
            nums[3] = nums[0] / arr.Length;
            return nums;
        }
        #endregion
    }
}

 

 

params关键字
params关键字的优点
1.数组可以单个传
2.也可以什么都不传
3.还可以给参数设置默认值
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3_params
{
    class Program
    {
        static void Main(string[] args)
        {
            //var nums = new[] { 1, 2, 5, 3, 6 };
            //Console.WriteLine(GetSum(nums));  // 什么都不传也可以
            //Console.WriteLine(GetSum());
            //ShowInfo("Hello World!", "前空格", "后空格", "前空格");
            ShowNum(10);
        }
        static void ShowNum(int num, int bei = 2)     // 从右到左设置,必须在所有可选参数之后
        {
            Console.WriteLine(num * bei);
        }
        static void ShowInfo(string s, params string[] operations)
        {
            string tmp = s;
            if(operations.Length > 0)
            {
                foreach (var item in operations)
                {
                    if(item == "前空格")
                    {
                        tmp = "###\t" + tmp;
                    }
                    if(item == "后空格")
                    {
                        tmp += "\t###";
                    }
                }
            }
            Console.WriteLine(tmp);
        }
        static int GetSum(params int[] nums)
        {
            int sum = 0;
            foreach (var item in nums)
            {
                sum += item;
            }
            return sum;
        }
    }
}

 

 

 

posted @ 2019-02-11 16:51  vuciao  阅读(509)  评论(0编辑  收藏  举报