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");
}
}
```