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 变量名命名要求
、变量名头必需以字母或下划线"_"开头
、变量名体只能是数字,字母,下划线的组合
、不能使用编程语言的关键字
、在作用域内,不能同名 命名是有法则的
、命名要有意义(概括变量里数据的规律)
、变量使用驼峰命名法(除了第一个单词首字母小写,其余单词首字母全大写)
、类与方法使用帕斯卡命名法(每个单词的首字母都大写) 、定义一个变量:数据类型 变量名;
、给变量赋值:变量名 =(赋值符号) 值(数据) 常量:
const 数据类型 常量名
命名法则:全大写,单词之间用下划线分隔
常量在定义时一定要赋值(初始化赋值)
常量的值不可以更改

m1w1d2_ide

关闭番茄插件的拼写纠错,Visual Assist Options的Underlining
调整行号:工具-选项-文本编辑器-C#-行号
调整主题:工具-选项-环境-常规-颜色主题-深色
调整字体:工具-选项-环境-字体颜色(推荐字体Consolas) 取数据类型的长度:sizeof()
基础数据类型所占字节: ASCII表
-:-
A-Z:-
a-z:- 字符串格式化输出:
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(- , );

m1w2d2_complex_datatype

基本数据类型
、定义变量,、使用变量
复杂数据类型
,定义类型,、定义这个类型的变量、、使用变量 枚举:一般情况我们用枚举来表示一组状态的集合
定义类型 一般情况下我们都放在类外面定义
enum 自定义枚举名
{
成员(枚举项),
成员(枚举项),
}
每个枚举项都可以赋整数值
如果没有赋值,他的值是前一枚举项的值+
第一个枚举项如果不赋值,默认值0
赋值原因:给枚举项建立数学联系(属性相克)
定义这个类型的变量时,枚举的值,只能是所规定的枚举项
自定义枚举名 变量名 = 自定义枚举名.某一枚举项 枚举转字符串:对应的变量,调用toString()方法,可以将枚举转字符串
字符串转成枚举:(Occupation)Enum.Parse(typeof(Occupation), "道士");

m1w2d3_array

、定义一个数组变量
数据类型[] 变量名;
int[] array;
数据类型[] 变量名 = {成员,成员};
int[] array1 = { , , , , };//不指定元素个数,只指定元素
int[] array2 = new int[] { , , , , , , , };//先限制元素个数,然后再指定元素
数据类型[] 变量名 = 指定的长度空数组。
int[] array3 = new int[];//最常用的形式,不关心值,只关心处理逻辑
元素的值是默认值(微软MSDN默认值)
数值类型是对应0
如果字符串是" " 、使用数组
访问成员,通过下标 变量名[下标号]访问对应下标的成员
array1[] = ;
Console.WriteLine(array1[]);
如果我使用的下标是负数,或者超出了元素个数,指定了数组中一个不存在的元素
会出现 越界异常
下标的有效范围是( - 数组名.Length-)
Console.WriteLine(array1.Length);
Console.WriteLine(array1.[array1.Length - ]);
通过数组名.Length我们能知道这个数组中有多少个元素 、遍历数组
遍历就是从一个 数据结构 第一个元素 到 最后一个元素
遍历就是把 数据结构中 所有元素访问完 Length:取数组元素的总个数
GetLength:取不同维度的个数

m1w2d3_struct_array

