第二阶段_第四家小节_C#基础2

来源:互联网 发布:数据分析 量化交易 编辑:程序博客网 时间:2024/05/01 02:25

 

 

第三小节

 

 

  1. 方法重载

 

//方法重载:方法名称相同,参数列表不同

//适用性:在不同条件下,解决同一类问题

//优点:让调用者解决一类问题,记忆1个方法。

 

要求:返回值相同

  1. 练习分钟小时的重载

 

  1. ref——引用参数

引用参数,为地址,相当于指针。

 

 

 

  1. out——输出参数

输出参数类似引用参数,但输出参数在函数中必须修改调用方法前可以不赋值

 

 

 

  1. 一维数组

 

 

  1. 数组读取

 

 

  1. 练习

 

 

 

 

 

 

 

 

 

 

 

  1. 录入成绩练习

 

 

 

 

 

  1. 获取最大值练习

 

 

  1. 数组写法与练习

 

  1. 计算今年第几天

 

 

 

 

 

 

  1. 练习自学Array的方法

  1. Forreach

:只能读

:全部

 

依次读取全部元素。

 

 

 

  1. 数组简元素进行比较

 

 

  1. 冒泡排序

缺点:通常交换次数过多。

 

 

  1. 选择排序(性能提升)

 

 

 

  1. Params

意义:简化调用者的调用难度。

 

 

形式用法:

 

调用:

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. 二维数组

    1. 形式:

 

 

 

从下到上,从右到左

 

 

 

 

 

 

 

  1. 声明

 

  1. 从左到右,从上到下

 

  1. 从右到左,从下到上

 

  1. 用法:

 

  1. arr.length//表示行数*列数;

  2. arr.Getength(0);// 行数

  3. arr.Getlength(1);// 列数

 

 

  1. 相关语法

 

  1. Array 数组基类(父类)

  1. object 万类之祖

  1. var 隐式(推断)类型

 

  1. Array的API

 

 

 

 

  1. 交错数组

 

 

特点:参差不齐的数组

 

长短不一的数组,交错数组的每个元素都是一维数组。

[1][ ][2]

[ ][ ][ ][3][ ]

[ ][ ][4][ ]

创建具有3个元素的交错数组(3行)

int[][] array;

array = new int[3][];--->前边方括号填包括几个一维数组,后边方括号里不能加东西

赋值:

array[0] = new int[3];

array[1] = new int[5];

array[2] = new int[4];

长度可相同。

//将数据1赋值给交错数组的第一个元素的第1个元素

array[0][0] = 1;

array[0][2] = 2;

array[1][2] = 3;

array[2][1] = 4;

读取array:(遍历交错数组)

foreach(var item in array)

{

foreach(var element in item)

{

Console.WriteLine(element);

}

}

//交错数组.Length 交错数组元素总数(行数)

//交错数组[索引].Length 交错数组元素的元素总数(某一行的列数)

for(int r=0;r<array.Length;r++)//交错数组的元素数

{

for(int c =0;c<array[r].Length;c++)//交错数组第一个元素的元素数

{

Console.WriteLine(array[r][c]);

}

}

 

 

 

 

  1. 形式:

float[][] arr3 = new float[3][];

//创建一维数组赋值给交错数组的第一个元素

arr3[0] = new float[2];

arr3[1] = new float[4];

arr3[2] = new float[3];

//将数据1赋值给交错数组的第一个元素的第二个元素

arr3[0][1] = 1;

arr3[1][0] = 2;

arr3[2][2] = 3;

  1. 获取所有元素

    1. Foreach

foreach (float[] item in arr3)//遍历交错数组的元素(一维数组)

{

foreach (var element in item)//遍历交错数组元素的元素

{

Console.WriteLine(element);

}

}

  1. For

for (int r = 0; r < arr3.Length; r++)

{

for (int c = 0; c < arr3[r].Length; c++)

{

Console.Write(arr3[r][c] +"\t");

}

Console.WriteLine();

}

}

 

 

  1. arr3.Length 交错数组的元素数

  2. arr3[0].Length 交错数组第一个元素的元素数

 

 

  1. 复习

 

 

 

 

 

  1. 参数数组

使用params关键字定义的

只能用于形参列表

 

 

 

 

1.原始

  1. 参数数组

    1. 正常数组整数相加

整数相加需求//参数个数不确定,类型确定

