c#基础知识(2)

一、流程控制

可以通过某些特定的控制语句来控制代码的程序执行结构

顺序结构

顺序执行语句

分支结构

分支流程控制 ——> if-else,switch-case

if-else

注意点:

1、可以只有if没有else,反之则不行。

2、如果{}中只有一句执行语句时,{}可以省略。

eg:

//if-else语句
bool condition = true;
//if里面写bool类型的条件
if(condition){
    //如果if为true,执行
    Console.WriteLine("!");
}
else{
    //如果if为false,执行
    Console.WriteLine("!");
}
//实例
int score = 123;

if (score < 0)
{
	Console.WriteLine("负成绩");
}else if (score >= 0 & score <= 100)
{
	Console.WriteLine("合法成绩");
}
else
{
	Console.WriteLine("作弊了");
}

swith-case

注意点:

1、case捕获的值需要和witch的变量类型匹配

2、不允许出现多个case的值是一样的

3、关键字break

​ a、break有跳出作用,具有穿透性

​ b、在C#中,如果一个case后面没有语句,那么可以不加break保留穿透性

​ c、如果一个case后面有语句,那么break必须添加

eg:

//switch-case语句
int coondition = 1;
//小括号里面可以写任意的数据类型
//选择一个任意类型的变量,捕获特定的值,如果变量的值和捕获到的值是一样的,那么执行case语句后的代码。
switch (coondition)
{
    case 0:
        Console.WriteLine("condition的值是0");
        break;
    case 1:
        Console.WriteLine("condition的值是1");
        break;
    default: //用来捕获上面的case都没有满足的情况
        Console.WriteLine("以上都不对");
        break;
}

//实例
int season = 3;
switch (season)
{
    case 1:
        Console.WriteLine("春困");
        break;
    case 2:
        Console.WriteLine("夏打盹");
        break;
    case 3:
        Console.WriteLine("秋乏");
        break;
    case 4:
        Console.WriteLine("冬眠");
        break;
        
    //  测试
    //'a'不报错是因为字符型可以自动转换为整型(隐式转换)
    case 'a':
        Console.WriteLine("hello world");
        break;
    //报错是因为重复出现1
    case 1:
        Console.WriteLine("hello world");
        break;
    //这里的'1'也是字符型,所以不报错
    case '1':
        Console.WriteLine("hello world");
        break;
    //报错:1.1f不能隐式转换为整型,可以加强制转换为整型 case (int)1.1f:,但没必要,因为强制转换后就是1
    case 1.1f:
        Console.WriteLine("hello world");
        break;
    default:
        Console.WriteLine("适合学习的季节");
        break;
}

//关键字break
/*
 * break有跳出作用,具有穿透性,
 * 在C#中,如果一个case后面没有语句,那么可以不加break保留穿透性
 * 如果一个case后面有语句,那么break必须添加
 */
int month = 3;
switch (month)
{
    case 1:
        Console.WriteLine("31天");
        break;
    case 2:
    case 3://如果month=3,因为穿透性,最终结果为:31case 4:
    case 5:
        Console.WriteLine("31天");
        break;
}

//打印月份对应天数
int month = 2;
switch (month)
{
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
        Console.WriteLine("31天");
        break;
    case 4: case 6: case 9: case 11:
        Console.WriteLine("30天");
        break;
    case 2:
        Console.WriteLine("28天");
        break;
}
循环结构

循环流程控制 ——> for,while,do-while

for

注意点:

​ a、关键字break:结束循环(就算条件依然满足,也要终止循环)

​ b、关键字continue:跳过本次循环,进入下一循环

//for循环语句

//循环条件
/* 
 * for(循环的起点;循环的条件;循环的步长){
 * 如果循环的条件满足,那么这里的代码会重复执行
 * 这部分代码被称作——循环体}
 */
//小明从0跑到100米
for (int meter = 0; meter <= 100; meter++)
{
    Console.WriteLine("小明跑了" + meter + "米");
}
/* 
* 循环中的每部分的执行顺序:
* 1:int num = 2; 循环的起点
* 2:num <= 100; 循环的条件
* 如果条件成立:
* 3:循环体
* 4:循环步长
* 2:再次回到第二步判断条件
* 如果不成立:
* 3:结束循环
*/


