C#学习笔记(二十):C#总结和月考讲解

m1w1d2_console_variable_constant

输入Console.WriteLine();
输出Console.ReadLine();

快捷键
折叠代码:快捷键“Ctrl+ K + S”
隐藏当前代码:组合键“Ctrl + M,M”
显示全部代码:组合键“Ctrl + M,L”
注释:组合键“Ctrl + K + C”;
取消注释:组合键“Ctrl + K + U”
批量操作:按住Alt选择一片区域,前段会有蓝线

快捷写法
Console.WriteLine();CW + 双击T
switch语句快速生成枚举方法,复制枚举名在switch()里,双击TAB
for循环,按两下TAB
i++:for+按两下TAB
i--:forr+按两下TAB

变量名命名要求
1、变量名头必需以字母或下划线"_"开头
2、变量名体只能是数字,字母,下划线的组合
3、不能使用编程语言的关键字
4、在作用域内,不能同名

命名是有法则的
1、命名要有意义(概括变量里数据的规律)
2、变量使用驼峰命名法(除了第一个单词首字母小写,其余单词首字母全大写)
3、类与方法使用帕斯卡命名法(每个单词的首字母都大写)

1、定义一个变量:数据类型 变量名;
2、给变量赋值:变量名 =(赋值符号) 值(数据)

常量:
const 数据类型 常量名
命名法则:全大写,单词之间用下划线分隔
常量在定义时一定要赋值(初始化赋值)
常量的值不可以更改

m1w1d2_ide

关闭番茄插件的拼写纠错,Visual Assist Options的Underlining
调整行号:工具-选项-文本编辑器-C#-行号
调整主题:工具-选项-环境-常规-颜色主题-深色
调整字体:工具-选项-环境-字体颜色(推荐字体Consolas)

取数据类型的长度:sizeof()
基础数据类型所占字节:

ASCII表
0-948-57
A-Z:65-90
a-z:97-122

字符串格式化输出:
Console.Writeline($"最大值{max}");
$符号,{}里可以直接填变量

显式转换:
Convert:用于所有基本类型之间的转换
Convert.ToInt16('A');

Parse:将字符串转换成一个特定类型
int.Parse(Console.ReadLine());

强制转换符:用于数值类型(整型,浮点型,char)和派生(继承)之间的转换
int a = (int)'a'

m1w1d4_operator

条件运算符:第一表达式?第二表达式:第三表达式
第一表达式必须是布尔表达式
第二和第三表达式必须和接收的类型一致
如果第一表达式为true时,返回第二表达式结果
如果第一表达式为false时,返回第三表达式结果

m1w1d5_randomnumber

随机数
Random roll = new Random();
roll.Next(-10 , 11);

m1w2d2_complex_datatype

基本数据类型
1、定义变量,2、使用变量
复杂数据类型
1,定义类型,2、定义这个类型的变量、2、使用变量

枚举:一般情况我们用枚举来表示一组状态的集合
定义类型 一般情况下我们都放在类外面定义
enum 自定义枚举名
{
成员(枚举项),
成员(枚举项),
}
每个枚举项都可以赋整数值
如果没有赋值,他的值是前一枚举项的值+1
第一个枚举项如果不赋值,默认值0
赋值原因:给枚举项建立数学联系(属性相克)
定义这个类型的变量时,枚举的值,只能是所规定的枚举项
自定义枚举名 变量名 = 自定义枚举名.某一枚举项

枚举转字符串:对应的变量,调用toString()方法,可以将枚举转字符串
字符串转成枚举:(Occupation)Enum.Parse(typeof(Occupation), "道士");

m1w2d3_array

1、定义一个数组变量
数据类型[] 变量名;
int[] array;
数据类型[] 变量名 = {成员,成员};
int[] array1 = { 1, 2, 3, 4, 5 };//不指定元素个数,只指定元素
int[] array2 = new int[8] { 1, 2, 3, 4, 5, 6, 7, 8 };//先限制元素个数,然后再指定元素
数据类型[] 变量名 = 指定的长度空数组。
int[] array3 = new int[8];//最常用的形式,不关心值,只关心处理逻辑
元素的值是默认值(微软MSDN默认值)
数值类型是对应0
如果字符串是" "

2、使用数组
访问成员,通过下标 变量名[下标号]访问对应下标的成员
array1[2] = 100;
Console.WriteLine(array1[2]);
如果我使用的下标是负数,或者超出了元素个数,指定了数组中一个不存在的元素
会出现 越界异常
下标的有效范围是(0 - 数组名.Length-1)
Console.WriteLine(array1.Length);
Console.WriteLine(array1.[array1.Length - 1 ]);
通过数组名.Length我们能知道这个数组中有多少个元素

3、遍历数组
遍历就是从一个 数据结构 第一个元素 到 最后一个元素
遍历就是把 数据结构中 所有元素访问完

Length:取数组元素的总个数
GetLength:取不同维度的个数

m1w2d3_struct_array

结构体
用途:一般情况下我们使用结构体来描述复杂事物,如桌子,如位置
这个复杂事物不能包含自己,会发生递归调用
结构体用于:属性不多,频繁计算的复杂事物
结构体储存在栈里,运行速度快,但栈里的空间宝贵,所以用来描述的事物不宜过多(<=5)(也可以不放在栈里,运算不用跳地址)
一般用于定义常用的数学概念及其需要计算的结果