形式:

static int Add(int[] arr)

 

调用:

Int sum =add(new int[]{1,2,3,4,5});

 

  1. 参数数组整数相加

形式:

整数相加需求//参数个数不确定,类型确定

static int Add(params int[] arr)

 

调用:

Int sum =add(1,2,3,4,5);

 

 

对于调用者来说更方便,对于方法内部而言,就是普通一维数组

整数相加的方法:(个数不确定,类型能确定)

用到params的数组要放在形参最后面, Add(int a,params int[] arr)

private static int Add(params int[] arr)【params 可以使调用者直接传递一组数据类型相同的变量集合,也可以不传】

{

int sum;

for(int i =0;i<arr.Length;i++)

{

sum+=arr[i];

}

}

foreach也可,因为foreach只对自身只读,这里是sum 变化,foreach不变化

Main()

{

//int a=Add(new int[]{1,2,3,4,5});

int a = Add(1,2,3,4,5);---->用了params 就不用再new int[]

int b = Add();--->用了params也可以不传

}

 

  1. 复习

 

 

 

 

 

  1. 彩票练习

 

 

  1. 答案

 

private static void Main2()

{

int[] myTicket = BuyTicket();

 

Console.WriteLine("我买的彩票:");

PrintTicket(myTicket);

Console.WriteLine("验证我的中奖潜力……");

 

int count = 0;

int level;

do

{

count++;

int[] ticket = CreateTicket();

//购买彩票与开奖彩票对比

level = TicketEquals(myTicket, ticket);

 

Console.WriteLine("*********开奖号码:*********");

PrintTicket(ticket);

 

if (level != 0)

Console.WriteLine("恭喜,{0}等奖。累计花费:{1}元", level, count * 2);

} while (level != 1);

}

 

private static int[] BuyTicket()

{

int[] ticket = new int[7];

 

for (int i = 0; i < ticket.Length - 1; )

{

Console.WriteLine("请输入第{0}个红球号码:", i + 1);

int redNumber = int.Parse(Console.ReadLine());

 

if (redNumber < 1 || redNumber > 33)

Console.WriteLine("您输入的数字超过红球号码范围:1--33");

//[重点:判断输入的号码在数组中是否存在]

else if (Array.IndexOf(ticket, redNumber) >= 0)

Console.WriteLine("当前数字已经存在,请重新录入");

else

ticket[i++] = redNumber;

}

 

int blueNumber;

do

{

Console.WriteLine("请输入篮球号码:");

blueNumber = int.Parse(Console.ReadLine());

if (blueNumber >= 1 && blueNumber <= 16)

ticket[6] = blueNumber;

else

Console.WriteLine("请输入数字超过篮球号码:1--16");

} while (blueNumber < 1 || blueNumber > 16);//数字不在1--16之间 再次执行

 

return ticket;

}

 

private static Random ran = new Random();

private static int[] CreateTicket()

{

int[] ticket = new int[7];

//[重点:生成多个不重复的随机数]

for (int i = 0; i < 6; )

{

//思路:生成随机数,判断是否存在,不在则存储

int num = ran.Next(1, 34);

if (Array.IndexOf(ticket, num) == -1)

ticket[i++] = num;

}

ticket[6] = ran.Next(1, 17);

//红球号码排序[重点:指定范围的排序]

Array.Sort(ticket, 0, 6);

return ticket;

}

 

private static int TicketEquals(int[] myTicket1, int[] ranTicket2)

{

//判断红球号码中奖数量

//思路:我的第1个号码在随机彩票的红球号码段中是否存在

// 我的第2个号码在随机彩票的红球号码段中是否存在

//[重点:在指定范围内检查是否具有相同元素]

int redCount = 0;

 

for (int i = 0; i < 6; i++)

{

if (Array.IndexOf(ranTicket2, myTicket1[i], 0, 6) != -1)

redCount++;

}

 

int blueCount = myTicket1[6] == ranTicket2[6] ? 1 : 0;

 

int level;

if (redCount + blueCount == 7)

level = 1;

else if (redCount == 6)

level = 2;

else if (redCount + blueCount == 6)

level = 3;

else if (redCount + blueCount == 5)

level = 4;

else if (redCount + blueCount == 4)

level = 5;

else if (blueCount == 1)

level = 6;

else

level = 0;

return level;

}

 

