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-9:48-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() + " "); Console.WriteLine(" "); 2、用单个字符来分隔: string str3 = "aaajbbbjccc"; string[] sArray3 = str3.Split('j'); foreach (string i in sArray3) Console.Write(i.ToString() + " "); Console.WriteLine(" "); 3、用多个字符来分隔: string str2 = "aaajbbbscccjdddseee"; string[] sArray2 = str2.Split(new char[2] { 'j', 's' }); foreach (string i in sArray2) Console.Write(i.ToString() + " "); Console.WriteLine(" "); 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={1,2,3,4,5,6}; 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、abstract、private、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 } }