//关键字break:在循环中表示结束一个循环
for (int i = 0; i <= 5; i++)
{
    if (i == 5)
    {//就算是循环条件依然满足,也需要结束一个循环
        break;
    }
    Console.WriteLine(i);//结果为0~4,后面的不再打印
}


//关键字continue:跳过本次循环,进入下一次循环
for (int j = 0; j <= 10; j++)
{
    if (j == 5)
    {//结束本次循环,然后进入下一次的循环
        continue;
    }
    Console.WriteLine(j);//结果为0~10,但是没有5,原因是到等于5时,跳过了本次循环输出,直接到一下次
}


//eg1:循环输出1~100的偶数
//第一种方式
for (int num = 0; num <= 100; num++)
 {
     if (num % 2 == 0)
     {
         Console.WriteLine(num);
     }
 }
 //第二种方式
 for (int num = 0; num <= 100; num += 2)
 {
     Console.WriteLine(num + 2);
 }
//第三种方式
for (int m = 1; m <= 100; m++)
{
    if (m % 2 == 1)
    {
        continue;
    }
    Console.WriteLine(m);
}

//eg2:输出1+2+3+……+100的和
int sum = 0;//为例=l储存遍历到的数字的和
for(int num = 1;num <= 100; num++)
{
	sum += num;
}
Console.WriteLine(sum);


//死循环
//第一种
for (int i = 0; i < 10; i += 0)//没有步长
{
	Console.WriteLine("Hello World");
}
//第二种
for ( ; ; )
{
	Console.WriteLine("Hello World");
}


while

注意点:

​ while小括号中的循环条件为真,执行循环体。

//while循环语句
//语法
//while的小括号中只需要写循环的条件
while (true)
{
	//循环体
}        

//eg:0到100的和
int i = 1;
int sum = 0;
while (i <= 100)
{
	sum += i++;// ==> sum = sum + i;i = i + 1
}
Console.WriteLine(sum);

do-while

注意点:

​ 在do-while语句中要先执行循环体然后才判断条件,不管条件是否成立都必须执行循环体

//do-while循环语句
//语法
do
{
    //循环体
} while (循环条件);

while与do-while两者区别

while:先判断循环条件是否满足,然后再决定是否循环

do-while:先执行一次循环体,然后再判断执行条件是否成立,决定是否继续下次循环

二、输出输出

write(输出语句):(与类型转换配合使用)

字符串转其他数据类型

Console.ToInt16() ——> short

Console.ToInt32() ——> int

Console.ToInt64() ——> long

Console.ToSByte() ——> sbyte

Console.ToSingle() ——> float

Console.ToDouble() ——> double

Console.ToDecimal() ——> decimal

Console.ToChar() ——> char

Console.ToBoolean() ——> bool

eg:

//字符串转其他的数据类型(凡是牵扯到字符串的转型都用concert)
String input = Console.ReadLine();//输入:12345
Console.WriteLine(input);//结果为:12345
int number = Convert.ToInt32(input);
Console.WriteLine(number+1);//结果为:12346

补充:Convert转换过程中输入的数值必须是符合类型的 。(int num =Console.ToInt32() 此时若输入3.14,执行后会出现异常:字符串输入类型不符。)

其他数据类型转字串

​ a、Concert.ToString() ——> string

​ b、使用字符串连接符+

eg:

//其他数据类型转字符串类型
//方式一
String str = Convert.ToString(3.14);
//方式二
str = 3.14 + "";

read(输入语句):

​ 1.Console.Read():从控制台读取一个字符

int result = Console.Read();
Console.WriteLine(result);

​ 2.Console.ReadKey():等待用户输入任何内容(请输入任意键)

ConsoleKeyInfo info = Console.ReadKey();

​ 3.Console.ReadLine():从控制台读取一行内容(unity中用的多)

String input = Console.ReadLine();
Console.WriteLine(input);

三、方法、函数

1.什么是方法

方法就是一个功能的集合,可以把程序中某段具有特殊功能的代码提取出来。