private static void PrintTicket(int[] ticket)

{

for (int i = 0; i < ticket.Length; i++)

{

Console.Write(ticket[i] + "\t");

}

Console.WriteLine();

}

 

 

  1. 输出#号练习

 

 

 

 

 

 

 

  1. 冒泡排序:发现【更】小的则交换

 

 

 

 

  1. 图片

 

  1. 代码

//缺点:通常交换次数过多。

private static int[] OrderBy1(int[] array)

{

//1.取数据

for (int r = 0; r < array.Length - 1; r++)

{

//2.比较

for (int c = r + 1; c < array.Length; c++)

{

//3.发现更小则交换

if (array[r] > array[c])

{

int temp = array[r];

array[r] = array[c];

array[c] = temp;

}

}

}

return array;

}

 

  1. 选择排序:发现【最】小的则交换

    1. 图片

 

  1. 代码

 

private static int[] OrderBy(int[] array)

{

//1.取数据

for (int r = 0; r < array.Length - 1; r++)//轮

{

//2.查找最小索引

int minIndex = r;//假设下当前元素就是最小索引

for (int c = minIndex +1; c < array.Length; c++)//次

{

//发现更小的元素

if (array[minIndex] > array[c])

{

//记录位置(替换假设的最小索引)

minIndex = c;

}

}

//3.交换

if (minIndex != r)

{

int temp = array[minIndex];

array[minIndex] = array[r];

array[r] = temp;

}

}

return array;

}

 

 

  1. 2048核心算法

 

//*******************2048核心算法*****************************************

/*需求分析1.0

1.向上移动

--- 获取列数据,形成一维数组

* --- 去除零元素(将非零元素向前移动)

* ---合并数据

* -- 如果相邻元素相同

* -- 将后一个元素累加到前一个元素上

* -- 将后一个元素清零

* --- 去除合并过程中产生的零元素(将非零元素向前移动)

* --- 还原列数据

*

2.向下移动

--- 获取列数据,形成一维数组

* --- 去除零元素(将非零元素向后移动)

* ---合并数据

* -- 如果相邻元素相同

* -- 将前一个元素累加到后一个元素上

* -- 将前一个元素清零

* --- 去除合并过程中产生的零元素(将非零元素向后移动)

* --- 还原列数据

 

*

需求分析2.0

1.向上移动

--- 获取列数据(从上到下),形成一维数组

--- 调用合并数据方法

* --- 还原列数据(从上到下)

*

2.向下移动

--- 获取列数据(从下到上),形成一维数组

--- 调用合并数据方法

* --- 还原列数据(从下到上)

*

3.合并数据

* --- 调用去除零元素

* ---合并数据

* -- 如果相邻元素相同

* -- 将后一个元素累加到前一个元素上

* -- 将后一个元素清零

* --- 调用去除零元素

 

4.去零方法(将非零元素向前移动)

*/

 

  1. 答案

 

  1. 移动零

private static void RemoveZero(int[] array)

{

//创建新数组0 0 0 0

int[] newArray = new int[array.Length];

int newIndex = 0;//新数组索引

//将参数中非零元素,依次存入新数组2 2 2 0

for (int i = 0; i < array.Length; i++)

{

if (array[i] != 0)

{

newArray[newIndex++] = array[i];// 存入 自增

}

}

//返回新数组

//return newArray;

//array = newArray;//修改栈中引用

newArray.CopyTo(array, 0); //拷贝元素 array[0] = newArray[0];

}

 

  1. 合并相同项

private static void Merge(int[] array)

{

RemoveZero(array);//2 0 2 2 --> 2 2 2 0

//合并数据

for (int i = 0; i < array.Length-1; i++)

{

//非零 且 相邻相同

if (array[i] !=0 && array[i] == array[i + 1])

{

array[i] += array[i + 1];

array[i + 1] = 0;

}

}

RemoveZero(array);

//return array;

}

  1. 向上移动

 

private static void MoveUp(int[,] map)

{

int[] mergeArray = new int[map.GetLength(0)];

for (int c = 0; c < map.GetLength(1); c++)

{

//00 10 20 30

for (int r = 0; r < map.GetLength(0); r++)//从上到下 获取列数据

mergeArray[r] = map[r, c];

 

Merge(mergeArray);

 

for (int r = 0; r < map.GetLength(0); r++)//从上到下 还原列数据

map[r, c] = mergeArray[r];

}

//return map;

}

  1. 向下移动