结构体
用途:一般情况下我们使用结构体来描述复杂事物,如桌子,如位置
这个复杂事物不能包含自己,会发生递归调用
结构体用于:属性不多,频繁计算的复杂事物
结构体储存在栈里,运行速度快,但栈里的空间宝贵,所以用来描述的事物不宜过多(<=)(也可以不放在栈里,运算不用跳地址)
一般用于定义常用的数学概念及其需要计算的结果 定义结构体的类型
struct 自定义类型名{成员;成员;}
成员之间用分号隔开
成员是其它数据类型
成员需要外部访问要用public 定义结构体的变量
数据类型 变量名 = 初始值;
Student xiaoMing = new Student();//一次性给结构体里所有变量附初值 数组 冒泡排序
//1、先写内循环,循环次数为:数组长度-1-外循环当前次数
//2、内循环每次对比当前位置与下一位置,如果逻辑(当前位大于对比位)达成 则交换位置
//3、外循环,循环次数为 数组长度-1
for (int i = ; i < array.Length - ; i++)
{
for (int j = ; j < array.Length - - i; j++)
{
if (array[j] > array[j + ])
{
int temp = array[j];
array[j] = array[j + ];
array[j + ] = temp;
}
}
} 二维数组也是解决重复数据的重复逻辑,不同的是他允许我们通过两(多)个下标
为什么用多个下标,人们在生活,经常需要处理二维的数据,地图,表单(纯三维数据特别的少)
本质上,内存中一维和二维数组是一样的 使用二维数组
定义二维数组
不指定元素
数据类型[,] 变量名;
指定元素
数据类型[,] 变量名 = new 数据类型[标号为0维度的元素个数,标号为1维度的元素个数]
数据类型[,] 变量名 = new 数据类型[行数,列数]
数据类型[,] 变量名 = new 数据类型[x,y] 交错数组与多维数组的区别
交错数组理论上才是数组的数组
、多维数组必须是每一个维度的元素个数相等,多维数组只能表示矩形数据块
交错数组可以表示锯齿数据块
、多维数组必须是指定每一个维度的元素个数
交错数组只能指定最外层的数组个数
、多维本质上是一块连续内存空间,为什么是多维表示,为了人们方便去理解,多维和一维只是索引器不一样
交错数组理论上才是数组的数组 定义一个交错数组
数据类型[][]变量名;
数据类型[][]变量名 = new 数据类型[][]{new int[],new int[],new int[],new int[],}
数据类型[][]变量名 = new 数据类型[][];

m1w2d6_debug

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

String.Split