//引用命名空间
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//namespace命名空间 
namespace aVariable
{   
    class Program //class类 类名
    {
        //mian主函数:程序是从这里开始执行的
        static void Main(string[] args)// 静态修饰符(static) 类型(void) 方法名字(mian)(形参列表){}
        {
            //方法体
        }

2.方法的声明

语法

​ [访问权限修饰符] [其他修饰符] 返回值类型 方法名 ([形参列表]) {

​ //(加[]表示可有可无)

​ //方法体

​ }

//方法声明
static void MyFirstMethord()
{
	for (int line = 1; line <= 9; line++)
	{
		for (int colum = 1; colum <= line; colum++)
		{
			Console.Write($"{line}x{colum}={line * colum,-2} ");
		}
		Console.WriteLine();
	}
}

注意点

​ 1.方法与方法是平级的,不允许出现方法嵌套方法

​ 2.方法名是一个标识符,遵循大驼峰命名法

3.方法的使用(调用)

一个方法体中的代码如果需要被执行,那么需要调用这个方法

语法:方法名();

static void Main(string[] args)
{
	//如何调用一个方法?
	MyFirstMethord();
}

4.参数

a、参数是什么

其实就是一个变量,在调用方法时候,需要给方法中所有的形式参数赋值

static void Main(string[] args)
{
    //调用方法时,10给a进行赋值
	Test(10);
    Test2(10, 1.1f, 3.14, 'a');
    Test3();//此时默认a的初始值为10,若此时Test3(100),则a的值为100,新赋值将覆盖原来的值。
    Test4(10);//此时10的值赋值给了a
    Test5(30, 40);//此时30的值赋值给了a,40的值赋值给了b(按顺序覆盖初始值),并且不能跳过b的值直接赋值给c
}
//a被称作 ——> 形式参数 ——> 形参
//调用方法的时候传的参数被称作 ——> 实际参数 ——> 实参(10)
static void Test(int a)
{
    Console.WriteLine(a * a);//结果为:100
}

static void Test2(int a, float b, double c, char d)
{
    Console.WriteLine(a);//10
    Console.WriteLine(b);//1.1f
    Console.WriteLine(c);//3.14
    Console.WriteLine(d);//a
}

static void Test3 (int a = 10){
    Console.WriteLine(a);//结果为:10
}

static void Test4(int a, int b =1)
{
	//形参列表中如果存在没有被初始化的值(int a),那么该值必须放在已被初始化的值之前(int b = 1)。
}

static void Test5(int a, int b = 10, int c = 20) 
{ 
    //若有初始值,则按顺序覆盖值
}

b、局部变量和全局变量

变量可以分为局部变量和全局变量

局部变量:书写在方法或者一个代码段内的变量

全局变量:书写在类中,与方法平级的变量

c、变量的作用域

变量作用域:表示一个变量能够被访问的范围。

一般来说,局部变量的作用域为:从声明开始,到声明所在的大括号{}结束。但在for循环中,循环起点定义的变量仅在for循环中生效。

d、交换变量(坑)

static void Main(string[] args)
{
	//交换变量
	int x = 10, y = 20;
	Swap(x, y);
	Console.WriteLine($"x = {x},y = {y}");//结果为:x = 10, y = 20
 	/*
 	 * x和y的值不能交换是因为,在程序执行中Main方法先进行压栈并调用Swap方法,
  	* 在调用时,只是把x和y的值复制了一份给a和b,其本身x = 10,y = 20并没有改变,
  	* 当a和b的值在Swap方法中交换完之后,Swap方法也调用执行完成,并且出栈,
  	* 而此时x,y的值并没有发生改变。
  	* 因此得到的结果中a,b的值进行了交换;而x,y的值没有进行交换。
  	*/
}

//交换变量
static void Swap(int a, int b)
{
	int c = a;
	a = b;
	b = c;
	Console.WriteLine($"x = {a},y = {b}");//结果为:x = 20, y = 10
}

变量交换不成功

5.返回值

什么是返回值

返回值:就是一个方法执行的结果。

void

不是数据类型,表示空,没有返回值。

如果一个方法不需要执行结果,这个方法的返回值类型可以设计为void。

return

return具有两层含义

​ 1.将后面的值作为方法的执行结果返回

​ 2.结束方法

注意事项

​ 1.如果一个方法的返回值不是void,那么在这个方法结束执行之前,必须有一个具体的返回值。

​ 2.如果一个方法中有分支,那么必须保证每一个分支上都有返回值。

​ 3.返回值的类型必须和具体的返回值的类型要匹配(可以有隐式转换的存在)。

​ 4.在返回值类型为void的方法中是可以使用return的。

static void Main(string[] args)
{
	//返回值
	//计算数字和并将结果传给main数
	/* int result = Add(10, 20);
  	 Console.WriteLine(result);*/
	Console.WriteLine(Add(10,20)); //结果为:30
    
    int result = Add2(10,20);
    Console.WriteLine(result);
    
	int result = Add3(10,20);
    Console.WriteLine(result);//报错!返回值类型不匹配
    
    Add4();
}


static int Add(int a,int b)
{
	int c = a + b;
	//return:将后面的值作为方法的执行结果
	return c;
	//return后面的代码将不再执行
	Console.WriteLine("Hello World");
}

static int Add2(int a,int b)
{
    if(a > b){
        return a - b;//其中一个分支有返回值,其他分支也必须有返回值
    }else{
        return a + b;
    }
}

static int Add3(int a,int b)//会报错是因为返回值类型不能转换
{
    return "Hello World";
}

static void Add4()//void型也可使用return,结束方法
{
    return;
}

6.方法的重载(OverLoad)

在一个类中,有多个方法满足以下几个条件,那么这些方法之间是重载关系:

​ 1、方法名相同

​ 2、参数不同(数量不同,类型不同,类型顺序不同)

​ 3、跟返回值,返回权限,权限状态没有关系,

如何区分调用不同的方法:通过实参来区分

作用:简化代码

7.递归

递归就是指方法循环调用,合理使用递归可以很方便的做一些事情。

递归使用到后面会越来越慢。如果没有出栈的机会最后会导致栈溢出

使用递归注意事项:一定要留有出栈的时机(使用递归找出口)

用法:

//递归(递归相当于变相的循环,也容易造成死循环,使用时必须留有出口)
static void Main(string[] args)
{
	Show();
}
static void Show()
{
	Console.WriteLine("show");
	Show();
}

eg:菲波那切数列

static void Main(string[] args)
{
	//eg:
	//1、打印前三十位的菲波那切数列
	for (int index = 1; index <= 30; index++)
	{
    	Console.WriteLine(GetNumberByIndex(index));
	}

	//2、打印菲波那切数列指定位数字
	Console.WriteLine(GetNumberByIndex(Convert.ToInt32
                                       (Console.ReadLine())));
}

//eg:求斐波那切数列的指定位数字

//参数index:要获取的哪一位的数字
//返回值:index对应的数字
static int GetNumberByIndex(int index)
{   
    //是递归的出口
    if (index == 1 || index == 2)
        return 1;
    //获取前两位的数字的和
    return GetNumberByIndex(index - 2) + GetNumberByIndex(index - 1);
}

四、ref/out关键字

ref关键字

ref是用来修饰参数的:

​ 1、如果一个形参用ref来修饰了,那么对应的实参也得用ref来修饰

​ 2、在传参的时候,传递的其实是实参的地址而不是实参的值

eg:两数交换
ref关键字交换变量

static void main(String[] args)
{
    //ref关键字
	//设计一个方法交换两个变量的值
	int x = 10, y = 20;
	Swap(ref x, ref y);
	Console.WriteLine($"x = {x},y = {y}");
}

static void Swap(ref int a, ref int b)
{
    //int c = a;
    //a = b;
    //b = c;

    a = a ^ b;
    b = a ^ b;//b = a ^ b ^ b;
    a = a ^ b;//a = a ^ b ^ a ^ b ^ b;

}

out关键字

out关键字主要作用:out方法里面的值给方法外面的变量去赋值的

out用来修饰参数的:

​ 1、如果一个形参用out来修饰了,那么对应的实参也得用out来修饰

​ 2、out修饰的参数在传参的时候,传递的是实参的地址

static void mian(String[] args)
{
    int x = 5;
	Change(out x);
	Console.WriteLine(x);
}

static void Change(out int a)
{
    a = 10;
    Console.WriteLine(a);//必须在赋值之后打印,因为加out关键字后,a默认为赋值状态
}

ref与out的区别

1、在方法结束之前必须对out参数必须进行赋值,类似返回值,而ref没有这个要求

2、ref参数可以直接使用,是默认有值的,指向实参的值,而out参数默认是未赋值的状态,不能直接使用

3、如果方法一个接受ref关键字,而另一个接受out关键字,那么方法将不能重载

五、数组操作

排序

选择排序

原理:选择一个下标,然后用这个下标对应的元素依次和后面的每一个元素进行比较
选择排序

static void main(String[] args){
    //数组排序
	//1、选择排序
	//原理:选择一个下标,然后用这个下标对应的元素依次和后面的每一个元素进行比较
	int[] array = { 1, 2, 13, 46, 57, 67, 4 };
	Sort01(array);
	foreach (int item in array)
	{
    	Console.Write(item + ",");
	}
}