定义结构体的类型
struct 自定义类型名{成员;成员;}
成员之间用分号隔开
成员是其它数据类型
成员需要外部访问要用public

定义结构体的变量
数据类型 变量名 = 初始值;
Student xiaoMing = new Student();//一次性给结构体里所有变量附初值


数组 冒泡排序
//1、先写内循环,循环次数为:数组长度-1-外循环当前次数
//2、内循环每次对比当前位置与下一位置,如果逻辑(当前位大于对比位)达成 则交换位置
//3、外循环,循环次数为 数组长度-1
for (int i = 0; i < array.Length - 1; i++)
{
for (int j = 0; j < array.Length - 1 - i; j++)
{
if (array[j] > array[j + 1])
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}

二维数组也是解决重复数据的重复逻辑,不同的是他允许我们通过两(多)个下标
为什么用多个下标,人们在生活,经常需要处理二维的数据,地图,表单(纯三维数据特别的少)
本质上,内存中一维和二维数组是一样的

使用二维数组
定义二维数组
不指定元素
数据类型[,] 变量名;
指定元素
数据类型[,] 变量名 = new 数据类型[标号为0维度的元素个数,标号为1维度的元素个数]
数据类型[,] 变量名 = new 数据类型[行数,列数]
数据类型[,] 变量名 = new 数据类型[x,y]

交错数组与多维数组的区别
交错数组理论上才是数组的数组
1、多维数组必须是每一个维度的元素个数相等,多维数组只能表示矩形数据块
交错数组可以表示锯齿数据块
2、多维数组必须是指定每一个维度的元素个数
交错数组只能指定最外层的数组个数
3、多维本质上是一块连续内存空间,为什么是多维表示,为了人们方便去理解,多维和一维只是索引器不一样
交错数组理论上才是数组的数组

定义一个交错数组
数据类型[][]变量名;
数据类型[][]变量名 = new 数据类型[4][]{new int[10],new int[5],new int[10],new int[5],}
数据类型[][]变量名 = new 数据类型[4][];

m1w2d6_debug

string.IsNullOrEmpty(s);//判断字符串是否为空

String.Split

1、用字符串分隔:
string str1 = "aaajsbbbjsccc";
string[] sArray1 = Regex.Split(str1, "js", RegexOptions.IgnoreCase);
foreach (string i in sArray1) Console.Write(i.ToString() + "\r\n");
Console.WriteLine("\r\n");

2、用单个字符来分隔:
string str3 = "aaajbbbjccc";
string[] sArray3 = str3.Split('j');
foreach (string i in sArray3) Console.Write(i.ToString() + "\r\n");
Console.WriteLine("\r\n");

3、用多个字符来分隔:
string str2 = "aaajbbbscccjdddseee";
string[] sArray2 = str2.Split(new char[2] { 'j', 's' });
foreach (string i in sArray2) Console.Write(i.ToString() + "\r\n");
Console.WriteLine("\r\n");

SubString 方法:
string str = "abcdefgh";
Response.Write(str.Substring(0, 1));//return:a
Response.Write(str.Substring(2, 3));//return:cde
Response.Write(str.Substring(7, 1));//return:h
Response.Write(str.Substring(7));//return:h
Response.Write(str.Substring(10));//error:startIndex 不能大于字符串长度。
Response.Write(str.Substring(7, 10));//error:索引和长度必须引用该字符串内的位置。

m1w2d6_function_flyingchess

函数是对逻辑(语句序列)的封装,方便以后重复使用
函数的签名{函数体}
指令逻辑(什么指令) 对谁(参数) 做什么(函数体) 结果如何(返回类型)
参数 可以是任意类型
函数体 可以是任意语句
返回类型 可以是任意类型 void(无返回类型)
如果指定了返回类型 必须有相应的返回值
使用return可以返回一个值,并结束函数
如果你使用了void,也可以使用return,这时,他不再返回值,但结束函数
 
返回类型 函数名 (参数列表)
{
函数体
}

m1w3d1_function_parm_overload_oop

ref关键字
在定义方法时 使用 参数修饰 ref 我们可以传递一个地址
1,定义方法参数使用ref关键字,调用时同时也可使用
2,调用时,实际参数必须有被赋值

函数的重载
函数允许我们重名,重名函数在重载的情况下是允许的
参数列表不一样时构成重载
重载函数有助我们统一理解
1、参数个数不一样
2、类型和顺序不一样

递归的调用
函数递归 指 函数自身 调用自身的 一种算法
在算法没有写错的情况 所以他有可能会造成 堆栈溢出异常
一般用递归解决子问题就是父问题的问题

边界 在递归过程中,我们必须得有一种已知情况
边界参数要交给自己
边界参数要无尽的趋向边界

值类型与引用类型的存储方式:
引用类型:引用类型存储在堆中。类型实例化的时候,会在堆中开辟一部分空间存储类的实
例。类对象的引用还是存储在栈中。
值类型:值类型总是分配在它声明的地方,做为局部变量时,存储在栈上;类对象的字段时,
则跟随此类存储在堆中。

m1w3d2_class_oop

类的定义
程序中的类,是属性和方法的封装
定义的格式和结构一样,只是关键字不一样用class
成员不一样,类允许使用任意类型的成员

类到对象
通过实例化,我们可以将类实例化成某一个具体的对象
通过 new 关键字 结合构造函数 可以实例化 一个具体的对象
通过初始化,可以确保这个对象有自己专有的值
数据类型 变量名 = 初始化值;

对象
对象是类的一个实例
我们用this关键指向自己这个对象
某一个类的对象拥有这个类所有的属性和方法,换言之,一个类的对象和这个类的属性和方法是一致的
同一个类的对象一般表现为数据不同,而属性和方法是一致的

构造 - 被使用 - 析构
构造
实例化可以将一个类实例化成一个对象
Student xiaoMing = new Student();
实例化会在内存中开辟一块空间,然后初始化(对空间中的成员添值,添值的逻辑我们交给构造函数)

构造函数
构造函数只能写在本类里
和函数大体一致
1、没有返回类型
2、函数名和类名一致
构造函数允许我们重载
当你不写构造函数时,会有一个默认构造存在
一旦重载,默认构造就会消失
一般情况下,我们会保留默认构造,再写一个默认构造(无参构造)
通过重载构造 我们可以对对象赋予不同的数据
通过this关键字,我们可以用一个构造函数 调用 另一个构造
一般情况下有多个构造 我们就用直接指向参数最多的构造
Student():this("小明"18"")

结构体与类的区别
1、结构体对象属于值类型,类对象属于引用类型
2、结构体中的字段不能赋初值 类中可以
3、结构体中不能显式定义无参构造函数,如果是重写了带参的构造函数,那么就需要对所有字段初始化
4、结构体放在栈里里,读写速度快,类放在堆里

类一般定义在命名空间下面
一种模板 这个模板就是用来创建对象的 通过这个模板可以创建对象的属性和方法
m1w3d3_attribute_inherit_visit
属性
1、和方法大体一样,返回类型不能是void,没有参数列表
如果你保护哪个字段,建议属性名用字段的帕斯卡命名法

2、属性块中由两个块组成get,set
get块在被使用(取值)时是被调用
set块在赋值时才会被调用
set get块可以由空语句替代
必须全部由空语句替代,或者没有set
get块和set块可以只有一个

3、get块必须有返回值,值类型与属性返回类型一致

4、在对应字段写入相应逻辑
属性的简写
get set块 可以是空语句,set块可以没有
这样的属性我们叫做自动属性,自动属性可以帮助我们快速实现一个自动属性
自动属性有保护的字段

m1w3d4_inherit

继承
如果我们定义了若干类,这些类都有一些共有的属性和方法
我们可以把这些共有部分抽象建立一个新的类,作为基类
已解决我们代码重复的问题,以便于管理
如果继承关系建立,子类的构造函数将会默认指向父类的无参构造
我们可以通过this调用自身的另一个构造函数
我们可以通过base调用父级的构造函数
继承:子类继承的是父类所有成员
但是你只能访问父类成员作用域允许的成员,除了private
如果你的成员需要外部访问,只能是public

里氏转换
1、子类(Reporter)可以当父类(Person)用
一个对象的实际类型是指他被构造出来时的类型
2、如果父类中的实际对象是子类,我们可以将其转成子类
is关键字 可以帮助我们判定一个对象中是否包含另一个对象类型
对象 is 包含的类型
as关键字 尝试性转换,如果转换成功则返回对应类,不成功则返回null
对象 as 尝试转换的类型

m1w3d5_virtual

多态 用虚方法实现
多态实现 真的鸭子嘎嘎叫,木头鸭子吱吱叫,橡皮鸭子唧唧叫
多态 不同的实际对象,在同一个指令(叫),有不同的表现
不同的对象,如何统一管理 里氏转换:可以把子级当父级 如果这些不同的对象全继承自一个父类
统一管理 如果把子级转换成了父级,子级的特性丢失了

用虚方法可以 用父级管理并且保留子级的特性 已解决问题
1,在实例方法前加 virtual
2,在派生类中用 override 重写 同名/同签名的方法
在一个虚方法被调用时,会根据最后重写的那个方法和实际类型来决定
不会根据当前类型来执行方法

m1w4d1_abstract

抽象函数、抽象类
多态实现 写一个动物的 抽象类,写两个子类狗狗叫,猫猫叫

Animal类Cry方法里写具体实现的问题:写什么都不合适
实例化 一个 animal的对象 他指代现实中 哪种对象 无法解释
如果有以上情况,我们可以用抽象函数,以便管理,以提高代码可读性

抽象函数
抽象函数用abstract关键字修饰
抽象函数只能存在于抽象类中
抽象函数不允许你实现,不需要写函数体,用空语句代替

抽象类
一个用abstract关键字修饰过的类,我们叫抽象类
抽象类中可以有抽象成员,也可以有普通成员
继承了抽象类的派生类,必须实现抽象类所有的抽象成员
抽象类不允许我们实例化,但是有构造函数并且可以重载

所以我们在写一个程序结构或者框架的时候会用到抽象类
m1w4d1_interface
不同对象 可以使用同一方法 表现不同行为
这些对象要同一个结构(数组)里 管理结构(容器)

如果多个接口出现了同名的成员,在实现的时候,默认是共用的
如果你想区分不同接口的不同方法,我们可以使用接口的显示实现
接口名.成员名
显示实现的成员必须由接口类型调用

1,多继承
2,多态

和类大体一致,关键字interface
成员没有实现,函数是没有函数体,用空语句,属相必须是自动属性
成员只能是属性,函数,事件,索引器
成员必须是public,不用写,也不能写

访问修饰 关键字 接口名{}
接口名 命名 一般以 I 为前缀

接口使用:
我们可以用一个类来继承已经定义好的接口:一对一,一对多,接口之间可以相互继承
如果在继承关系中,这个类有继承其它类,这个基类要放在继承的第一位
继承一个接口必须实现这个接口所有成员
能让我们把物品按特定的功能统一管理

m1w4d2_indexes

索引器
索引器可以让我们通过不同的索引号返回对应类型的多个属性
索引器适用于除自动属性以外的所有属性特性
索引号可以是任意类型
索引器在通过类对象来访问和赋值 变量(类对象)[索引号]
访问修饰 返回类型 this[索引号,索引号,索引号,索引号......]
{ get {return} set {value} }

静态构造函数什么时候调用
当我们访问静态成员的时候,先调用且只调用一次
当我们创建对象的时候,先调用且只调用一次
可以对静态字段做初始化使用的,静态的成员才会加载到内存中

m1w4d2_operator

重载运算符
返回类型?,函数名(operator 运算符)?参数?
public static i = i + 1;
两个参数,任意类型
返回类型,任意类型
算数运算符 是双目运算符,参数必须是两个,任意类型,返回类型,任意类型
关系运算符 是双目运算符,参数必须是两个,任意类型,返回类型是bool

m1w4d3_delegate

委托
委托类型的定义
委托是一个引用类型,存放着一个或者一组方法的引用
方法的签名
访问修饰 关键字(delegate) 对应方法的签名(返回类型 委托名 参数)

委托类型的定义
MyDelegate myDelegate;//这种形式用的比较多
MyDelegate myDelegate1 = new MyDelegate(Max);//这种形式用的比较少

赋值
将委托的委托列表清空,然后将赋值的函数注册到委托列表
如果我们将一个函数赋值到委托
这个委托被调用时,等同与函数被调用
赋值只需要函数(方法)名,不需要传参
myDelegate = Max;//用的比较少

注册
如果我们将一个函数注册到委托
相当于将函数注册到其委托列表
这个委托被调用时,将调用到这个注册函数
注册只需要函数(方法)名,不需要传参
myDelegate += Min;//用的比较多

注销
注册就是将一个函数从委托的委托列表中移除
仅移除最后一个注册的对应函数
如果委托列表中没有对应的函数不会报错
myDelegate -= Max;

调用
委托会将其 委托列表 中所有的函数按顺序执行
通过委托我们只能取得最后的执行的函数的返回值
委托调用时确定其参数,虽然委托中有多个函数,但只能使用一份参数
委托可以通过 变量名(参数)调用,变量名.Invoke(参数)
Console.WriteLine(myDelegate(3, 5));

作为参数的应用
委托可以做为另一个函数的参数使用
当一个函数使用了委托参数时
当其被调用时,我们可以直接放入一个对应委托,或者直接放入一个与委托同参同返回的函数参数

如果一个函数和委托的约束的签名一致
我们就可以把这个函数赋值或注册到委托

m1w4d3_delegate1

设计模式 在编程的过程中,前辈们为了解决特定的通用问题而总结出来的模式
单例模式
观察者模式 用于构建 事件处理系统
通过一个被观察者去管理观察者
被观察者 通过 事件(委托) 在状态改变时 调用所用注册过的 观察者方法

1、委托外部调用不安全
2、委托外部赋值不安全
3、私有化之后,外部成员无法注册

事件是对委托的进一步封装,约束了委托访问的作用域,允许事件在外部注册,但是不能赋值和调用
通过在一个委托的前面加上event关键字可以定义一个事件

m1w4d3_delegate3_lambert

匿名委托和lambert表达式

匿名委托
匿名委托只能作为委托的值被使用
缺陷
匿名委托可读性差,建议匿名委托语句行数不宜过多,一句最佳
匿名委托不可复用(违背封装原则)
delegate (参数) {函数体}
Sort(array, condition = delegate (int a, int b) { return a < b; });

lambert表达式(匿名委托的进一步简写)
lambert表达式只能作为委托的值被使用
缺陷
lambert表达式可读性差,建议匿名委托语句行数不宜过多,一句最佳
lambert表达式不可复用(违背封装原则)

lambert表达式可以让你不适用类型
lambert表达式如果函数体只有一句语句,可以省略花括号,不写return,不写分号;
lambert表达式在参数只有一个的情况下可以不用括号
(参数)=> {函数体}
Sort(array, (int a, int b) => { return a > b; });

m1w4d4_list

泛型集合
在我们要使用泛型集合时
首先我们要确认是否using System.Collections.Generic;

泛型列表
泛型列表允许我们做任意类型的列表,只需要在<>中填入相应类型
list.Capacity; Capacity表示列表的实际长度
list.Count; Count表示list中有多少个有意义的元素

添加元素
list.Add(123);

访问元素
通过索引器可以访问对应元素,但索引器的标号必须小于Count
Console.WriteLine(list[0]);
Console.WriteLine(list.Capacity);//初始为0.由Add创建

删除元素
list.RemoveAt(0);//移除指定下标中的元素
list.Remove(999);//移除指定元素(从头查找到的)

插入元素
list.Insert();//在指定下标处,插入指定元素,原元素及其后的元素均排在插入元素的后方
list.Insert(4, 999);

查找元素
从头查找
int id = list.IndexOf(999);//根据元素从头查找,并返回找到的第一个元素的位置
从尾查找
int id1 = list.LastIndexOf(8);//根据元素从尾查找,并返回找到的第一个元素的位置

m1w4d4_list1

泛型列表排序IComparable
用一个List排序
泛型集合都是实现System.Collections.Generic;中对应接口的一些类型
如果要实现一个自定义类的排序
1、实现一个IComparable的接口
2、调用Sort的重载,用一个接口类型IComparer
3、调用Sort的重载,用一个委托类型Comparition
需要一个和List装载的类型相同的一排序方法 int 函数名 (对应类型 对应类型)

m1w4d5_dictionary

声明变量
Dictionary<char, string> dic = new Dictionary<char, string>();

添加元素
dic.Add('1', "");
dic['2'] = "";

修改一个元素
dic['2'] = "";

如果用户输入的key不在我们的范围内,会报错
通过ContainsKey判定字典中是否包含了对应的key

m1w4d5_list1

泛型
定义
泛型是C#的一种特性,可以让我们将一种结构(类,接口)或者一种逻辑(函数)应用到所有类型
如果我们要把一个类型或者方法写成泛型的,我们只需要在名称后面加上<>,<>中可以填入若干个类型替代符

数学运算

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //要求用户输入一个年份,然后判断是不是闰年?
            //闰年判断
            //年份能被400整除(2000)
            //年份能被4整除,但是不能被100整除(2008)
            Console.WriteLine("请输入一个年份");
            int year = int.Parse(Console.ReadLine());
            bool conditionA = year % 400 == 0;
            bool conditionB = year % 4 == 0;
            bool conditionC = year % 100 != 0;
            string message = (conditionA || (conditionB && conditionC)) ? "是闰年" : "不是闰年";
            Console.WriteLine(message);
            //找出100内所有素数。素数 / 质数:只能被1和这个数字本身整除的数字,1不是质数, 最小的质数是2。
            //如果你遇到一个复杂,要抽象其子问题
            //子问题:某一个数是不是质数
            for (int j = 2; j <= 100; j++)
            {
                int num = j;
                for (int i = 2; i <= num; i++)
                {
                    if (i == num)
                    {
                        Console.WriteLine("{0}是一个质数", i);
                        break;
                    }
                    if (num % i == 0)
                    {
                        Console.WriteLine("{0}不是一个质数", i);
                        break;
                    }
                }
            }
            //求100 - 999之间的水仙花数,例如:153 = 1 * 1 * 1 + 5 * 5 * 5 + 3 * 3 * 3
            //取某一位等于这个数 余这个位的上一位,如取百位,余千,然后与本位相除,如百位,除一百
            //abc = a * a * a + b * b * b + c * c * c;
            for (int i = 100; i <= 999; i++)
            {
                int a = (i % 1000) / 100;
                int b = (i % 100) / 10;
                int c = (i % 10) / 1;
                if (i == a * a * a + b * b * b + c * c * c)
                {
                    Console.WriteLine(i);
                }
            }
            //老师问学生,这道题你会作了吗?如果学生答“会了(y)”,则可以放学,
            //如果学生不会做(n),则老师再讲一遍,再问学生是否会做了。。。
            //直到学生会了为止,才可以放学
            //直到学生会了或老师给他讲了10遍还不会,都要放学
            bool ok = false;
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("老师问:这道题你会作了吗?");
                Console.WriteLine("学生答:会了/不会做(y/n)");
                while (true)
                {
                    string ansanswer = Console.ReadLine();
                    if (ansanswer == "y")
                    {
                        Console.WriteLine("你真聪明"); ok = true; break;
                    }
                    else if (ansanswer == "n")
                    {
                        Console.WriteLine("老师又讲了一遍"); break;
                    }
                    else
                    {
                        Console.WriteLine("输入有误,请重新输入");
                    }
                }
                if (ok)
                {
                    break;
                }
            }
            Console.WriteLine("放学了");
            //在控制台上输出如下10 * 10的空心星型方阵
            //********** 画10个点*
            //**画第1个是 *,画第10个是 *,其他是空格
            //* *
            //**
            //**
            //**
            //**
            //**
            //**
            //**********
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    if (i == 0 || i == 9 || j == 0 || j == 9)
                    {
                        Console.Write("*");
                    }
                    else
                    {
                        Console.Write(" ");
                    }
                }
                Console.WriteLine();
            }
            //在控制台上输出如下10行的金字塔方阵
            //*
            //***
            //*****
            //*******
            //*********
            //***********
            //*************
            //***************
            //*****************
            //*******************
            //n 2n - 1 m - n m
            //行n 星数 空格 总行数m
            //1 1 9 10
            //2 3 8 10
            //3 5 7 10
            //4 7 6 10
            int m = 10;
            for (int j = 1; j <= 10; j++)
            {
                int n = j;
                int start = 2 * n - 1;
                int space = m - n;
                for (int i = 0; i < space; i++)
                {
                    Console.Write(" ");
                }
                for (int i = 0; i < start; i++)
                {
                    Console.Write("*");
                }
                Console.WriteLine();
            }
            //空心金字塔
            int m = 10;
            for (int j = 1; j <= 10; j++)
            {
                int n = j;
                int start = 2 * n - 1;
                int space = m - n;
                for (int i = 0; i < space; i++)
                {
                    Console.Write(" ");
                }
                for (int i = 0; i < start; i++)
                {
                    if (j == m)
                    {
                        Console.Write("*");//让最后一行输出星号
                    }
                    else
                    {
                        if (i == 0 || i == start - 1)
                        {
                            Console.Write("*");
                        }
                        else
                        {
                            Console.Write(" ");
                        }
                    }
                }
                Console.WriteLine();
            }
            //一只蜗牛在井底,井深30米,蜗牛每天爬3米,晚上滑2米,请问蜗牛要爬多少天,才能爬出井口
            //位置 snailPos
            //井深 well
            //天数 day
            //爬行速度 speed
            //掉落速度 drop
            int snailPos = 0;
            int well = 30;
            int day = 1;
            int speed = 3;
            int drop = 2;
            while (true)
            {
                //蜗牛爬
                snailPos += speed;
                Console.WriteLine("第{0}天爬了{1}米", day, snailPos);
                //爬完后立马问,到井口没
                if (snailPos >= well)
                {
                    break;
                }
                //晚上滑
                snailPos -= drop;
                //过了一天
                day++;
            }
            Console.WriteLine(day);
        }
        //数组排序
        static int[] GetArrayRank(int[] array)
        {
            for (int i = 0; i < array.Length - 1; i++)
            {
                for (int j = 0; j < array.Length - 1 - i; j++)
                {
                    if (array[j] > array[j + 1])
                    {
                        int temp = array[j];
                        array[j] = array[j + 1];
                        array[j + 1] = temp;
                    }
                }
            }
            return array;
        }
        //判断闰年
        static void GetYear(int year)
        {
            while (true)
            {
                if (year % 400 == 0 || year % 4 == 0 && year % 100 != 0)
                {
                    Console.WriteLine("是闰年"); break;
                }
            }
        }
    }
}

 月考讲解