、用字符串分隔:
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"); 、用单个字符来分隔:
string str3 = "aaajbbbjccc";
string[] sArray3 = str3.Split('j');
foreach (string i in sArray3) Console.Write(i.ToString() + "\r\n");
Console.WriteLine("\r\n"); 、用多个字符来分隔:
string str2 = "aaajbbbscccjdddseee";
string[] sArray2 = str2.Split(new char[] { '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(, ));//return:a
Response.Write(str.Substring(, ));//return:cde
Response.Write(str.Substring(, ));//return:h
Response.Write(str.Substring());//return:h
Response.Write(str.Substring());//error:startIndex 不能大于字符串长度。
Response.Write(str.Substring(, ));//error:索引和长度必须引用该字符串内的位置。

m1w2d6_function_flyingchess

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

m1w3d1_function_parm_overload_oop

ref关键字
在定义方法时 使用 参数修饰 ref 我们可以传递一个地址
,定义方法参数使用ref关键字,调用时同时也可使用
,调用时,实际参数必须有被赋值 函数的重载
函数允许我们重名,重名函数在重载的情况下是允许的
参数列表不一样时构成重载
重载函数有助我们统一理解
、参数个数不一样
、类型和顺序不一样 递归的调用
函数递归 指 函数自身 调用自身的 一种算法
在算法没有写错的情况 所以他有可能会造成 堆栈溢出异常
一般用递归解决子问题就是父问题的问题 边界 在递归过程中,我们必须得有一种已知情况
边界参数要交给自己
边界参数要无尽的趋向边界 值类型与引用类型的存储方式:
引用类型:引用类型存储在堆中。类型实例化的时候,会在堆中开辟一部分空间存储类的实
例。类对象的引用还是存储在栈中。
值类型:值类型总是分配在它声明的地方,做为局部变量时,存储在栈上;类对象的字段时,
则跟随此类存储在堆中。

m1w3d2_class_oop

类的定义
程序中的类,是属性和方法的封装
定义的格式和结构一样,只是关键字不一样用class
成员不一样,类允许使用任意类型的成员 类到对象
通过实例化,我们可以将类实例化成某一个具体的对象
通过 new 关键字 结合构造函数 可以实例化 一个具体的对象
通过初始化,可以确保这个对象有自己专有的值
数据类型 变量名 = 初始化值; 对象
对象是类的一个实例
我们用this关键指向自己这个对象
某一个类的对象拥有这个类所有的属性和方法,换言之,一个类的对象和这个类的属性和方法是一致的
同一个类的对象一般表现为数据不同,而属性和方法是一致的 构造 - 被使用 - 析构
构造
实例化可以将一个类实例化成一个对象
Student xiaoMing = new Student();
实例化会在内存中开辟一块空间,然后初始化(对空间中的成员添值,添值的逻辑我们交给构造函数) 构造函数
构造函数只能写在本类里
和函数大体一致
、没有返回类型
、函数名和类名一致
构造函数允许我们重载
当你不写构造函数时,会有一个默认构造存在
一旦重载,默认构造就会消失
一般情况下,我们会保留默认构造,再写一个默认构造(无参构造)
通过重载构造 我们可以对对象赋予不同的数据
通过this关键字,我们可以用一个构造函数 调用 另一个构造
一般情况下有多个构造 我们就用直接指向参数最多的构造
Student():this("小明",,"男") 结构体与类的区别
、结构体对象属于值类型,类对象属于引用类型
、结构体中的字段不能赋初值 类中可以
、结构体中不能显式定义无参构造函数,如果是重写了带参的构造函数,那么就需要对所有字段初始化
、结构体放在栈里里,读写速度快,类放在堆里 类一般定义在命名空间下面
一种模板 这个模板就是用来创建对象的 通过这个模板可以创建对象的属性和方法
m1w3d3_attribute_inherit_visit
属性
、和方法大体一样,返回类型不能是void,没有参数列表
如果你保护哪个字段,建议属性名用字段的帕斯卡命名法 、属性块中由两个块组成get,set
get块在被使用(取值)时是被调用
set块在赋值时才会被调用
set get块可以由空语句替代
必须全部由空语句替代,或者没有set
get块和set块可以只有一个 、get块必须有返回值,值类型与属性返回类型一致 、在对应字段写入相应逻辑
属性的简写
get set块 可以是空语句,set块可以没有
这样的属性我们叫做自动属性,自动属性可以帮助我们快速实现一个自动属性
自动属性有保护的字段

m1w3d4_inherit

继承
如果我们定义了若干类,这些类都有一些共有的属性和方法
我们可以把这些共有部分抽象建立一个新的类,作为基类
已解决我们代码重复的问题,以便于管理
如果继承关系建立,子类的构造函数将会默认指向父类的无参构造
我们可以通过this调用自身的另一个构造函数
我们可以通过base调用父级的构造函数
继承:子类继承的是父类所有成员
但是你只能访问父类成员作用域允许的成员,除了private
如果你的成员需要外部访问,只能是public 里氏转换
、子类(Reporter)可以当父类(Person)用
一个对象的实际类型是指他被构造出来时的类型
、如果父类中的实际对象是子类,我们可以将其转成子类
is关键字 可以帮助我们判定一个对象中是否包含另一个对象类型
对象 is 包含的类型
as关键字 尝试性转换,如果转换成功则返回对应类,不成功则返回null
对象 as 尝试转换的类型

m1w3d5_virtual

多态 用虚方法实现
多态实现 真的鸭子嘎嘎叫,木头鸭子吱吱叫,橡皮鸭子唧唧叫
多态 不同的实际对象,在同一个指令(叫),有不同的表现
不同的对象,如何统一管理 里氏转换:可以把子级当父级 如果这些不同的对象全继承自一个父类
统一管理 如果把子级转换成了父级,子级的特性丢失了 用虚方法可以 用父级管理并且保留子级的特性 已解决问题
,在实例方法前加 virtual
,在派生类中用 override 重写 同名/同签名的方法
在一个虚方法被调用时,会根据最后重写的那个方法和实际类型来决定
不会根据当前类型来执行方法

m1w4d1_abstract

抽象函数、抽象类
多态实现 写一个动物的 抽象类,写两个子类狗狗叫,猫猫叫 Animal类Cry方法里写具体实现的问题:写什么都不合适
实例化 一个 animal的对象 他指代现实中 哪种对象 无法解释
如果有以上情况,我们可以用抽象函数,以便管理,以提高代码可读性 抽象函数
抽象函数用abstract关键字修饰
抽象函数只能存在于抽象类中
抽象函数不允许你实现,不需要写函数体,用空语句代替 抽象类
一个用abstract关键字修饰过的类,我们叫抽象类
抽象类中可以有抽象成员,也可以有普通成员
继承了抽象类的派生类,必须实现抽象类所有的抽象成员
抽象类不允许我们实例化,但是有构造函数并且可以重载 所以我们在写一个程序结构或者框架的时候会用到抽象类
m1w4d1_interface
不同对象 可以使用同一方法 表现不同行为
这些对象要同一个结构(数组)里 管理结构(容器) 如果多个接口出现了同名的成员,在实现的时候,默认是共用的
如果你想区分不同接口的不同方法,我们可以使用接口的显示实现
接口名.成员名
显示实现的成员必须由接口类型调用 ,多继承
,多态 和类大体一致,关键字interface
成员没有实现,函数是没有函数体,用空语句,属相必须是自动属性
成员只能是属性,函数,事件,索引器
成员必须是public,不用写,也不能写 访问修饰 关键字 接口名{}
接口名 命名 一般以 I 为前缀 接口使用:
我们可以用一个类来继承已经定义好的接口:一对一,一对多,接口之间可以相互继承
如果在继承关系中,这个类有继承其它类,这个基类要放在继承的第一位
继承一个接口必须实现这个接口所有成员
能让我们把物品按特定的功能统一管理

m1w4d2_indexes

索引器
索引器可以让我们通过不同的索引号返回对应类型的多个属性
索引器适用于除自动属性以外的所有属性特性
索引号可以是任意类型
索引器在通过类对象来访问和赋值 变量(类对象)[索引号]
访问修饰 返回类型 this[索引号,索引号,索引号,索引号......]
{ get {return} set {value} } 静态构造函数什么时候调用
当我们访问静态成员的时候,先调用且只调用一次
当我们创建对象的时候,先调用且只调用一次
可以对静态字段做初始化使用的,静态的成员才会加载到内存中

m1w4d2_operator

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

m1w4d3_delegate

委托
委托类型的定义
委托是一个引用类型,存放着一个或者一组方法的引用
方法的签名
访问修饰 关键字(delegate) 对应方法的签名(返回类型 委托名 参数) 委托类型的定义
MyDelegate myDelegate;//这种形式用的比较多
MyDelegate myDelegate1 = new MyDelegate(Max);//这种形式用的比较少 赋值
将委托的委托列表清空,然后将赋值的函数注册到委托列表
如果我们将一个函数赋值到委托
这个委托被调用时,等同与函数被调用
赋值只需要函数(方法)名,不需要传参
myDelegate = Max;//用的比较少 注册
如果我们将一个函数注册到委托
相当于将函数注册到其委托列表
这个委托被调用时,将调用到这个注册函数
注册只需要函数(方法)名,不需要传参
myDelegate += Min;//用的比较多 注销
注册就是将一个函数从委托的委托列表中移除
仅移除最后一个注册的对应函数
如果委托列表中没有对应的函数不会报错
myDelegate -= Max; 调用
委托会将其 委托列表 中所有的函数按顺序执行
通过委托我们只能取得最后的执行的函数的返回值
委托调用时确定其参数,虽然委托中有多个函数,但只能使用一份参数
委托可以通过 变量名(参数)调用,变量名.Invoke(参数)
Console.WriteLine(myDelegate(, )); 作为参数的应用
委托可以做为另一个函数的参数使用
当一个函数使用了委托参数时
当其被调用时,我们可以直接放入一个对应委托,或者直接放入一个与委托同参同返回的函数参数 如果一个函数和委托的约束的签名一致
我们就可以把这个函数赋值或注册到委托

m1w4d3_delegate1

设计模式 在编程的过程中,前辈们为了解决特定的通用问题而总结出来的模式
单例模式
观察者模式 用于构建 事件处理系统
通过一个被观察者去管理观察者
被观察者 通过 事件(委托) 在状态改变时 调用所用注册过的 观察者方法 、委托外部调用不安全
、委托外部赋值不安全
、私有化之后,外部成员无法注册 事件是对委托的进一步封装,约束了委托访问的作用域,允许事件在外部注册,但是不能赋值和调用
通过在一个委托的前面加上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(); 访问元素
通过索引器可以访问对应元素,但索引器的标号必须小于Count
Console.WriteLine(list[]);
Console.WriteLine(list.Capacity);//初始为0.由Add创建 删除元素
list.RemoveAt();//移除指定下标中的元素
list.Remove();//移除指定元素(从头查找到的) 插入元素
list.Insert();//在指定下标处,插入指定元素,原元素及其后的元素均排在插入元素的后方
list.Insert(, ); 查找元素
从头查找
int id = list.IndexOf();//根据元素从头查找,并返回找到的第一个元素的位置
从尾查找
int id1 = list.LastIndexOf();//根据元素从尾查找,并返回找到的第一个元素的位置

m1w4d4_list1

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

m1w4d5_dictionary

声明变量
Dictionary<char, string> dic = new Dictionary<char, string>(); 添加元素
dic.Add('', "一");
dic[''] = "二"; 修改一个元素
dic[''] = "贰"; 如果用户输入的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 % == ;
bool conditionB = year % == ;
bool conditionC = year % != ;
string message = (conditionA || (conditionB && conditionC)) ? "是闰年" : "不是闰年";
Console.WriteLine(message);
//找出100内所有素数。素数 / 质数:只能被1和这个数字本身整除的数字,1不是质数, 最小的质数是2。
//如果你遇到一个复杂,要抽象其子问题
//子问题:某一个数是不是质数
for (int j = ; j <= ; j++)
{
int num = j;
for (int i = ; i <= num; i++)
{
if (i == num)
{
Console.WriteLine("{0}是一个质数", i);
break;
}
if (num % i == )
{
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 = ; i <= ; i++)
{
int a = (i % ) / ;
int b = (i % ) / ;
int c = (i % ) / ;
if (i == a * a * a + b * b * b + c * c * c)
{
Console.WriteLine(i);
}
}
//老师问学生,这道题你会作了吗?如果学生答“会了(y)”,则可以放学,
//如果学生不会做(n),则老师再讲一遍,再问学生是否会做了。。。
//直到学生会了为止,才可以放学
//直到学生会了或老师给他讲了10遍还不会,都要放学
bool ok = false;
for (int i = ; i < ; 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 = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
if (i == || i == || j == || j == )
{
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 = ;
for (int j = ; j <= ; j++)
{
int n = j;
int start = * n - ;
int space = m - n;
for (int i = ; i < space; i++)
{
Console.Write(" ");
}
for (int i = ; i < start; i++)
{
Console.Write("*");
}
Console.WriteLine();
}
//空心金字塔
int m = ;
for (int j = ; j <= ; j++)
{
int n = j;
int start = * n - ;
int space = m - n;
for (int i = ; i < space; i++)
{
Console.Write(" ");
}
for (int i = ; i < start; i++)
{
if (j == m)
{
Console.Write("*");//让最后一行输出星号
}
else
{
if (i == || i == start - )
{
Console.Write("*");
}
else
{
Console.Write(" ");
}
}
}
Console.WriteLine();
}
//一只蜗牛在井底,井深30米,蜗牛每天爬3米,晚上滑2米,请问蜗牛要爬多少天,才能爬出井口
//位置 snailPos
//井深 well
//天数 day
//爬行速度 speed
//掉落速度 drop
int snailPos = ;
int well = ;
int day = ;
int speed = ;
int drop = ;
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 = ; i < array.Length - ; i++)
{
for (int j = ; j < array.Length - - i; j++)
{
if (array[j] > array[j + ])
{
int temp = array[j];
array[j] = array[j + ];
array[j + ] = temp;
}
}
}
return array;
}
//判断闰年
static void GetYear(int year)
{
while (true)
{
if (year % == || year % == && year % != )
{
Console.WriteLine("是闰年"); break;
}
}
}
}
}

月考讲解

C#基础:(共10题,每题2分)
、如果一个函数成员需要被子类使用且不需要提供其他类来使用,需要的修饰符【】
A、private
B、protected
C、internal //在当前项目中都可以访问;
D、public .在C#里,下列有关基本类的大小不正确的是【】
A、int类型是4个字节
B、bool类型是1个字节
C、long类型是8个字节
D、char类型是一个字节 //ascii是1个字节,unicode是2个字节,utf-8是3个字节 .关于定义数组定义不正确的是【】
A、int[] numbers={,,,,,};
B、int[] numbers=new int[];
C、int[][] numbers=new int[][];交错数组//交错数组第二个维度不能指定
D、var a=new[]{,,,,,}; .有关数组说法正确的是 【】(多选)
A、数组的内存是分配在栈中
B、数组的索引从零开始的
C、数组是一种数据结构,它包含若干相同的类型的变量
D、数组可以是一维、多维、交错的 、以下关于C#中方法重载的说法正确的是【】。(多选)
A.如两个方法名字不同,而参数的数量不同,那么它们可以构成方法重载
B.如两个方法名字相同,而返回值的数据类型不同,那么它们可以构成方法重载
C.如两个方法名字相同,而参数的数据类型不同,那么它们可以构成方法重载
D.如两个方法名字相同,而参数的数量不同,那么它们可以构成方法重载 、在C#语法中,在派生类中对基类的虚函数进行重写,要求在声明中使用【】关键字。
A.override
B.new
C.static
D.virtual 、有关结构体和类的说法不正确的是 【】
A、结构是值类型的,而类是引用类型的
B、结构体不可以声明构造函数 //结构体可以声明构造函数,默认函数保留
C、结构体直接继承System.ValueType类型 //System.ValueType是所有值类型的基类
D、结构体可以继承接口 //结构体可以继承接口,但不可以继承类 .关于静态类说法正确的是【】 (多选)
A、声明静态类,该类不能使用new关键字创建实例
B、静态仅包含静态成员 //静态类包含常量成员
C、静态类不能包含常量成员
D、静态类是密封的 //静态类隐含是密封的 、有关继承需要用的关键字说法不正确的是【】
A、virtual用于修饰方法、属性、索引器或事件,并使它们可以在派生类中被重写。
B、virtual可以和static、abstract、private、override修饰符一起使用。
C、override关键字提供从基类继承的成员的新的实现,重写的基类方法必须是virtual、abstract、或override关键字修饰的。
D、Sealed用于修饰类时,将会阻止其他类从该类派生 、在C#中,一个类【】
A.可以继承多个类
B.可以实现多个接口
C.在一个程序中只能有一个子类
D.只能实现一个接口 算法题(共8题,每题的分数10分)
、写一个方法可以实现对一个数组实现升序排序: 使用冒泡排序实现数组内的排序 、写一个方法试着用最少的比较次数去寻找数组中的最大值和最小值 、写一个方法实现输入一个数组,实现一个函数,让所有奇数都在偶数前面 、猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾就多吃了一个。第二天早上又将剩下的桃子吃了一半,还是不过瘾又多吃了一个。以后每天都吃前一天剩下的一半再加一个。到第10天刚好剩一个。问猴子第一天摘了多少个桃子? 、写一个方法可以求N到M之间的质数 N> M<; 、多态实现求面积和周长(矩形和圆形) 、有若干只鸡兔同在一个笼子里,从上面数,有N个头,从下面数,有M只脚。问笼中各有多少只鸡和兔? 、小明带有一百文钱,去市场买鸡,公鸡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 = { , , , , };
string[] nums = { "abd", "abc", "bcd", "cbd", "bdc", "ab", "b" };
SortArray(nums);
SortArray(nums, (a, b) =>
{
for (int i = ; 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 = { , , , , };
int max, min;
if (GetMaXMin(nums, out max, out min))
{
Console.WriteLine("Max : " + max + ", Min : " + min);
}
#endregion
#region 第3题调用
int[] nums = { , , , , , , , , , , , , };
Sort(nums);
foreach (var item in nums)
{
Console.WriteLine(item);
}
#endregion
#region 第4题调用
Console.WriteLine(Monkey());
#endregion
#region 第5题调用
foreach (var item in GetPrimeNumber(, ))
{
Console.WriteLine(item);
}
#endregion
#region 第6题调用
Shape[] shapes = { new Rectangle(, ), new Circle() };
foreach (var item in shapes)
{
Console.WriteLine(item.GetArea());
Console.WriteLine(item.GetLength());
}
#endregion
#region 第7题调用
int checkin, rabbit;
if (GetNum(, , out checkin, out rabbit))
{
Console.WriteLine("鸡 :" + checkin + ", 兔 : " + rabbit);
}
#endregion
#region 第8题调用
BuyChecken(, true);
#endregion
}
#region 1. 写一个方法可以实现对一个数组实现升序排序: 使用冒泡排序实现数组内的排序
static void SortArray<T>(T[] array)
{
for (int i = ; i < array.Length; i++)
{
for (int j = ; j < array.Length - - i; j++)
{
IComparable<T> comparable = array[j] as IComparable<T>;
if (comparable != null)
{
if (comparable.CompareTo(array[j + ]) > )
{
T tmp = array[j];
array[j] = array[j + ];
array[j + ] = tmp;
}
}
}
}
}
static void SortArray<T>(T[] array, Comparison<T> comparison)
{
for (int i = ; i < array.Length; i++)
{
for (int j = ; j < array.Length - - i; j++)
{
if (comparison(array[j], array[j + ]) > )
{
T tmp = array[j];
array[j] = array[j + ];
array[j + ] = tmp;
}
}
}
}
#endregion
#region 2. 写一个方法试着用最少的比较次数去寻找数组中的最大值和最小值
static bool GetMaXMin(int[] array, out int max, out int min)
{
if (array == null || array.Length == )
{
max = min = ;
return false;
};
// 把数组两两分组 小的放左边 大的方右边 比较次数 n/2 次
// 最小值在左边找 比较次数 n/2 次
// 最大值在右边找 比较次数 n/2 次
// 总的比较次数 3n/2 次
// 优化:不做交换 直接和每组比 每组比较的次数 3次
max = min = array[];
// 长度为偶数
if (array.Length % == )
{
for (int i = ; i < array.Length; i += )
{
if (array[i] > array[i + ])
{
if (array[i] > max) max = array[i];
if (array[i + ] < min) min = array[i + ];
}
else
{
if (array[i + ] > max) max = array[i + ];
if (array[i] < min) min = array[i];
}
}
}
else // 长度为奇数
{
for (int i = ; i < array.Length - ; i += )
{
if (array[i] > array[i + ])
{
if (array[i] > max) max = array[i];
if (array[i + ] < min) min = array[i + ];
}
else
{
if (array[i + ] > max) max = array[i + ];
if (array[i] < min) min = array[i];
}
}
if (max < array[array.Length - ]) max = array[array.Length - ];
if (min > array[array.Length - ]) min = array[array.Length - ];
}
return true;
}
#endregion
#region 3. 写一个方法实现输入一个数组,实现一个函数,让所有奇数都在偶数前面
static void Sort(int[] array)
{
// 两个指针
// 左边的找到第一个偶数
// 右边的找到第一个奇数
// 如果两个指针满足 左边的 < 右边的 就交换这两个数
int left = ;
int right = array.Length - ;
while (left < right)
{
// 找左边的偶数
while (left < right)
{
if (array[left] % != )
{
left++;
}
else break;
}
// 找右边的奇数
while (left < right)
{
if (array[right] % == )
{
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 > ) return ;
else if (day == ) return ;
else return * (Monkey(day + ) + );
}
#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 >= ? start : ;
int end = left < right ? right : left;
end = end >= ? end : ;
for (int i = start; i < end; i++)
{
// 判断每一个数字 i 是否是质数
bool isPrimeNumber = true;
// 除了1和自己 能被其他数字整除就不是质数
for (int j = ; j < i; j++)
{
if (i % j == ) // 能被其中一个数字整除了 就不是质数了
{
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) * ;
}
}
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 * * radius);
}
}
#endregion
#region 7. 有若干只鸡兔同在一个笼子里,从上面数,有N个头,从下面数,有M只脚。问笼中各有多少只鸡和兔?
static bool GetNum(int head, int foot, out int checkin, out int rabbit)
{
if (foot % != || foot < * head) {
checkin = rabbit = ;
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 * ) / ;
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 = ; i <= totalMoney * ; i+=) // 小鸡的个数
{
// 买公鸡
for (int j = ; j <= totalMoney/; j++)
{
// 买母鸡
for (int k = ; k <= totalMoney/; k++)
{
num = i + j + k;
cost = i / + * j + * k;
if(allin)
{
if (num == && cost == )
{
Console.WriteLine($"小鸡:{i}只, 公鸡{j}只, 母鸡:{k}只");
}
}
else
{
if (num == && cost <= )
{
Console.WriteLine($"小鸡:{i}只, 公鸡{j}只, 母鸡:{k}只");
}
}
}
}
}
}
#endregion
}
}
上一篇:兼容iOS 10 资料整理笔记


下一篇:微服务中的 API 网关(API Gateway)