函数
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 = ;
GetCircle(ref circle);
Console.WriteLine("周长是:{0}", circle.p);
Console.WriteLine("面积是:{0}", circle.a);
//交换钱数
int myMoney = ;
int yourMoney = ;
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 = ;
defender.health = ;
Attack(ref attacker, ref defender);
Console.WriteLine("血:{0}", defender.health);
#endregion
#region 函数的重载
//函数允许我们重名,重名函数在重载的情况下是允许的
//参数列表不一样时构成重载
//重载函数有助我们统一理解
//1、参数个数不一样
//2、类型和顺序不一样
Console.WriteLine(SumOverload(, 2.0f));
Console.WriteLine(SumOverload(1.0f, ));
Console.WriteLine(SumOverload("aaa", "bbb"));
#endregion
#region 递归的调用
//函数递归 指 函数自身 调用自身的 一种算法
//在算法没有写错的情况 所以他有可能会造成 堆栈溢出异常
//一般用递归解决子问题就是父问题的问题
//边界 在递归过程中,我们必须得有一种已知情况
//边界参数要交给自己
//边界参数要无尽的趋向边界
//求阶乘 6!。 1 * 2 * 3 *4 *5 * 6 * ... * n;
//n! = n * n - 1!
Console.WriteLine(Factorial());
//求1!+2!+3!+... + 10!(两个递归)
Console.WriteLine(Sum());
//一根竹竿长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());
//一根绳子长100m,每天减断一半,问第1天它是多长,问第20天它是多长
Console.WriteLine(Cut());
Console.WriteLine(Cut());
Console.WriteLine(Cut());
#endregion
#region 函数复习
//语句 ;
//代码块 {}
//计算两个数字的和
int a = ;
int b = ;
//容易产生重复,产生代码冗余
int c = Add(a, b);
Console.WriteLine(c);
Add(-, 9.0f);
Console.WriteLine("");
int x = ;
int y = ;
Swap(, );
Console.WriteLine("传进来的变量a:{0},b:{1}", x, y);
//传给ref的实参必须初始化
int x1 = ;
int y1 = ;
//值类型与引用类型的存储方式:
//引用类型:引用类型存储在堆中。类型实例化的时候,会在堆中开辟一部分空间存储类的实
//例。类对象的引用还是存储在栈中。
//值类型:值类型总是分配在它声明的地方,做为局部变量时,存储在栈上;类对象的字段时,
//则跟随此类存储在堆中。
//https://www.cnblogs.com/zd1994/p/4424329.html
int[] nums = { , , };
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 < ) 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[];
array[] = array[];
array[] = 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 * * PI;
circle.a = r * r * PI;
}
//交换钱数(形参)
static void ChangeMoney1(int myMoney, int yourMoney)
{
int temp = ;
temp = myMoney;
myMoney = yourMoney;
yourMoney = temp;
}
//交换钱数(实参)
static void ChangeMoney2(ref int myMoney, ref int yourMoney)
{
int temp = ;
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 <= ) return ;//边界
return sum1 * Factorial(sum1 - );
}
//求1!+2!+3!+... + 10!(两个递归)
static long Sum(long sum)
{
long sum1 = ;
for (int i = ; i <= sum; i++)
{
sum1 = sum1 + Factorial(i);
}
return sum1;
}
//一根竹竿长100m,每天砍掉一半,问第10天它的长度是多少。
static float GetBamboo(int day)
{
if (day <= ) return ;
return GetBamboo(day - ) * 0.5f;
}
//一根绳子第十天长100m,每天减断一半,问第1天它是多长,问第20天它是多长
static float Cut(int day)
{
if (day < ) return Cut();
if (day == ) return ;
if (day > ) return Cut(day - ) * 0.5f;
return Cut(day + ) * ;
}
#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 = "";
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[];
array[] = array[];
array[] = tmp;
}
// 参数个数不同
// 参数个数相同,类型不同
// 参数类型不同
// 重载跟返回类型无关
// 定义的位置
// 返回类型 方法名(参数列表) { 方法体}
static int Add(int a, int b)
{
return a + b; // 结束当前函数
}
static void Add(int array, float b)
{
if (array + b < ) 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[] { , , , , , };
//// 解法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 == "")
{
loginInfo = "登录成功";
return true;
}
else
{
if(user.usr == "user")
{
loginInfo = "密码错误";
}
else if(user.pwd == "")
{
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[];
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 = ;
max = min = arr[];
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[]; // 0 sum 1 max 2 min 3 average
foreach (var item in arr)
{
nums[] += item;
if (nums[] < item) nums[] = item;
if (nums[] > item) nums[] = item;
}
nums[] = nums[] / 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();
}
static void ShowNum(int num, int bei = ) // 从右到左设置,必须在所有可选参数之后
{
Console.WriteLine(num * bei);
}
static void ShowInfo(string s, params string[] operations)
{
string tmp = s;
if(operations.Length > )
{
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 = ;
foreach (var item in nums)
{
sum += item;
}
return sum;
}
}
}