C#基础:(共10题,每题2分)
1、如果一个函数成员需要被子类使用且不需要提供其他类来使用,需要的修饰符【】
A、private  
B、protected
C、internal //在当前项目中都可以访问;
D、public

2.在C#里,下列有关基本类的大小不正确的是【】
A、int类型是4个字节
B、bool类型是1个字节
C、long类型是8个字节
D、char类型是一个字节 //ascii是1个字节,unicode是2个字节,utf-8是3个字节 

3.关于定义数组定义不正确的是【】
A、int[] numbers={123456};
B、int[] numbers=new int[6];
C、int[][] numbers=new int[2][3];交错数组//交错数组第二个维度不能指定
D、var a=new[]{1,2,3,4,5,6};

4.有关数组说法正确的是 【】(多选)
A、数组的内存是分配在栈中
B、数组的索引从零开始的
C、数组是一种数据结构,它包含若干相同的类型的变量
D、数组可以是一维、多维、交错的

5、以下关于C#中方法重载的说法正确的是【】。(多选)
A.如两个方法名字不同,而参数的数量不同,那么它们可以构成方法重载
B.如两个方法名字相同,而返回值的数据类型不同,那么它们可以构成方法重载
C.如两个方法名字相同,而参数的数据类型不同,那么它们可以构成方法重载
D.如两个方法名字相同,而参数的数量不同,那么它们可以构成方法重载