    //使用选择排序来对一个数组进行升序排序
static void Sort01(int[] array)
{
    //外层循环用来遍历需要和后面所有的元素比较的下标
    for (int i = 0; i < array.Length - 1; i++)
    {
        //内层循环的下标依次和外层的下标进行比较
        for (int j = i + 1; j < array.Length; j++)
        {
            //交换的条件
            if (array[i] > array[j])
            {
                //如果前面的元素大就交换元素
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}

冒泡排序

原理:依次比较两个相邻的元素
冒泡

//2、冒泡排序
#region
//原理:依次比较两个相邻的元素
int[] array = { 1, 2, 5, 3, 4 };

Sort02(array);
foreach (int item in array)
{
    Console.Write(item + ",");
}

//使用冒泡排序对数组进行升序排序
static void Sort02(int[] array)
{
    for (int i = 0; i < array.Length; i++)//循环的趟数
    {
        //每比较完一趟就一定会有一个较大的数被排好所以循环的条件是:j < array.Length - i - 1
        for (int j = 0; j < array.Length - i - 1; j++)//每趟循环的次数
        {
            if (array[j] > array[j + 1])
            {
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

查找

顺序查找
从数据的第一个元素开始,依次比较,直到找到目标数据或查找失败。

/*
1.从表中的第一个元素开始,依次与关键字比较。
2.若某个元素匹配关键字,则 查找成功。
3.若查找到最后一个元素还未匹配关键字,则 查找失败。
*/
public class Program {
    public static void Main(string[] args) {
        int[] array = { 10, 19, 21, 67, 99, 110, 920, 1000 };
        Console.WriteLine(SequentialSearch(array, 80));
        Console.ReadKey();
    }
    private static int SequentialSearch(int[] array, int key) {
        for (int i = 0; i < array.Length; i++)
            if (array[i] == key)
                return i;
        return -1;
    }
}

二分查找

前提条件:数组需要是排序的

原理:每次查找指定范围的中间值

int[] array = { 10, 19, 21, 67, 99, 110, 920, 1000 };
int index = -1;//表示查找到的元素的下标

//确定一个要查找的下标范围
int min = 0;
int max = array.Length - 1;
while (max >= min)//确保数组有元素 循环条件:极限状态下max = min 表示数组只有一个元素
{
    int mid = (min + max) / 2;

    if (array[mid] == 920)
    {
        index = mid;
        break;
    }
    else if (array[mid] > 920)
    {
        max = mid - 1;//查找范围缩小到一半,即范围改变成(0~中间值的前一个数)
    }
    else
    {
        min = mid + 1;//查找范围缩小一半,即范围改变成(中间值的后一个数~max)
    }
}
onsole.WriteLine(index);

六、栈和队列

在栈和堆上但凡是用来存引用的,地址的都是8字节。(例如:String——引用类型8字节)
栈和队列
1.一个方法如果需要被执行,那么这个方法需要被压到栈中执行。

压栈(push)出栈(pull)

2.一个方法中的代码如果执行完毕,那么这个方法自动出栈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值