private static void MoveDown(int[,] map)

{

int[] mergeArray = new int[map.GetLength(0)];

for (int c = 0; c < map.GetLength(1); c++)

{

//30 20 10 00

for (int r = map.GetLength(0) - 1; r >= 0; r--)

mergeArray[3 - r] = map[r, c];//正向存入一维数组

 

Merge(mergeArray);

 

for (int r = map.GetLength(0) - 1; r >= 0; r--)

map[r, c] = mergeArray[3 - r];

}

//return map;

}

  1. 输出显示

private static void PrintMap(int[,] map)

{

for (int r = 0; r < map.GetLength(0); r++)

{

for (int c = 0; c < map.GetLength(1); c++)

{

Console.Write(map[r, c] + "\t");

}

Console.WriteLine();

}

}

 

//移动 Move(1 , map)

//导医

  1. 移动

private static void Move(int direction,int[,] map)

{

switch (direction)

{

case 0:

MoveUp(map);

break;

case 1:

MoveDown(map);

break;

}

}

 

//目的:让2048算法使用者,可以只记忆一个Move方法。

  1. 移动重写

private static void Move(MoveDirection direction, int[,] map)

{

switch (direction)

{

case MoveDirection.Up:

MoveUp(map);

break;

case MoveDirection.Down:

MoveDown(map);

break;

}

}

  1. 主函数

static void Main()

{

int[,] map = new int[4, 4]

{

{ 2,4,0,4 },

{ 0,2,2,4 },

{ 2,0,0,2 },

{ 4,2,2,0 }

};

PrintMap(map);

Console.WriteLine("向上移动");

//MoveUp(map);//用户需要记忆的方法过多

//Move(0, map);//用户输入的方向不明确

Move(MoveDirection.Up, map);//限定了取值范围

 

PrintMap(map);

 

Console.WriteLine("向下移动");

//MoveDown(map);

Move(MoveDirection.Down, map);

PrintMap(map);

 

}

 

 

 

 

 

 

 

 

  1. 数据类型

 

  1. 类型图示

 

 

 

 

  1. 值类型和引用类型图示

 

 

 

 

 

 

 

 

 

 

Int[] arr;//在栈中声明。A为位地址

arr= new int[]{1}

 

 

 

 

 

 

 

 

 

 

  1. 没有【】就是改栈(重新开辟空间,附地址),有就是改堆。

String a="1"

String b=a

B="5"

S2="1"

 

 

 

 

  1. 面试:Stringbuilder与string的区别于优越性差异

 

 

 

 

 

 

  1. 应用1:赋值

 

  1. 图示

 

 

 

  1. 代码

static void Main3()

{

//方法执行在栈中

//方法内部声明的变量,都在栈中分配空间。

int a;//在栈中

a = 1;//数据1在栈中( 因为值类型直接存数据 )

int b = a;//a将存储的数据赋值b

a = 2;//修改栈中存储的数据

Console.WriteLine(b);//?

 

//arr:数组的引用

int[] arr;//在栈中

arr = new int[] { 1 };//数组对象在堆中(引用类型数据在堆中)

int[] arr2 = arr;//arr将存储的引用赋值给arr2

//arr[0] = 2;//修改堆中存储的数据(数组对象)

arr = new int[] { 2 };//修改栈中存储的引用

Console.WriteLine(arr2[0]);//?

 

string s1 = "老王";

string s2 = s1;//s1将存储的引用赋值给s2

s1 = "老宋";//修改栈中存储的引用,重新开辟空间存储"老宋",替换栈中引用

Console.WriteLine(s2);//?

 

object o1 = 100;

object o2 = o1;//将o1存储的引用赋值给o2

o1 = 200;//修改栈中存储的引用,重新开辟空间存储200,替换栈中引用

Console.WriteLine(o2);//?

}

 

  1. 应用2:比较

 

 

  1. 图示

 

 

 

 

 

  1. 代码

static void Main4()

{

//值类型存数据,比较数据

int a = 1, b = 1;

bool r1 = a == b;//比较数据1

Console.WriteLine(r1);//true

 

//引用类型存引用,比较引用

int[] arr01 = { 1 }, arr02 = { 1 };

bool r2 = arr01 == arr02;//比较数组引用

bool r3 = arr01[0] == arr02[0];//比较数组元素

Console.WriteLine(r2);//?

}

 

  1. 应用3:传参

 

  1. 图示

 

 

 

 

  1. 代码