6、在C#语法中,在派生类中对基类的虚函数进行重写,要求在声明中使用【】关键字。
A.override
B.new
C.static
D.virtual

7、有关结构体和类的说法不正确的是 【】
A、结构是值类型的,而类是引用类型的
B、结构体不可以声明构造函数 //结构体可以声明构造函数,默认函数保留
C、结构体直接继承System.ValueType类型 //System.ValueType是所有值类型的基类
D、结构体可以继承接口 //结构体可以继承接口,但不可以继承类

8.关于静态类说法正确的是【】 (多选)
A、声明静态类,该类不能使用new关键字创建实例
B、静态仅包含静态成员 //静态类包含常量成员
C、静态类不能包含常量成员
D、静态类是密封的 //静态类隐含是密封的

9、有关继承需要用的关键字说法不正确的是【】
A、virtual用于修饰方法、属性、索引器或事件,并使它们可以在派生类中被重写。
B、virtual可以和static、abstractprivate、override修饰符一起使用。
C、override关键字提供从基类继承的成员的新的实现,重写的基类方法必须是virtual、abstract、或override关键字修饰的。
D、Sealed用于修饰类时,将会阻止其他类从该类派生

10、在C#中,一个类【】
A.可以继承多个类
B.可以实现多个接口
C.在一个程序中只能有一个子类
D.只能实现一个接口

