zoukankan      html  css  js  c++  java
  • C# 全总结

       1 using System;
       2 using System.Collections.Generic;
       3 //using System.Linq;
       4 using System.Text;
       5 using System.Diagnostics;
       6 using System.IO;
       7 using static System.Console;
       8 using System.Linq;
       9 using System.Runtime.InteropServices;
      10 using System.Threading;
      11 
      12 namespace ConsoleApplication1
      13 {
      14     class Program
      15     {
      16         [DllImport("dltest.dll", EntryPoint ="Print")]
      17         static extern void xPrint(int x);
      18         #region old-test
      19 
      20         //////////////////////////////////////////////////////////////////
      21         static void TestStreamReadWrite()
      22         {//一个流不能兼备读写两种操作,不知道为什么,这不合理
      23             string s1 = "你好啊ABC";
      24 
      25             var t = "你好啊ABC".Length;
      26             //关于编码注意几点:
      27             //1,sizeof(char) 等于 2
      28             //2,str.Length 是以元素个数算的,不是按字节算的,如 "你好啊ABC” length = 6
      29             //3,c#在VS的默认编码为 Encoding.Default, 该编码下汉字占两字节,非汉字占1字节,通过查看ms中的字节数据可知
      30             //4,string 类型写入任何buffer时都是先写长度,一般为1字节,再写字节数据,如下
      31             var sz = sizeof(char); //2, 注意char占2字节
      32             var szb = sizeof(bool); //1
      33 
      34             var ms = new MemoryStream();
      35             var writer = new BinaryWriter(ms, Encoding.UTF7);
      36             writer.Write(s1);
      37             ms.Close();
      38             writer.Close();
      39 
      40             var ms2 = new MemoryStream(ms.GetBuffer());
      41             var reader = new BinaryReader(ms2, Encoding.UTF8);
      42             var s2 = reader.ReadString();
      43 
      44         }
      45 
      46         //////////////////////////////////////////////////////////////////
      47         static void TestEncoding()
      48         {
      49             string s1 = "你好啊ABC";
      50 
      51             //汉字乱码问题,汉字必须使用2个以上字节才能表示
      52             //编码方式
      53             //1,ASCII码,只有一个字节,不能正确表示汉字,出现乱码,可以正确表示数字和字母符号
      54             //2,UNICODE,任何符号都用2个字节表示,因此可以表示汉字和任意符号
      55             //3,UTF8,变字节的编码,可以正确表示任何字符和汉字,各国语言
      56             //4,GB2312编码,国标码,主要是为汉字服务的中国编码,汉字占两字节,字母数字占1字节
      57             //5,default编码,在国内, 般就是GB2312
      58             Encoding.Default.GetBytes(s1);
      59             var bytes = Encoding.GetEncoding("GB2312").GetBytes(s1);
      60             var len = bytes.Length;
      61             var bts = new byte[10 + len];
      62             Array.ConstrainedCopy(bytes, 0, bts, 0, len);
      63 
      64             var s2 = Encoding.GetEncoding("GB2312").GetString(bts).TrimEnd('');
      65             string s3 = "hello/0/0dddddd".TrimStart('');//!!!!!!!!!!!!!!!!!!!!!!!!!!!!    
      66 
      67         }
      68 
      69         #region 计算机中数据的存储
      70         //////////////////////////////////////////////////////////////////
      71         static void TestTypeConvert()
      72         {//把一个有符号数转为无符号后再转回来值保持不变,以下以1字节为例
      73             //原理:计算机中符点数都是有符号的,不存在这种转变,只剩下整数,
      74             //真值:绝对值的二进制值,如-1的真值为 00000001
      75             //整数是以补码形式存放的,计算机规定了正数的补码是本身,负数的补码是:符号位不变,真值按位取反再加1
      76             //强制转换做的事就是把一个补码看成是有符号还是无符号
      77             //有符号数,在计算时:符号位不变,真值按位取反再加1。无符号数直接计算,举例如下:
      78             //1,-1 的真值为00000001,补码为 1 111 1111,强转时就是把补码值看作是一个无符数,因此它=255
      79             //,再次强转时把它看成有符号数,符号位不管,其余位按位取反加1后是1,因此再次转回了-1
      80             //2,-2 的真值为00000010,补码为 1 111 1110,强转时把补码看作无符号数,因此它=254
      81             //3,-128真值有点特殊,128的二进制码为1000 0000,第8位是符号位,舍弃,取后面的0,即-128的真值为0
      82             //补码经按位取反加1后还是 1 000 0000,强转时看成无符号数即为128
      83             //-------------------------------------------
      84             //1字节数据和2字节数据进行加法运算时,要进行位扩展,将1字节扩展为2字节
      85             //正数扩展时高位补0,负数扩展时高位补1
      86             //C#中小于4字节的数据进行运算时会先扩展成int再进行
      87             sbyte sb = -127;
      88             var b = (byte)(sb);
      89             var sb1 = (sbyte)(b);
      90             object dx = 10.0f;
      91             double dx2 = 33;
      92             byte ix = (byte)dx2;
      93 
      94             var t = dx.GetType();
      95             Type T = System.Type.GetType(t.FullName, true);
      96 
      97 
      98         }
      99         #endregion
     100 
     101         //////////////////////////////////////////////////////////////////
     102         void TestUncheck()
     103         {
     104             unchecked
     105             {//不被编译系统做编译时安全检查
     106 
     107             }
     108         }
     109 
     110         static void TestBoxing()
     111         {
     112             int i = 10;
     113             object o = 1;
     114             int i2 = (int)o;
     115         }
     116 
     117         static void TestReadBytes()
     118         {
     119             byte[] bts = new byte[4] { 23, 0, 16, 0 };
     120             var ms = new MemoryStream(bts);
     121             var br = new BinaryReader(ms);
     122             var p1 = ms.Position;
     123             var ix = br.ReadUInt32();
     124             var p2 = ms.Position;
     125             Console.WriteLine("num=" + ix);
     126             br.Dispose();
     127             br.Close();
     128             ms.Dispose();
     129             ms.Close();
     130         }
     131 
     132         static void TestStrEnd()
     133         {
     134             string str = "abcde";
     135             var br = new BinaryReader(new MemoryStream(Encoding.ASCII.GetBytes(str)));
     136             var b = br.ReadByte();
     137             while (b != 0)
     138             {
     139                 Console.WriteLine(b);
     140                 try
     141                 {
     142                     b = br.ReadByte();
     143                 }
     144                 catch (System.Exception ex)
     145                 {
     146                     Console.WriteLine("未发现字符串结束符");
     147                     break;
     148                 }
     149             }
     150         }
     151 
     152         static void TestBigEndia()
     153         {
     154             var br = new BinaryWriter(File.Create("f:/testx.dt"), Encoding.ASCII);
     155             br.Write((Int16)9);
     156             string str = "Stand";
     157             br.Write(str);
     158             br.Write((Int16)10);
     159             br.Write((Int16)70);
     160             br.Dispose();
     161 
     162         }
     163 
     164         static void TestChar0()
     165         {//注意字符串中0和的区别,如 s1="h0ello", s2 = "hello"
     166             //s2中的是字符串结尾符,除了C#不把它作为结束符外,其它语言都把它作为结束符,如U3D,LUA,C/C++等
     167             //而s1中的0仅是一个字符0而已,字符0的ASCII值是0X31=49,''的ASCII值是0
     168             //注意这两种0在C#和U3D的API之间切换时容易造成BUG,如:
     169             //1, debug.log(s1): "h0ello"
     170             //2,debug.log(s2): "h"
     171             var s = "hello";
     172             s += 0 + ",world";
     173             var s1 = "hello";
     174             s1 += (char)0 + ",world";
     175             var s2 = "hello";
     176             s2 += '' + ",world";
     177         }
     178         static void MemTest()
     179         {
     180 
     181         }
     182         static void ReflectionTest()
     183         {//测试两种反射的效率问题
     184             //Type.GetType()只能在同一个程序集中使用,typeof则可以跨程序集(assembly)
     185             //通过下面的实测,发现typeof是比GetType快40多倍
     186             var timer = Stopwatch.StartNew();
     187             timer.Start();
     188 
     189             Type tx = Type.GetType("string");
     190             var tx1 = Type.GetType("float");
     191             timer.Stop();
     192 
     193             Console.WriteLine("T1= " + timer.Elapsed);//0.0000471
     194 
     195             timer.Restart();
     196 
     197             tx = typeof(string);
     198             tx1 = typeof(float);
     199 
     200             timer.Stop();
     201             Console.WriteLine("T2= " + timer.Elapsed);//0.0000011
     202         }
     203 
     204         static void TestDelegate()
     205         {
     206 
     207             //类C++11风格:指定初始化容量20,使用初始化列表给部分成员赋值
     208             var lst = new List<float>(20) { 1, 3, 4, 20, -2, 9, 0 };
     209             for (var i = 0; i < lst.Count; ++i)
     210             {
     211                 //使用下标进行随机访问,说明list不是一个真正的链表,而是类似STL的Vector
     212                 Console.WriteLine(lst[i]);
     213             }
     214 
     215             //public void Sort (Comparison<T> comparison)      
     216             //public delegate int Comparison<T>(T x, T y);
     217 
     218 
     219             //这是对调用List<int>.Sort进行排序的写法,其中sort的定义及Comparison委托的定义如上
     220             lst.Sort(new Comparison<float>(delegate (float m1, float m2) //委托
     221             {
     222                 return 1;
     223             }));
     224             lst.Sort(delegate (float m1, float m2) //委托
     225             {
     226                 return 1;
     227             });
     228             lst.Sort((float m1, float m2) =>//Linq表达式
     229             {
     230                 return 1;
     231             });
     232             lst.Sort((m1, m2) => //Linq表达式
     233             {
     234                 return 1;
     235             });
     236 
     237         }
     238 
     239         static string TestRetStr()
     240         {//测试返回字符串是否会复制
     241             return "helloworld";
     242         }
     243 
     244         static void TestStrRet()
     245         {//h1 = h2 = h3说明它们返回的是同一个字符串的引用
     246             var s1 = TestRetStr();
     247             var s2 = TestRetStr();
     248             var s3 = TestRetStr();
     249             var h1 = s1.GetHashCode();
     250             var h2 = s1.GetHashCode();
     251             var h3 = s1.GetHashCode();
     252         }
     253         static void TestVirtualFuncCall()
     254         {
     255             var otx = new CTestChildX();
     256 
     257             otx.Update();//输出结果:child,如果注释1处函数不加override,输出结果为:base
     258             var oty = new CTestY();
     259             oty.Update();
     260             oty.OnUpdate();
     261 
     262         }
     263         static void TestStrModify()
     264         {
     265             var s1 = "hello";
     266             var s2 = s1;
     267             s1 += "world";
     268             Console.WriteLine(s2);
     269 
     270             var uns1 = s2.GetHashCode();
     271             Console.WriteLine(uns1);
     272         }
     273 
     274         static void Tests1()
     275         {
     276             var s1 = "hello";
     277             var uns1 = s1.GetHashCode();
     278             Console.WriteLine(uns1);
     279 
     280         }
     281 
     282         #endregion
     283 
     284         #region 2018.3.30
     285         #region ref out and template
     286         class myTemp<T1, T2>//类入口
     287         {
     288             public T1 Add(T1 a, T1 b)
     289             {//模板类型不能直接相加,必须先转为动态类型,避开编译检查,运行时动态决定类型
     290                 dynamic da = a;
     291                 dynamic db = b;
     292                 return da + db;
     293             }
     294 
     295             public void tint<T3>()//注意C++不能这么写,所有模板参数必须由类入口传入
     296             {
     297                 Type t = typeof(T3);
     298                 WriteLine(t);
     299             }
     300         }
     301 
     302         delegate void refOutFunc(ref double t1, out double t2);
     303         delegate T TemplateDelegate<T, U>(T a, U b);
     304         static void TestRefAndOut()
     305         {
     306             //ref, out 本质上都是引用
     307             //fef就为了传给函数使用,必须先初始化,但也可以传出数据,out是为了从函数中传出数据使用,不用初始化
     308             refOutFunc rof = delegate (ref double ax, out double bx) {
     309                 ax = 1; bx = 2;//ref out两种类型的变量都被更改了
     310             };
     311 
     312             double x1 = 0, x2;
     313             rof(ref x1, out x2);
     314         }
     315         static void TestTemplate()
     316         {
     317             var otp = new myTemp<int, int>();
     318             otp.tint<object>();
     319         }
     320         static T TempFunc<T, U>(T a, U b)
     321         {
     322             return a;
     323         }
     324         static void TestBufAligin()
     325         {//自定义字节BUF的对齐测试
     326             int x = 9;
     327             int y = (x + 7) & ~7;
     328             WriteLine(y);
     329         }
     330         #endregion
     331 
     332         #endregion
     333 
     334         #region 2018.4.9
     335 
     336         //BUG??????
     337         //使用StopWatch测试运行时间
     338         //两段测试A和B
     339         //测试结果受测试顺序影响,后测要比先测耗时长了许多
     340 
     341         static void TestKeyIntStr()
     342         {//
     343             var idict = new Dictionary<int, string>();
     344             var sdict = new Dictionary<string, string>();
     345 
     346             for (int i = 0; i < 1000000; i++)
     347             {
     348                 var key = i * 2 + 1;
     349                 var v = i * i + "";
     350                 idict.Add(key, v);
     351                 sdict.Add(key + "", v);
     352             }
     353 
     354             //测试 A
     355             var t1 = 100000 * Test1(idict);
     356 
     357             //测试 B
     358             var t2 = 100000 * Test2(sdict);
     359 
     360             Console.WriteLine("t1: {0},t2: {1}", t1, t2);
     361             //Console.WriteLine("dt1: {0},dt2: {1}", dt1, dt2);
     362         }
     363         static float Test1(Dictionary<int, string> dict)
     364         {
     365             var timer = new Stopwatch();
     366             timer.Start();
     367             var it = dict[2001];
     368             var t1 = timer.ElapsedTicks;
     369             timer.Stop();
     370             return (float)((float)t1 / Stopwatch.Frequency);
     371         }
     372 
     373         static double Test2(Dictionary<string, string> dict)
     374         {
     375             var timer = new Stopwatch();
     376             timer.Start();
     377             var it = dict["2001"];
     378             var t1 = timer.ElapsedTicks;
     379             timer.Stop();
     380             return (float)((float)t1 / Stopwatch.Frequency);
     381         }
     382         #endregion
     383 
     384         #region 2018.7.7
     385         #region 数组的数组,二维数组
     386         static int[] returnArray()
     387         {
     388             //数组是引用类型,分配在堆上
     389             int[] arr = { 1, 2, 3, 4 }; //虽然这样写,其实等价于int[] arr = new int[]{1,2,3,4};
     390             return arr; //返回一个数组对象
     391         }
     392         static void TestArray() {
     393 
     394             //1,一维数组
     395             char[] arr = new char[2] { 'a', 'b' }; //必须全部初始化,或不初始化
     396             int[] iarr = new int[2] { 0, 1 };
     397             char[] sarr = new char[3];
     398 
     399             //2,数组的数组,锯齿数组
     400             char[][] d2arr = new char[2][];
     401             d2arr[0] = new char[30];
     402             d2arr[1] = new char[2] { 'a', 'b' };
     403             d2arr[0][1] = 'x';
     404 
     405             //3,二维数组,矩阵
     406             int[,] i2arr = new int[2, 3];
     407             for (var i = 0; i < 2; ++i)
     408             {
     409                 for (var j = 0; j < 3; ++j)
     410                 {
     411                     i2arr[i, j] = i * 3 + j;
     412                 }
     413             }
     414         }
     415         #endregion
     416         #region 字段初始化无法使用非静态(字段、方法、属性)
     417         delegate int mydelegate(int x);
     418         //-------------------------------------------------------------------------
     419         //字段初始化无法使用非静态(字段、方法、属性)
     420         //-------------------------------------------------------------------------
     421         float fxs;
     422         static float sfxs;
     423         //float fxs2 = fxs; //error
     424         float fxs3 = sfxs; //right,可用静态字段初始化
     425         float fxs4 = TestStaticInit(); //right,调用静态函数初始化
     426         static int TestStaticInit() { return 10; }
     427         mydelegate _mydel = (x) =>//LINQ为什么可以?,从下面可知,LINQ语句只相当于一堆初始化语句的集合
     428         {
     429             //int fx = fxs; //error
     430             return 20;
     431         };
     432 
     433         #endregion
     434         #region 默认访问修饰符
     435         //1,名字空间中,最外层类及接口的默认修饰符为internal,也就是本程序集可访问
     436         //2,类中,变量,成员,类中类的默认修饰符为private
     437         //3,结构中,同类
     438         //4,接口中,所有方法和属性都为public,接口中只能有方法,不能有变量
     439         interface IMyinterface
     440         {//接口中可以有方法,抽象属性,不可以有变量
     441             int Id { get; } //抽象属性,公有
     442             void Fly();  //方法,公有
     443         }
     444         #endregion
     445         #region 类模板继承
     446         class CTClass<t1, t2, t3> //多个where的写法
     447             where t1 : struct //必须是值类型
     448             where t2 : class //必须是引用类型
     449             where t3 : new() //必须有无参构造函数
     450         {
     451             float fx, fy;
     452             public static t1 Add(t1 a, t1 b)
     453             {
     454                 return (dynamic)a + (dynamic)b;
     455             }
     456         }
     457 
     458         //模板继承的几种方式
     459         //1,全特化
     460         class CDTClass : CTClass<int, CCmpBase, CCmpBase> { }
     461 
     462         //2,原样继承,注意基类的所有约束都要重写一遍
     463         class CDTX<t1, t2, t3, t4> : CTClass<t1, t2, t3>
     464             where t1 : struct //必须是值类型
     465             where t2 : class //必须是引用类型
     466             where t3 : new() //必须有无参构造函数
     467         { }
     468         //3,偏特化,介于二者之间的形态
     469         #endregion
     470         #region 运算符重载
     471         class CCmpBase
     472         {//带有默认构造函数
     473             float _x;
     474         }
     475         class CComplex : CCmpBase
     476         {
     477             float real, image;
     478             public CComplex(float real, float image = 0)
     479             {
     480                 this.real = real;
     481                 this.image = image;
     482             }
     483 
     484             //一,类型转换 :数值转对象
     485             //CComplex cp = 2.1f 或 CComplex cp; cp = 2.1f;
     486             //C#从不调用类型转换构造函数进行类型转换
     487             public static implicit operator CComplex(float real)
     488             {
     489                 return new CComplex(real);
     490             }
     491 
     492             //二,类型转换:对象转bool
     493             public static explicit operator bool(CComplex cp)
     494             {
     495                 return cp.real != 0 && cp.image != 0;
     496             }
     497 
     498             //三,类型转换:对象转数值
     499             public static implicit operator float(CComplex cp)
     500             {
     501                 return cp.real;
     502             }
     503 
     504             //四,算术运算符重载 : +,-,*,/,%等
     505             //c#的运算符重载全部为静态函数,因此没有隐含参数
     506             //而C++运算符重载时可以重载为友元,绝大多数重载为类的成员函数,因此基本都有一个隐含参数(对象本身)
     507             public static CComplex operator +(CComplex a, CComplex b)
     508             {
     509                 return new CComplex(a.real + b.real, a.image + b.image);
     510             }
     511             public static CComplex operator ++(CComplex cp)
     512             {
     513                 cp.real++;
     514                 cp.image++;
     515                 return cp;
     516             }
     517 
     518             //五,不支持的运算符重载
     519             //1,不允许重载=运算符, C++可以,都不允许重载+=之类的
     520             //2,不允许重载括号()运算符
     521             //3,不允许重载[]运算符,因为它是索引器
     522             //public static implicit operator () (CComplex cp)
     523             //{
     524             //    return a;
     525             //}
     526 
     527             void TestPrivate()
     528             {
     529                 var cp = new CComplex(1, 3);
     530                 cp.real = 20;
     531                 cp.image = 30.0f;
     532             }
     533             public void PrintInfo()
     534             {
     535                 WriteLine("real:{0},image:{1}", real, image);
     536             }
     537         }
     538         static void TestOperatorOverload()
     539         {
     540             CComplex cp = new CComplex(1, 1);
     541 
     542             //1,同时支持前后向++,【不同于C++】
     543             cp++;
     544             ++cp;
     545 
     546             //2,但不允许连++, 【不同于C++】
     547             //cp++++或 ++++cp
     548 
     549             cp.PrintInfo();
     550 
     551             //3,支持连续+,【同于C++】
     552             CComplex cp1 = new CComplex(1, 1);
     553             var cpadd = cp + cp1 + cp1 + cp1;
     554             cpadd.PrintInfo();
     555             //类型转换运算符
     556             cp = 2.1f;
     557 
     558             //类型转换运算符
     559             //C++中是调用类型转换构造函数,而不是运算符重载
     560             CComplex cp2 = 1.0f;
     561 
     562         }
     563         #endregion
     564         #endregion
     565 
     566         #region 2018.7.11
     567         #region 两数相加函数模板实现
     568         static T MaxNum<T>(T a, T b)
     569         {
     570             return ((dynamic)a > (dynamic)b) ? a : b;
     571         }
     572         #endregion
     573         #region thread lock
     574         //thread test
     575         class Account
     576         {
     577             private object thisLock = new object();
     578             int balance;
     579             Random r = new Random();
     580 
     581             public Account(int initial)
     582             {
     583                 balance = initial;
     584             }
     585 
     586             int Withdraw(int amount)
     587             {
     588                 if (balance < 0)
     589                 {
     590                     throw new Exception("Negative Balance");
     591                 }
     592 
     593                 lock (thisLock)
     594                 {
     595                     if (balance > amount)
     596                     {
     597                         WriteLine("before-withdraw: " + balance);
     598                         WriteLine("amount to withdraw: " + amount);
     599                         balance -= amount;
     600                         WriteLine("after withdraw: " + balance);
     601                         return amount;
     602                     }
     603                     else
     604                         return 0; //transaction rejected
     605                 }
     606             }
     607 
     608             public void DoTransactions()
     609             {
     610                 for (int i = 0; i < 100; ++i)
     611                 {
     612                     Withdraw(r.Next(1, 100));
     613                 }
     614             }
     615 
     616         }
     617 
     618         static void TestObjectLock()
     619         {
     620             Account acc = new Account(1000);
     621             Thread[] threads = new Thread[10];
     622             for (int i = 0; i < 10; ++i)
     623             {
     624                 threads[i] = new Thread(acc.DoTransactions);
     625             }
     626             for (int i = 0; i < 10; ++i)
     627             {
     628                 threads[i].Start();
     629                 //threads[i].Join();
     630             }
     631 
     632 
     633         }
     634         #endregion
     635         #region derive protected
     636         class A
     637         {
     638             float fxPrivate;
     639             protected int nProtected;
     640             protected A(int x) { }
     641         }
     642 
     643         class B : A     //c++的公有继承
     644         {
     645             B(String name, int x) : base(x) { }
     646 
     647             protected int nProtected;
     648             void TestDerive()
     649             {//这里的规则与C++完全一样:
     650                 //1,子类不能访问基类的私有成员,可以访问基类的保护和公有成员
     651                 //2,保护成员可以在本类中访问(不一定是本对象中)
     652                 nProtected = 20;
     653                 base.nProtected = 10;
     654                 var ob = new B("b", 1);
     655                 ob.nProtected = 30; //类中访问类的保护成员,但不是本对象的成员
     656 
     657             }
     658         }
     659         #endregion
     660         #endregion
     661 
     662         #region 2018.7.12
     663         #region 常量和静态变量静态类readonly
     664         //----------------------------------------------------------------------
     665         //常量和静态变量,静态类
     666         //----------------------------------------------------------------------
     667         //类的静态变量和常量,都属于类而不属于对象,不能用对象来调用,只能用类名调用
     668         //这不同于C++,是更合理的设计
     669         //常量的值在类定义时就确定了,不因对象而不同,因此存放在类中更合理
     670         class CNormclass
     671         {
     672             class CInclass
     673             {
     674                 public float fx = 20;
     675             }
     676             public int _id;
     677             public const string cname = "CNormalclass";
     678 
     679             //1,常量仅能修饰 :数字,bool,字符串,null引用
     680             //不能像C++那样定义一个常量对象,这真是太悲哀了,因为很多时候这可以加速数据传递,增加安全性
     681             //由于这个原因,C#的List.ToArray每次都只能返回一个内部数组的拷贝,因此使用list存储数量较大较复杂的数据时
     682             //不要轻易使用ToArray,直接用List就行了,它也支持下标索引方式取数组元素
     683             const CInclass lst = null;
     684 
     685             //2,readonly也不能实现常量对象的效果
     686             //readonly仅表示变量本身不能被赋值,但不阻止通过对象变量更改对象内的字段
     687             //onc.readonlyobj.fx = 20
     688             public float fx = 20;
     689 
     690             private readonly CInclass readonlyobj = new CInclass();
     691   
     692             public static void Test()
     693             {
     694                 //1,不能调用非静态字段或方法
     695                 //this._id = 20; //error,没有this指针
     696 
     697                 //2,可以调用常量字段
     698                 var lname = cname;
     699 
     700                 var onc = new CNormclass();
     701 
     702                 //私有变量在类的静态方法也可以访问
     703                 //2,虽然不能更改readonlyobj本身的值,却可以更改其内部成员的值,这就是readonly的作用
     704                 onc.readonlyobj.fx = 20; 
     705             }
     706         }
     707         static class C712//类中类,默认为私有
     708         {//静态类不能实例化,且只能声明:常量,静态常量,静态属性,静态方法
     709             public const int constX = 20; //1,常量
     710             public static int staticX = 0; //2,静态常量
     711             public static int ix { set; get; } //3,静态属性
     712 
     713             //一,【静态类中不能定义实例化字段】
     714             //public int _id; 
     715 
     716             //二,【静态类中不能定义实例化字段】
     717             //void Ctest(){ //【error: 静态类中不能定义实例化方法】
     718             //    this._id = 20;
     719             //}
     720 
     721             static void Test()//4,静态方法
     722             {
     723                 //三,【静态方法中不能调用非静态变量或方法,因为没有this指针】
     724                 //_id = 20;  //error 
     725 
     726                 //四,【可以调用常量字段,这与C++不同】
     727                 var c = constX;
     728             }
     729 
     730         }
     731         public const int ixd = 20;
     732         public static float fx = 20;
     733         public void Testff()
     734         {
     735             fx = 30; //等价于Program.fx = 30,而不是 this.fx = 30;
     736             Program.fx = 30;
     737             var tx = C712.constX;
     738             C712.staticX = 30;
     739             var ix = Program.ixd;
     740 
     741             //var oc7 = new C712(); //error 静态类不能创建实例
     742         }
     743         #endregion
     744         #region 事件和委托
     745         //--------------------------------------------------------------
     746         //event -test
     747         //--------------------------------------------------------------
     748         //使用event的好处,与delegate的区别:
     749         //event 本质上是一个委托,是做了一些安全措施的委托
     750         //1,event 定义的委托只允许 +=操作,不允许=赋值,这样防止事件被误清空,delegate则没有这些限制
     751         //2,event 定义的委托只能在本类中调用,可以防止外部触发,delegate没有这些限制
     752         //3,不使用事件,delegate方式完全可以实现类似限制,通过私有变量和公有函数结合方式
     753         class EventTest
     754         {
     755             public delegate void Delx(string s = "");
     756             Delx _delegate; // 私有委托,防止外部调用
     757             public event Delx _event; //公有事件,给外部通过+=注册使用,但_event()函数只能在本类调用,不能在类外调用
     758 
     759             //-------------------------------------------------------------
     760             //1 ,委托方式
     761             //-------------------------------------------------------------
     762             //(1)外部调用eventTest.AddListener(func)方式注册事件
     763             public void AddListener(Delx callback)
     764             {
     765                 _delegate += callback;
     766             }
     767             //(2)本类对象调用此函数触发事件
     768             void DelegateBrocast()
     769             {
     770                 _delegate("delegate"); //回调,触发事件
     771             }
     772 
     773             //-------------------------------------------------------------
     774             //2,事件方式
     775             //-------------------------------------------------------------
     776             //(1)外部使用 _event += 方式注册回调函数
     777             //(2)本类对象调用此函数触发事件
     778             void EventBrocast()
     779             {
     780                 _event("event");//回调,触发事件
     781             }
     782         }
     783         class Listener
     784         {
     785             public void OnEvent(string s)
     786             {
     787                 WriteLine("on-event---------------" + s);
     788             }
     789         }
     790         static void TestEventAndDelegate()
     791         {
     792             Listener l1 = new Listener();
     793             EventTest test = new EventTest();
     794 
     795             //1,事件方式
     796             test._event += l1.OnEvent; //注册事件
     797             //test._event = l1.OnEvent; //编译错误,事件只能使用+=,防止事件被清空
     798             //test._event("event"); //编译错误,事件不能在类外调用,事件只能由其所在类调用
     799 
     800             //2,委托方式
     801             test.AddListener(l1.OnEvent); //注册委托,通过函数对委托进行注册,因委托是私有的,可防止直接操作 test._delegate()
     802         }
     803 
     804         #endregion
     805         #region 文件和目录
     806         static void FileAndDirectory()
     807         {
     808             //-------------------------------------------------------------------------
     809             //文件对象的相关操作
     810             //-------------------------------------------------------------------------
     811             //方式一,使用工具类:File类,不需生成对象
     812             var file = File.Open("f:/test.txt", FileMode.Create, FileAccess.ReadWrite);
     813             //方式二,通过FileStream的对象
     814             var filestream = new FileStream("f:/test._txt", FileMode.Create, FileAccess.ReadWrite);
     815 
     816             //-------------------------------------------------------------------------
     817             //目录文件相关操作
     818             //-------------------------------------------------------------------------
     819             //方式一,实例化DirectoryInfo类
     820             var dir = new DirectoryInfo("f:/tolua");
     821             //(1)获取目录
     822             foreach (var d in dir.GetDirectories("*.*", SearchOption.AllDirectories))
     823             {
     824                 WriteLine(d.FullName);
     825             }
     826             //(2)获取文件
     827             foreach (var fileinfo in dir.GetFiles("*.*", SearchOption.AllDirectories))
     828             {
     829                 WriteLine(fileinfo.FullName);
     830             }
     831 
     832             //方式二,使用工具类: Directory类,不需生成对象
     833             //(1)获取目录
     834             var dirs = Directory.GetDirectories("f:/tolua", "*.*", SearchOption.AllDirectories);
     835             //(2)获取文件
     836             dirs = Directory.GetFiles("f:/tolua", "*.*", SearchOption.AllDirectories);
     837 
     838             for (int i = 0; i < dirs.Length; ++i)
     839             {//打印输出
     840                 WriteLine(dirs[i]);
     841             }
     842 
     843         }
     844         #endregion
     845         #endregion
     846 
     847         #region 2018.7.17
     848         #region 计算机中浮点数的存储
     849         static void TestFloat()
     850         {
     851             using (var ms = new MemoryStream())
     852             {
     853 
     854                 using (var br = new BinaryWriter(ms))
     855                 {
     856                     br.Write(125.5f);
     857                     var bytes = ms.GetBuffer();
     858                 }
     859             }
     860             unsafe
     861             {
     862                 float fx = 125.5f;
     863                 int* pfx = (int*)(&fx);
     864             }
     865 
     866         }
     867 
     868         #endregion
     869         #region 位移运算
     870         static void TestBitShift()
     871         {   //----------------------------------------------------------------------------
     872             //十进制数转二进制:
     873             //1,原理:将数X右移1位,最低位被移出,再左移,得到了数X0,则x-x0即为最低位的值
     874             //2,手工算法:根据1的原理,不断的对一个数整除2得余数,了终得到余数序列即是二进制的反向序列
     875             //3,左移等价于乘2,右移等价于除2,原理是乘法的竖式算法,
     876             //  101
     877             //x 010
     878             //-------           竖式算法适用于任何进制的加减法和乘法运算
     879             //  000
     880             //+101
     881             //-------
     882             // 1010
     883             //----------------------------------------------------------------------------
     884 
     885             int x = 7;
     886             List<Byte> bits = new List<Byte>(4);
     887             while (x != 0)
     888             {
     889                 var left = x - ((x >> 1) << 1);//<=> x - x/2*2
     890                 bits.Add((byte)left);
     891                 x = x >> 1;
     892             }
     893         }
     894         #endregion
     895         #region IEnumerableAndLinQ
     896         class Product
     897         {
     898             public int cateId;
     899             public string name;
     900         }
     901         class Category
     902         {
     903             public int id;
     904             public string name;
     905         }
     906         public static void TestIEnumerableAndLinq()
     907         {
     908             Category[] cates = new Category[]
     909             {
     910                 new Category{id = 1, name = "水果"},
     911                 new Category{id = 2, name = "饮料"},
     912                 new Category{id = 3, name = "糕点"},
     913             };
     914 
     915             Product[] products = new Product[]
     916             {
     917                 new Product{cateId=1, name = "apple"},
     918                 new Product{cateId=1, name = "banana"},
     919                 new Product{cateId=1, name = "pear/梨"},
     920                 new Product{cateId=1, name = "grape/葡萄"},
     921                 new Product{cateId=1, name = "pineapple/菠萝"},
     922                 new Product{cateId=1, name = "watermelon/西瓜"},
     923                 new Product{cateId=1, name = "lemon/柠檬"},
     924                 new Product{cateId=1, name = "mango/芒果"},
     925                 new Product{cateId=1, name = "strawberry/草莓"},
     926                 new Product{cateId=2, name = "bear/啤酒"},
     927                 new Product{cateId=2, name = "wine"},
     928                 new Product{cateId=3, name = "cake"},
     929                 new Product{cateId=3, name = "basicuit/饼干"},
     930 
     931             };
     932             var rets = cates.Where((x) => { return x.id > 1 && x.id < 5; });
     933             var iter = rets.GetEnumerator();
     934 
     935             while (iter.MoveNext())
     936             {
     937                 //WriteLine(iter.Current);
     938             }
     939 
     940             var set = from c in cates
     941 
     942                           //这里只能写一个条件,就是equals,用来关联两个表
     943                           //并且 c相关的条件只能写在equals左边,p相关条件只能写equals右边
     944                       join p in products on c.id equals p.cateId
     945 
     946                       //这里存放的是 products中的元素合集,而不是cates中的元素合集
     947                       //如果 from p in products join c in cates on c.id equals p.id into xgroups
     948                       //则xgroups中放的是cates中的元素集合
     949 
     950                       //这里是说将products中cateId等于c.id的所有元素放入一个组xgroups中
     951                       into xgroups
     952                       orderby c.id descending //对set中的结果进行降序排列
     953 
     954                       //where m > 4 && m < 10 //这里就可以写多个条件了
     955 
     956                       //from in 相当于外层循环,join in 相当于内层循环
     957                       //select在双层循环体中,每执行一次循环,【如果符合条件】,则执行一次结果选择
     958                       //双层循环完成后,最终将很多条选择提交给set
     959                       //【注意,如果不符合条件 select不会执行】
     960                       select new { cate = c.name, grp = xgroups }; //可以生成一个新的对象
     961 
     962             foreach (var p in set)
     963             {
     964                 WriteLine("分组:" + p.cate);
     965                 foreach (var g in p.grp)
     966                 {
     967                     WriteLine(g.cateId + "," + g.name);
     968                 }
     969             }
     970         }
     971 
     972         #endregion
     973         #region 类和继承
     974         class CTestX
     975         {
     976             public virtual void OnUpdate()
     977             {
     978                 Console.WriteLine("base-on-update");
     979             }
     980             public virtual void OnUpdate2()
     981             {
     982                 Console.WriteLine("base-on-update2");
     983             }
     984             public void Update()
     985             {
     986                 this.OnUpdate(); //注释1,如果子类有overide则调用子类的,否则调用自己的
     987             }
     988 
     989             public CTestX()
     990             {
     991 
     992             }
     993             protected CTestX(float fx)
     994             {
     995                 WriteLine("CTestX");
     996             }
     997 
     998             ~CTestX()
     999             {
    1000                 WriteLine("~Ctestx");
    1001             }
    1002             public float fx;
    1003             string name;
    1004         }
    1005 
    1006         //子类不能访问基类任何私有的东西,包括方法,字段,属性,但它们都被继承了,属于子类,从实例内存可证
    1007         //方法包括构造函数,即当基类是私有构造函数时,子类无法在初始化列表中调用base()来初始化
    1008         class CTestChildX : CTestX
    1009         {
    1010             CTestX otestx;
    1011 
    1012             public CTestChildX() : base(1)//当基类为私有构造时,这里base无法调用
    1013             {//当基类没有无参构造函数时,必须在初始化列表中初始化所有成员对象,如otestx
    1014                 WriteLine("CTestChildX");
    1015             }
    1016 
    1017             //注意overide与virtual的区别:
    1018             //1,overide : 表明【函数是对基类的重写】 且 【本身是虚函数可被子类重写】
    1019             //【函数会与基类、子类发生虚函数机制】
    1020             //2,virtual : 仅表明函数是个虚函数,不会与基类发生虚函数机制
    1021             //如果子类overide了该函数,则会与子类发生虚函数机制
    1022             //3,多级继承中只要有一级没override,虚函数机制就会打断在此层级,见
    1023 
    1024             //override在编译层的机制是重写虚函数表中的函数地址
    1025             //即将继承而来的虚函数表中的虚函数地址替换成本类的虚函数地址
    1026             public static void TestDerive()
    1027             {
    1028                 //                 CTestX ox = new CTestChildX();
    1029                 //                 ox.OnUpdate(); //base-on-update,无虚函数机制发生
    1030                 //                 ox.OnUpdate2(); //child-on-update2,虚函数机制发生
    1031                 //                 ox = new CTestY();
    1032                 //                 ox.OnUpdate(); //base-on-update,无虚函数机制发生
    1033                 CTestChildX ocx = new CTestZ();
    1034                 ocx.OnUpdate(); //grand-child-on-update
    1035             }
    1036 
    1037             public override void OnUpdate()
    1038             {
    1039                 Console.WriteLine("child-on-update");
    1040             }
    1041             public override void OnUpdate2()
    1042             {
    1043                 Console.WriteLine("child-on-update2");
    1044             }
    1045 
    1046             ~CTestChildX() //不支持virtual
    1047             {
    1048                 WriteLine("~CTestChildX");
    1049             }
    1050         }
    1051 
    1052         class CTestY : CTestChildX
    1053         {
    1054             public override void OnUpdate()
    1055             {
    1056                 Console.WriteLine("grand-child-on-update");
    1057 
    1058             }
    1059         }
    1060         class CTestZ : CTestY
    1061         {
    1062             //因为这里的Update不是虚函数,因此
    1063             public void OnUpdate()
    1064             {
    1065                 Console.WriteLine("grand-grand-child-on-update");
    1066 
    1067             }
    1068         }
    1069 
    1070 
    1071         struct CTX
    1072         {
    1073             void Test() {//不支持C++的const语法
    1074             }
    1075         }
    1076 
    1077         //1,不能继承结构,可以实现接口,
    1078         //2,不能有虚函数
    1079         struct CCTX //: CTX 
    1080         {
    1081             public void Test()
    1082             {
    1083 
    1084             }
    1085         }
    1086 
    1087         #endregion
    1088         #region 字符串格式化
    1089         static void TestStrFormat()
    1090         {
    1091             var str = Console.ReadLine();
    1092             while (str != "exit")
    1093             {
    1094                 int ix;
    1095                 Int32.TryParse(str, out ix); //ix = 120
    1096                 var f1 = string.Format("{0 :d5}", ix); //"00120"
    1097                 var f2 = string.Format("{0,-10:d5}", ix);//"00120     "
    1098                 var f3 = string.Format("{0:x}", ix); //16进制输出到字符串
    1099                 var f4 = string.Format("{0:0.000}", ix);//浮点数 120.000
    1100                 Console.WriteLine("-----------begin-------------");
    1101                 Console.WriteLine(f1);
    1102                 Console.WriteLine(f2);
    1103                 Console.WriteLine(f3);
    1104                 Console.WriteLine(f4);
    1105                 Console.WriteLine("------------end-------------");
    1106 
    1107                 str = Console.ReadLine();
    1108             }
    1109         }
    1110         #endregion
    1111         #endregion
    1112 
    1113         #region 2018.7.25
    1114         #region 引用返回值(不是右值引用)
    1115         static int[] _bookNum = new int[] { 1, 2, 3, 4, 5, 6 };
    1116         static ref int GetBookNumber(int i)
    1117         {
    1118             int x = 10;
    1119             return ref _bookNum[i];
    1120         }
    1121         static void TestRefReturn()
    1122         {
    1123             ref int rfn = ref GetBookNumber(1);
    1124             rfn = 10101; //_bookNum[1]变成了 10101
    1125             int vn = GetBookNumber(2);
    1126             vn = 202; //_bookNum[2]未变,仍为3
    1127 
    1128             ref int x = ref vn;
    1129         }
    1130         #endregion
    1131         #region 索引器
    1132         class mylist<T>
    1133         {
    1134             const int defaultCap = 4;
    1135             T[] items;
    1136             int count;
    1137             int cap = defaultCap;
    1138             public mylist(int cap = defaultCap)
    1139             {
    1140                 if (cap != defaultCap)
    1141                     this.cap = cap;
    1142                 items = new T[cap];
    1143             }
    1144             public T this[int idx] {
    1145                 set {
    1146                     items[idx] = value;
    1147                 }
    1148                 get {
    1149                     return items[idx];
    1150                 }
    1151             }
    1152 
    1153         }
    1154         enum Color
    1155         {
    1156             red,
    1157             green,
    1158             blue,
    1159             yellow,
    1160             cyan,
    1161             purple,
    1162             black,
    1163             white,
    1164         }
    1165 
    1166         static void TestIndexer(Color clr = Color.black)
    1167         {
    1168             mylist<string> lst = new mylist<string>();
    1169             lst[1] = "hello";
    1170         }
    1171         #endregion
    1172         #region 部分类
    1173         //部分类的作用是可以把一个庞大的类拆分到多个文件,每个文件实现一部分
    1174         //而不是实现像C++那样将声明与实现分开
    1175         //若要实现声明(接口)与实现分开,应该使用抽象类或接口
    1176         partial class CPartclass
    1177         {
    1178             public void ShowName() {
    1179                 WriteLine("show name");
    1180             }
    1181         }
    1182 
    1183         partial class CPartclass
    1184         {
    1185             public void ShowAge(){
    1186                 WriteLine("show age");
    1187             }
    1188         }
    1189         static void TestPartclass()
    1190         {
    1191             CPartclass opc = new CPartclass();
    1192             opc.ShowName();
    1193             opc.ShowAge();
    1194         }
    1195         #endregion
    1196         #region 动态分配对象数组C#与C++的区别
    1197         struct xobject 
    1198         {
    1199             public float fx, fy, fz; //全是public的
    1200         }
    1201         static void TestDynamicAllocInCSharpCpp()
    1202         {
    1203             //1,对于引用类型数组,需要两步才能完成,因为数组中存放的是对象的引用
    1204             //1.1 c#中
    1205             xobject[] arr = new xobject[2];//这时候,只是分配了一个引用数组,arr[0],arr[1]均为null
    1206             for (int i = 0; i < 2 ; i++)
    1207             {
    1208                 arr[i] = new xobject(); //为数组中每个引用申请对象
    1209             }
    1210 
    1211             //1.2 c++中
    1212             //xobject** pp = new xobject*[2];
    1213             //pp[0] = new xobject();
    1214             //pp[1] = new xobject();
    1215 
    1216             //2 对于值类型数组,则只需一步,因为数组中放的就是值,这在C#与CPP中都一样
    1217             //2.1 C#中
    1218             int[] iarr = new int[2];
    1219             var a0 = iarr[0]; //0
    1220             var a1 = iarr[1]; //0
    1221 
    1222             xobject[] varr = new xobject[3];
    1223             varr[0].fx = 0.1f;
    1224             varr[1].fy = 2.5f;
    1225             varr[2].fz = 12;
    1226 
    1227             //2.2,在C++中
    1228             //xobject* pobjs = new xobject[2]; //每个数组元素都是一个值类型对象
    1229             //pobjs[0].fx = 20;
    1230         }
    1231         #endregion
    1232         #region Object?语法
    1233         static void TestobjAsk()
    1234         {
    1235             object obj = "hello";
    1236             WriteLine(obj?.ToString());//如果obj不为null则调用tostring
    1237         }
    1238         #endregion
    1239         #region C#默认字符编码及系统默认编码
    1240         //默认编码为unicode,字符串本身的编码并不重要,字节读写时指定的编码才重要,如下面的BinaryWriter
    1241         //Encoding.Default是当前系统的默认编码,并不是c#字符串的默认编码
    1242         //Encoding.Default规则:汉字2字节,其它1字节
    1243         static void TestDefaultStrEncoding()
    1244         {
    1245             string str = "hdd好";
    1246             
    1247             using (var ms = new MemoryStream())
    1248             {
    1249                 using (var br = new BinaryWriter(ms, Encoding.Default))
    1250                 {
    1251                     br.Write(str);
    1252                     var len = ms.Length-1;
    1253                     WriteLine(len);
    1254 
    1255                 }
    1256             }
    1257         }
    1258         #endregion
    1259         #region 属性attribute和反射
    1260         class ReflectableClass
    1261         {
    1262             public float fx;
    1263             public string str;
    1264             //static const int x = 20; //这在C++中是可以的
    1265             public void Printstr(string str, int idx)
    1266             {
    1267                 WriteLine(str + ":" + idx);
    1268             }
    1269         }
    1270         static void TestReflect()
    1271         {
    1272             
    1273             ReflectableClass ox = new ReflectableClass();
    1274             Type t = typeof(ReflectableClass);//Type.GetType("ConsoleApplication1.Program.ReflectableClass");//ox.GetType();
    1275             var tname = t.GetField("name");
    1276             var tfx = t.GetField("fx");
    1277             var func = t.GetMethod("Printstr", new Type[] {typeof(string),typeof(int) });
    1278             func.Invoke(ox, new object[] { "helloworld", 1 });
    1279 
    1280             
    1281             Type Ts = Type.GetType("System.String");
    1282             var fs = Ts.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });
    1283             var subs = fs.Invoke("hello world", new object[] { 1, 5 });
    1284             WriteLine(subs);
    1285         }
    1286 
    1287         static void TestAttribute()
    1288         {
    1289 
    1290         }
    1291 
    1292         #endregion
    1293         #endregion
    1294         #region JSON
    1295         void TestJson()
    1296         {
    1297 
    1298         }
    1299 
    1300         #endregion
    1301         #region CPP与CS间数据传递转换
    1302 
    1303         #endregion
    1304         #region 线程
    1305         #endregion
    1306         #region 线程池
    1307         #endregion
    1308         #region 任务
    1309         #endregion
    1310         #region 程序集
    1311         #endregion
    1312         #region 多线程调试
    1313         #endregion
    1314 #region 扩展方法测试
    1315         static void TestExtMethod()
    1316         {
    1317             ExtTargetCls oet = new ExtTargetCls();
    1318             oet.methodExt(100);
    1319             WriteLine(oet.sum);
    1320         }
    1321         #endregion
    1322         class CMyList
    1323         {
    1324             //readonly仅表示变量本身不能被赋值,但不阻止通过对象变量更改对象内的字段
    1325             //on._id = 100 //ok
    1326             //on = new CNormclass() //error
    1327 
    1328             public readonly int[] rarr = { 1, 2, 3, 4 };
    1329             public readonly int rix = 30; //可在初始化时赋值
    1330             public readonly CNormclass on = new CNormclass();
    1331             public CMyList()
    1332             {
    1333                 rix = 1; //可在构造函数中赋值
    1334             }
    1335             public int[] toArray()
    1336             {
    1337                 return rarr;
    1338             }
    1339 
    1340             public void Clear()
    1341             {
    1342                 for(var i=0; i < rarr.Length; ++i)
    1343                 {
    1344                     rarr[i] = 0;
    1345                 }
    1346             }
    1347             public static implicit operator CMyList(int ix)
    1348             {
    1349                 return new CMyList();
    1350             }
    1351 
    1352         }
    1353 
    1354         // ctrl + w, t 可以察看所有待做任务
    1355         static void Main(string[] args)
    1356         {
    1357             TestExtMethod();
    1358             //TestReflect();
    1359             //TestDefaultStrEncoding();
    1360             //TestDynamicAllocInCSharpCpp();
    1361             //TestPartclass();
    1362             //TestRefReturn();
    1363             //TestOperatorOverload();
    1364             //    CTestChildX.TestDerive();
    1365             //TestFloat();
    1366 
    1367             //var arr = returnArray();
    1368  
    1369         }
    1370 
    1371     }
    1372     #region 扩展方法
    1373     sealed class ExtTargetCls
    1374     {
    1375         public float sum = 10;
    1376     }
    1377     //扩展方法必须在顶级静态类中定义,不能是内部类
    1378     //能不能通过扩展方法来修改类库以达到不法目的? 不能,因为扩展方法只能修改类的公有成员
    1379     static class ExtentMethod
    1380     {
    1381         public static void methodExt(this ExtTargetCls target, float add)
    1382         {
    1383             target.sum += add;
    1384         }
    1385     }
    1386     #endregion
    1387 }
  • 相关阅读:
    C++学习9 this指针详解
    福建省第八届 Triangles
    UVA 11584 Partitioning by Palindromes
    POJ 2752 Seek the Name, Seek the Fame
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    HDU 2988 Dark roads(kruskal模板题)
    HDU 1385 Minimum Transport Cost
    HDU 2112 HDU Today
    HDU 1548 A strange lift(最短路&&bfs)
  • 原文地址:https://www.cnblogs.com/timeObjserver/p/9391470.html
Copyright © 2011-2022 走看看