static void Main5()

{

int a1 = 1;

int[] arr1 = { 1 };

Fun1(a1, arr1);//a1将存储的数据1、arr1将存储的引用 传入方法

Console.WriteLine(a1);//?1

Console.WriteLine(arr1[0]);//?2

 

int a2 = 1;

Fun2(ref a2);//将a2自身地址传入方法

Console.WriteLine(a2);//2

 

//区别2:输出参数进入方法前可以不赋值

int a3;//意图:接收方法的结果

Fun3(out a3);//将a2自身地址传入方法

Console.WriteLine(a3);//2

}

 

 

  1. 方法参数:值参数、引用参数、输出参数

根据传递方式进行的划分。

  1. 值参数:按值传递 --- 传递实参变量所存储的内容

作用:传递信息

 

局部变量:在栈中,全局变量,不在

方法内种局部变量,为

private static void Fun1(int a,int[] arr)

{

//结论:引用类型,方法内部修改堆中数据,影响实参。

a = 2;

arr[0] = 2;//堆中数据

//arr = new int[] { 2 };//修改栈中引用

}

 

  1. 引用参数:按引用传递 --- 传递实参变量自身引用(内存地址)

//作用:改变数据

private static void Fun2(ref int a)

{//方法内部修改形参,等同于修改实参

a = 2;

}

 

  1. 输出参数:按引用传递 --- 传递实参变量自身引用(内存地址)

//作用:返回结果

private static void Fun3(out int a)

{//区别1:方法内部必须修改输出参数

a = 2;

}

 

static void Main6()

{

int num01 = 1, num02 = 2;

SwopNumber(ref num01, ref num02);

 

int area,per;

CalculateRect(10, 20, out area, out per);

 

 

string input = Console.ReadLine();

//int atk = int.Parse(input);

 

//尝试着转换,如果成功通过输出参数返回结果。

// 如果失败,可以通过返回值获取结果。(木有异常)

int result;

if (!int.TryParse(input, out result))

{

Console.WriteLine("失败喽");

}

}

 

 

  1. 应用练习

    1. 交换两个整数

  1. 矩形面积

 

 

 

  1. 装箱yu拆箱

 

 

 

 

 

面试:发生拆装箱的数目

例子:

ILspy

 

没有拆装箱,int number…….

 

Concat字符串拼接,本质是由concat,装箱。。。。。。结局方案。.Tostring

Int->object形参为object

 

如果形参object,实参值类型,产生装箱操作。

 

 

  1. 解决方案

1.

2.泛型:可以将数据类型作为参数传入。

Private static void Fun2<Type>(To){

}

调用:Fun2<int>(To);

 

//如果形参object类型,实参值类型。会产生装箱操作。

//解决方案:1.重载 2.泛型:可以将数据类型作为参数传入方法。

 

 

  1. String

 

 

  1. 特性1:字符串池(字符串常量)

// 节省内层

 

string s1 = "老王";

string s2 = "老王";

//s1 / s2 是同一对象

 

string s3 = new string(new char[] { '老', '宋' });

string s4 = new string(new char[] { '老', '宋' });

//s3 / s4 不是同一对象

 

 

 

 

  1. 特性2:不可变性

// 如果可变,就会破坏其他对象的内存空间

string s5 = "张飞";

s5 = "夏军军";//重新开辟空间 存储新字符串,替换栈中引用。

//s5[0] = '夏';

char c1 = s5[0];

Console.WriteLine(s5);//? "张飞" -改变-> "夏军"

 

string s6 = "老";

string s7 = s6 + "王";//"老王" 与 s1/s2 不是同一对象 "字符串变量参与的拼接,没有使用字符串池的特性"

 

string s8 = string.Empty;//""

for (int i = 0; i < 10; i++)

{

//每次拼接都会产生一个新对象,产生1个垃圾

s8 = s8 + i.ToString();

//"" + "0"

//"0" +"1"

//"01" +"2"

}

Console.WriteLine(s8);//?

 

 

 

  1. 可变字符串

 

 

 

 

  1. String和stringbuilder的优缺点

 

 

 

  1. 重点与练习