算法题(共8题,每题的分数10分)
1、写一个方法可以实现对一个数组实现升序排序: 使用冒泡排序实现数组内的排序

2、写一个方法试着用最少的比较次数去寻找数组中的最大值和最小值

3、写一个方法实现输入一个数组,实现一个函数,让所有奇数都在偶数前面

4、猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾就多吃了一个。第二天早上又将剩下的桃子吃了一半,还是不过瘾又多吃了一个。以后每天都吃前一天剩下的一半再加一个。到第10天刚好剩一个。问猴子第一天摘了多少个桃子?

5、写一个方法可以求N到M之间的质数 N>0 M<200;

6、多态实现求面积和周长(矩形和圆形)

7、有若干只鸡兔同在一个笼子里,从上面数,有N个头,从下面数,有M只脚。问笼中各有多少只鸡和兔?

8、小明带有一百文钱,去市场买鸡,公鸡5文钱,母鸡3文钱,小鸡1文钱3只; 问:小明要如何配比才能买一百只,他一共有几种方案

 

using System;
using System.Collections.Generic;
namespace CSharp月考
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            #region 选择题
            // 1 B
            // 2 D
            // 3 C
            // 4 BCD
            // 5 CD
            // 6 A
            // 7 B
            // 8 ABD
            // 9 B
            // 10 B
            #endregion
            #region 第1题调用
            int[] nums = { 5, 7, 6, 9, 8 };
            string[] nums = { "abd", "abc", "bcd", "cbd", "bdc", "ab", "b" };
            SortArray(nums);
            SortArray(nums, (a, b) =>
            {
                for (int i = 0; i < a.Length && i < b.Length; i++)
                {
                    if (a[i] != b[i])
                    {
                        return a[i] - b[i];
                    }
                }
                return a.Length - b.Length;
            });
            foreach (var item in nums)
            {
                Console.WriteLine(item);
            }
            #endregion
            #region 第2题调用
            int[] nums = { 5, 7, 6, 9, 8 };
            int max, min;
            if (GetMaXMin(nums, out max, out min))
            {
                Console.WriteLine("Max : " + max + ", Min : " + min);
            }
            #endregion
            #region 第3题调用
            int[] nums = { 2, 1, 3, 5, 8, 10, 7, 2, 7, 4, 3, 1, 5 };
            Sort(nums);
            foreach (var item in nums)
            {
                Console.WriteLine(item);
            }
            #endregion
            #region 第4题调用
            Console.WriteLine(Monkey(1));
            #endregion
            #region 第5题调用
            foreach (var item in GetPrimeNumber(0, 200))
            {
                Console.WriteLine(item);
            }
            #endregion
            #region 第6题调用
            Shape[] shapes = { new Rectangle(5, 10), new Circle(5) };
            foreach (var item in shapes)
            {
                Console.WriteLine(item.GetArea());
                Console.WriteLine(item.GetLength());
            }
            #endregion
            #region 第7题调用
            int checkin, rabbit;
            if (GetNum(5, 14, out checkin, out rabbit))
            {
                Console.WriteLine("鸡 :" + checkin + ", 兔 : " + rabbit);
            }
            #endregion
            #region 第8题调用
            BuyChecken(100, true);
            #endregion
        }
        #region 1.    写一个方法可以实现对一个数组实现升序排序: 使用冒泡排序实现数组内的排序
        static void SortArray<T>(T[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                for (int j = 0; j < array.Length - 1 - i; j++)
                {
                    IComparable<T> comparable = array[j] as IComparable<T>;
                    if (comparable != null)
                    {
                        if (comparable.CompareTo(array[j + 1]) > 0)
                        {
                            T tmp = array[j];
                            array[j] = array[j + 1];
                            array[j + 1] = tmp;
                        }
                    }
                }
            }
        }
        static void SortArray<T>(T[] array, Comparison<T> comparison)
        {
            for (int i = 0; i < array.Length; i++)
            {
                for (int j = 0; j < array.Length - 1 - i; j++)
                {
                    if (comparison(array[j], array[j + 1]) > 0)
                    {
                        T tmp = array[j];
                        array[j] = array[j + 1];
                        array[j + 1] = tmp;
                    }
                }
            }
        }
        #endregion
        #region 2.  写一个方法试着用最少的比较次数去寻找数组中的最大值和最小值
        static bool GetMaXMin(int[] array, out int max, out int min)
        {
            if (array == null || array.Length == 0)
            {
                max = min = 0;
                return false;
            };
            // 把数组两两分组 小的放左边 大的方右边        比较次数 n/2 次
            // 最小值在左边找                          比较次数 n/2 次
            // 最大值在右边找                          比较次数 n/2 次
            // 总的比较次数                                  3n/2 次
            // 优化:不做交换 直接和每组比 每组比较的次数 3次
            max = min = array[0];
            // 长度为偶数
            if (array.Length % 2 == 0)
            {
                for (int i = 0; i < array.Length; i += 2)
                {
                    if (array[i] > array[i + 1])
                    {
                        if (array[i] > max) max = array[i];
                        if (array[i + 1] < min) min = array[i + 1];
                    }
                    else
                    {
                        if (array[i + 1] > max) max = array[i + 1];
                        if (array[i] < min) min = array[i];
                    }
                }
            }
            else  // 长度为奇数
            {
                for (int i = 0; i < array.Length - 1; i += 2)
                {
                    if (array[i] > array[i + 1])
                    {
                        if (array[i] > max) max = array[i];
                        if (array[i + 1] < min) min = array[i + 1];
                    }
                    else
                    {
                        if (array[i + 1] > max) max = array[i + 1];
                        if (array[i] < min) min = array[i];
                    }
                }
                if (max < array[array.Length - 1]) max = array[array.Length - 1];
                if (min > array[array.Length - 1]) min = array[array.Length - 1];
            }
            return true;
        }
        #endregion
        #region 3.  写一个方法实现输入一个数组,实现一个函数,让所有奇数都在偶数前面
        static void Sort(int[] array)
        {
            // 两个指针
            // 左边的找到第一个偶数
            // 右边的找到第一个奇数
            // 如果两个指针满足  左边的 < 右边的 就交换这两个数
            int left = 0;
            int right = array.Length - 1;
            while (left < right)
            {
                // 找左边的偶数
                while (left < right)
                {
                    if (array[left] % 2 != 0)
                    {
                        left++;
                    }
                    else break;
                }
                // 找右边的奇数
                while (left < right)
                {
                    if (array[right] % 2 == 0)
                    {
                        right--;
                    }
                    else break;
                }
                if (left < right)
                {
                    int tmp = array[left];
                    array[left] = array[right];
                    array[right] = tmp;
                }
            }
        }
        #endregion
        #region 4.  猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾就多吃了一个。第二天早上又将剩下的桃子吃了一半,还是不过瘾又多吃了一个。以后每天都吃前一天剩下的一半再加一个。到第10天刚好剩一个。问猴子第一天摘了多少个桃子?
        //          7        2*7 + 1        15
        //          8        2*3 + 1        7
        //          9        2*1 + 1        3
        //          10       1              1
        static int Monkey(int day)
        {
            if (day > 10) return 0;
            else if (day == 10) return 1;
            else return 2 * (Monkey(day + 1) + 1);
        }
        #endregion
        #region 5.  写一个方法可以求N到M之间的质数 N>0 M<200;
        static List<int> GetPrimeNumber(int left, int right)  // (]
        {
            List<int> primeNumber = new List<int>();
            int start = left < right ? left : right;
            start = start >= 2 ? start : 2;
            int end = left < right ? right : left;
            end = end >= 2 ? end : 2;
            for (int i = start; i < end; i++)
            {
                // 判断每一个数字 i 是否是质数
                bool isPrimeNumber = true;
                // 除了1和自己 能被其他数字整除就不是质数
                for (int j = 2; j < i; j++)
                {
                    if (i % j == 0)  // 能被其中一个数字整除了 就不是质数了
                    {
                        isPrimeNumber = false;
                        break;
                    }
                }
                if (isPrimeNumber)
                {
                    primeNumber.Add(i);
                }
            }
            return primeNumber;
        }
        #endregion
        #region 6.  多态实现求面积和周长(矩形和圆形)
        abstract class Shape
        {
            public abstract int GetArea();
            public abstract int GetLength();
        }
        class Rectangle : Shape
        {
            int width;
            int height;
            public Rectangle(int width, int height)
            {
                this.width = width;
                this.height = height;
            }
            public override int GetArea()
            {
                return this.width * this.height;
            }
            public override int GetLength()
            {
                return (width + height) * 2;
            }
        }
        class Circle : Shape
        {
            int radius;
            public Circle(int radius)
            {
                this.radius = radius;
            }
            public override int GetArea()
            {
                return (int)(radius * radius * Math.PI);
            }
            public override int GetLength()
            {
                return (int)(Math.PI * 2 * radius);
            }
        }
        #endregion
        #region 7.  有若干只鸡兔同在一个笼子里,从上面数,有N个头,从下面数,有M只脚。问笼中各有多少只鸡和兔?
        static bool GetNum(int head, int foot, out int checkin, out int rabbit)
        {
            if (foot % 2 != 0 || foot < 2 * head) {
                checkin = rabbit = 0;
                return false;
            }
            // 二元一次方程  假设x只鸡, y只兔子
            //foot = x * 2 + y * 4;     
            //head = x + y;              => x = head - y
            // => foot = (head - y) * 2 + y * 4
            // => foot = head * 2 - 2 * y + y * 4
            // => y = (foot - head * 2)/2
            rabbit = (foot - head * 2) / 2;
            checkin = head - rabbit;
            return true;
        }
        #endregion
        #region 8.  小明带有一百文钱,去市场买鸡,公鸡5文钱,母鸡3文钱,小鸡1文钱3只; 问:小明要如何配比才能买一百只,他一共有几种方案
        // 100文钱                                 只
        //         公鸡     5         1            x        5x
        //         母鸡     3         1            y        3y
        //         小鸡     1         3            z        z/3
        // x  + y  + z    = 100
        // 5x + 3y + z/3 <= 100
        static void BuyChecken(int totalMoney, bool allin = false)
        {
            int num;   // 买鸡的数量
            int cost;  // 花费
            // 买小鸡
            for (int i = 0; i <= totalMoney * 3; i+=3)          // 小鸡的个数
            {
                // 买公鸡
                for (int j = 0; j <= totalMoney/5; j++)
                {
                    // 买母鸡
                    for (int k = 0; k <= totalMoney/3; k++)
                    {
                        num = i + j + k;
                        cost = i / 3 + 5 * j + 3 * k;
                        if(allin)
                        {
                            if (num == 100 && cost == 100)
                            {
                                Console.WriteLine($"小鸡:{i}只, 公鸡{j}只, 母鸡:{k}只");
                            }
                        }
                        else
                        {
                            if (num == 100 && cost <= 100)
                            {
                                Console.WriteLine($"小鸡:{i}只, 公鸡{j}只, 母鸡:{k}只");
                            }
                        }
                    }
                }
            }
        }
        #endregion
    }
}

 

posted @ 2019-02-11 17:32  vuciao  阅读(699)  评论(0编辑  收藏  举报