C# 共筆 === ###### tags: `NCNU` `C#` ## Input `Console.ReadLine()`: 讀取一行 ### 空格格開多個輸入值 ```csharp= string text = Console.ReadLine(); string[] storage = text.Split(' '); ex: a = int.Parse(storage[0]); b = int.Parse(storage[1]); c = int.Parse(storage[2]); ``` #### 簡寫 ```csharp= int[] allNum = Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse); ``` #### Another split example(delimiters) source: [link](https://syntaxdb.com/ref/csharp/string-split) ```csharp= Console.Write("Please input 3 integers: "); string str = Console.ReadLine(); char[] delimiters = {' '}; //char[] delimiters = {' ', ','}; // split by space & comma string[] Array = str.Split(delimiters); //will split names using space as delimiter int[] myinteger = new int[Array.Length]; int i = 0,total = 0; while (i < Array.Length) { myinteger[i] = Int32.Parse(Array[i]); total += myinteger[i]; Console.WriteLine("{0}", myinteger[i]); i++; } ``` ## Output ```csharp= Console.WriteLine("xxx {0}", var); Console.Write("xxx"); ``` ## File 讀寫 ### 讀檔 ```csharp= using System.IO; // System.Text.Encoding.Default 避免亂碼 StreamReader sr = new StreamReader("input.txt", System.Text.Encoding.Default); // 檔案要放在 專案 /bin/debug 中 (若有 release 也要放一份), mac 好像要放在專案裡面 // 在很短的情形 fr.ReadToEnd() 與 fr.ReadLine() 相同 string readin; while(!sr.EndOfStream) { readin = sr.ReadLine(); } sr.Close(); ``` :::warning 檔案讀取如果沒有說幾行 每一行後面加個空白, 最後一筆換行 ex: ``` // input.txt xxx 80 90 yyy 75 68 zzz 74 35 ``` ```csharp= string readin = ""; while(!sr.EndOfStream) { readin += sr.ReadLine() + " "; } Console.WriteLine(readin); // xxx 80 90 yyy 75 68 zzz 74 35 ``` ::: ### 寫檔 ```csharp= StreamWriter sw = new StreamWriter("Output.txt"); sw.WriteLine("xxx"); sw.Close(); ``` ## Format ### Type #### Array ```csharp= int[] myArr = new int[100]; int[] myArr = new int[] {1, 2, 3}; ``` 2DA ```csharp= int[,] myArr = new int[5, 10]; /* 不規則陣列 */ int[][] myjag = new int[3][]; int[][] myArr = new int [5][10]; int[,] myArr = new int[] {{1, 2}, {1, 2}, {1, 2}}; ``` 陣列初始化 ```csharp= int []a = new int []{1,2,3,5,6}; int [,]a = new int []{{1,2,3},{4,5,6},{7,8,9}}; string[] RoleName = new string[] {"魯夫","喬巴"}; ``` > 連續記憶體空間 > [name=Array Memory] --- #### ArrayList - 一般使用方法 ```csharp= using System.Collections; /* 需引入 System.Collections方可使用AraryList*/ /* Main 內*/ ArrayList myarraylist = new ArrayList(); for (int i = 0; i < 10; i++) { myarraylist.Add(i); } // 0 1 2 3 4 5 6 7 8 9 myarraylist[myarraylist.Count/2] = 26; // 0 1 2 3 4 26 7 8 9 Console.WriteLine("現在的長度:{0}", myarraylist.Count); // 長度:10 for (int i = 0; i < myarraylist.Count; i++) Console.Write("{0} ", myarraylist[i].ToString().PadLeft(3)); myarraylist.RemoveAt(3); // 0 1 2 4 26 7 8 9 myarraylist.Remove(2); // 0 1 4 26 7 8 9 myarraylist.Insert(6,200); // 0 1 4 26 7 8 200 9 ``` - 存Structor到ArrayList ```csharp= /* * ArrayList可存任何形態 * Array宣告int則只可塞入int。 */ /* * 塞入Structor範例 */ public struct Personal { public int age; public string name; } // ... // ... // ... ArrayList myarraylist02 = new ArrayList(); for (int i = 0; i < 10; i++) { Personal anyperson; anyperson.age = i + 50; anyperson.name = (i + 100).ToString(); myarraylist02.Add(anyperson); } for (int i = 0; i < myarraylist02.Count; i++) { Personal temp = (Personal)myarraylist02[i]; Console.Write("\nname={0} ,age={1}", temp.name, temp.age); } ``` #### foreach ```csharp= int[] grade = new int[] {10, 20, 30}; foreach(int value in grade){ ... } ``` ##### Function Of Array --- - GetUpperBound() : index最大值 - int [] a1 = new int [10]; - a1.GetUpperBound() : 取第1維index // get 9 - int [,] a2 = new int [3,3]; - a2.GetUpperBound() : 取第2維index // get 2 - GetLowerBound() - GetLength() - CreateInstance() - SetValue() - GetValue() --- > Example: ```csharp= ...bla...bla...bla... static void Main(string[] args) { int[] array_name = new int[100]; int i; for (int i = 0; i < array_name.Length; i++) array_name[i] = i; for (int j = 0; j < array_name.Length; j++) Console.WriteLine("{0}", array_name[j]); Console.WriteLine("請按任意按鍵..."); Console.ReadKey(); } ``` ### string method `{var}.toString('格式')` > Example: > method:one: ```csharp= float fnum = -3.14f; fnum.toString('0.0000'); // -3.1400 ``` > method:two: ```csharp= float fnum = -3.14f; Console.WriteLine({0:0.0000},fnum); //-3.1400 ``` #### 輸出其他格式 ```csharp= int num = 1234.567; Console.WriteLine("numC={0:C} numC3={0:C3}", num, num); // numC=NT$1,234.57 numC3=NT$1,234.567 ``` 參考課本 2-32, 2-33 #### 型態強制轉型(cast) ```csharp= float a = 1.8f; int i = (int)a; /* 若要處理四捨五入 */ int i = (int)(a + 0.5); ``` ## 自訂類別列舉常數 enumalte > int 預設為 0 開始,後續+1...,如果中間更改常數值,後面不給定值會接續更改後的數值 ```csharp= enum WeekDays:int { Monday = 1; //default with 0, but now defined with 1, so it's 1. Tuesday, // due to Monday = 1, monday++ then Tuesday = 2 Wednesday, Thursday = 9, Friday, // due to Thursday = 9, Thursday++ then Friday = 10 Saturday, Sunday }; staic void main(string[] args) { Console.WriteLine("星期一列舉常數值:{0}",(int)WeekDays.Monday); // 星期一列舉常數值:1 } ``` :::info [Ref::M$::enum](https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/enum) ::: ## 結構 Struct ```csharp= // 預設不加 public, 預設為 private // // // private struct StudentGrade { // 裡面一定要加public, 否則外部無法修改 public int math; public int program; public int total; public float average; } static void Main(string[] args) { StudentGrade t1; Console.WriteLine("請輸入數學成績:"); t1.math = Int32.Parse(Console.ReadLine()); Console.WriteLine("請輸入程設成績:"); t1.prog = Int32.Parse(Console.ReadLine()); t1.total = t1.math + t1.prog; t1.average = t1.total / 2.0f; Console.WriteLine("數學:{0}, 程設:{1}, 總分:{2}, 平均:{3}", t1.math, t1.prog, t1.total, t1.average); } ``` #### new ```csharp= StudentGrade allStu; StudentGrade[] allStu = new StudentGrade[100]; ``` ## if-else :::danger C# 無法使用這種寫法,編譯會錯誤!! ```csharp= int k = 10; if(k){ ... } ``` ::: ## switch 可整數、"字串"、'字元', :warning:不可浮點數 ## 比大小 可用 `Int32.MaxValue` 來獲得最大的值,反之可以加上負號 ```csharp= max = -Int32.MaxValue; // 任意比它大 min = Int32.MaxValue; // 任意比它小 ...比大小... ``` ### Array ```csharp= Array.Sort(allNum); int minV = allNum[0]; int maxV = allNum[allNum.Length - 1]; // or Array.Reverse(allNum); maxV = allNum[0]; ``` ## call by reference ```csharp= public static void swap(ref int n1, ref int n2) { int tmp = n1; n1 = n2; n2 = tmp; } static void Main(string[] args) { int n1 = 10, n2 = 20; swap(ref n1, ref n2); } ``` :::danger 記得傳址時,變數要有初始值,所以不能這樣: ```csharp= int n3; addTen(ref n3); // 錯誤,沒有初始值 ``` ::: ## 函數多載 允許同名 function overload,也解決命名煩惱。 雖然函數同名,但能透過傳入的參數數量辨別。 ```csharp= public static double Add(double a, double b) { return (a + b); } public static double Add(double a) { return a + 10.0; } ``` ## Try Catch ```csharp= try { ... } catch (SystemException ex) { Console.WriteLine("錯誤訊息:{0}", ex.Message); Console.WriteLine("哪裡出問題:{0}", ex.StackTrace); Console.WriteLine("問題類別:{0}", ex.GetType().ToString()); Console.WriteLine("source:{0}", ex.Source); } finally { ... } ``` ### 檢查運算是否 overflow **checked** 關鍵字是用來明確啟用整數型別算術運算和轉換的溢位檢查。 ``` try { a = checked(a * 10); } catch(SystemException ex) { Console.WriteLine("\n----------------\n{0}", ex.StackTrace); Console.WriteLine("\n{0}\n----------------\n", ex.Message); } ``` ## 物件導向 ```csharp= public class ThreeNPlusOne { int N; int count; /* * private int num0; * 若前有'private'則將無法透過在Main()內以ThreeNPlusOne.num呼叫 * 可透過以下方式取得 * public void getNum() { Console.Write(num); } * * public int num1; * 前面為public則可直接以ThreeNPlusOne.num1進行存取。 * * protected int num2; * * int num3; //預設為private * * public double IN_Degree { set { in_degree = value; } get { return in_degree; } } */ public void ShowResult() { Console.WriteLine("\nN = {0}, 執行 {1} 次", N, count); } public void Process() { int originN = N; while (N != 1) { count++; if (N % 2 == 0) { N /= 2; } else { N = 3 * N + 1; } } N = originN; } // Constructor 跟類別同名,不能有 return public ThreeNPlusOne() { N = 0; // this.N = 0; count = 0; // this.count = 0; } public ThreeNPlusOne(int n) { N = n; count = 0; } } static void Main(string[] args) { Console.Write("請輸入正整數: "); int N = int.Parse(Console.ReadLine()); ThreeNPlusOne a1 = new ThreeNPlusOne(N); a1.Process(); a1.ShowResult(); } ``` ### 白手套(? 避免使用者直接操作到私有變數,可以設立一個對外的變數(中介層),透過對它的操作來更動私有變數。 ```csharp= public class Test { private int money = 0; // protect private Data public int IN_money { set { if(value >= 0) { money = value; } } get { return money; } } } ... Test t1 = new Test(); t1.IN_money = 60; ``` :::info ``value`` 為關鍵字,取到的值為 main 函數中設定的值。 ex: ``` t1.out_var = 123; // value = 123 ``` ::: ## 結尾/雜物 ```csharp= Console.WriteLine("請按任意鍵繼續..."); Console.ReadKey(); ``` ## Destructor ```csharp= /*只有一種Destructor,清除佔用的記憶體*/ ~ThreeNPlusOne() { Console.WriteLine("This is a destructor...."); } ``` ## 繼承 ```csharp= public class A { public int x; private int y; protected int z; public A(int a, int b, int c) { x = a; y = b; z = c; } public void Show() { Console.WriteLine("x={0}, y={1}, z={2}",x , y, z); } } // B 繼承至 A public class B : A { public int w; public B(int a, int b, int c, int d) : base(a, b, c) { w = d; } } static void Main(string[] args) { B objb = new B(10, 20, 30, 40); /* * B -> w = 40 * A -> a = 10, b = 20, c = 30 * 如同 java 内,public class B extends A; */ objb.Show(); // 10,20,30,40 objb.x = 100; // success: x 是 public objb.Show(); // 100,20,30,40 objb.y = 200; // error: y 是 private objb.z = 300; // error: z 是 protected,下方有 success 例子。 } ``` ==B繼承A,且可使用A's protected== ```csharp= public class A { public int x; private int y; protected int z; public A(int a, int b, int c) { x = a; y = b; z = c; } public void Show() { Console.WriteLine("x={0}, y={1}, z={2}",x , y, z); } } // B 繼承至 A public class B : A { public int w; public B(int a, int b, int c, int d) : base(a, b, c) { w = d; } static void Main(string[] args) { B objb = new B(10, 20, 30, 40); objb.z = 300; // success: z 是 protected,且在 B 内處理。 objb.Show(); // 10,20,300,40 } } ``` 繼承後也可以 override 原屬性/方法 ```csharp= public class A { public void Show() { Console.WriteLine("Parent"); } } // B 繼承至 A public class B : A { // override Parent's method new public void Show() { Console.WriteLine("Child"); } } ```