# C# 程式語言
###### tags: `程式筆記` `web111a` `C#`
* **老師:戴德仁**666
* 時間:2022/3/18
## 導師時間
1. 請同學注意上課、點名時間8:20,逾時會記曠課
2. 班長提供請假名單
3. 課表更動請查閱共用
4. 第52屆全國技能競賽中區分區技能競賽
5. 課務用電腦不得私自安裝非授權軟體
6. 建議購買SSD/256G外接硬碟
## 專題注意事項
1. 需部署至課務伺服器
2. 1-3人
## 環境建置
1. 7-ZIP
2. notepad++
3. fastcopy
4. git
1. 路徑C:\Git
1. 取消勾選 Windows Explorer integration
1. 編輯器選擇 nano
5. Cmder
6. nvm
1. 路徑C:\nvm、C:\nvm\nodes
7. XAMPP
8. composer
1. develop mode要勾選
## Git
### 基本設定
1. 調整 options
2. [初次設定 Git](https://git-scm.com/book/zh-tw/v2/%E9%96%8B%E5%A7%8B-%E5%88%9D%E6%AC%A1%E8%A8%AD%E5%AE%9A-Git)
1. username
1. email
1. default editor
## 終端機設定
* 命令提示字元中可以設定>進階,以管理員身份執行就不用每一次都按
### Cmder
1. 控制台>系統>進階系統設定>環境變數>path
2. 新增 cmder 路徑 C:\cmder
## node設定
* 安裝
```bash=
nvm list avaiable
nvm install [版本號]
nvm use [版本號]
```
* 測試
```bash=
node
```
## SAMPP設定
1. 設定環境變數
* D:\xampp\php
* D:\xampp\mysql\bin
2. 設定檔
* 檔案名稱:setup_xampp.bat
3. 確認是否設定完成
```bash=
php --version
```

```bash=
mysql --version
```

## composer
Composer是PHP的軟體包管理系統
### 指定composer根位置
1. 新增系統變數
1. 變數名稱:COMPOSER_HOME
1. 變數值:c:\composer
1. 設定環境變數
1. path 增加 c:\composer\vendor\bin
## Visual Studio 2019 簡介
基本完整的開發工具集,它包括了整個軟體生命週期中所需要的大部分工具,如UML工具、程式碼管控工具、整合開發環境(IDE)等等。
* 如需新增套件,可至控制台>程式集>變更
* ASP.NET
* AZURE
* .NET 桌面開發
* 通用 Windows 平台開發
* VS 擴充功能開發
## 延伸
### 環境變數
#### [環境變數教學](https://shaochien.gitbooks.io/command-line-and-environment-variable-tutorial/content/environment-variable.html)
> 如果沒有把軟體本身「可執行檔的路徑」設定在 PATH 環境變數中的話,則每次執行該命令必須使用以下兩種方式:
>
> * 到該程式所在的執行檔目錄底下執行
> * 輸入執行檔的完整路徑
#### 例如:command not found 就是路徑沒設定好
[zsh command not found](https://bonze.tw/mac--e8-a7-a3-e6-b1-ba-zsh-command-not-found/)
### SAMPP
允許使用者可以在自己的電腦上輕易的建立網頁伺服器。
> XAMPP的名稱來自以下組合:
> **X**(支援跨平台)
> **A**pache
> **M**ySQL或MariaDB
> **P**HP
> **P**erl
* [Mac 使用 XAMPP 建立 php 開發環境 教學](https://medium.com/@mpp21x/%E4%BD%BF%E7%94%A8-xampp-%E5%BB%BA%E7%AB%8B-php-symfony-%E9%96%8B%E7%99%BC%E7%92%B0%E5%A2%83-b5a793ab5b6b)
* Virual Host
* 設定 VirtualHost 目的是使用同一個伺服器架設多個網站,當使用者以不同網域名稱連到該主機時, web server 會依據不同的目的網頁需求,回應不同的網頁內容。
### PHP
* scripting language
* server-side language
* creating dynamic web pages
* 
### Node.js
> Node.js 是能夠在伺服器端運行 JavaScript 的開放原始碼、跨平台執行環境。
JavaScript 通常作為使用者端程式設計語言使用,以JavaScript 寫出的程式常在使用者的瀏覽器上執行。Node.js 的出現使 JavaScript 也能用於伺服器端編程。
* nvm:node version management
---
## C# 程式架構
* **老師:戴德仁**
* 時間:2022/3/29
### C# 開發應用
1. window from
2. 控制台
3. web (ASP.NET, MVC) --> 另一門課
### 主要架構
* 入口函數:`Main()`
* 預設類別名稱 class:`Program.cs`
* 命名空間通常放最外層:`namespace`,幫助不同命名空間中有相同函數時可用來分類,類似於資料夾

### 註解
* `// 單行`
* `/* 多行 */`
### Main()

* static 靜態:讓程式在執行時,先在記憶體佔位置
* 程式執行三階段
* coding 編輯
* compile 編譯
* linking 連結:將函式庫、外部程式作連結
* build 成執行檔,一般存於 bin/debug 或 bin/Release 資料夾中
### void
當方法沒有回傳值時
### Read()
```csharp=
console.Read(); // 僅抓取使用者輸入第一個字元
console.ReadLine(); // 抓取多行使用者輸入
```
### 資料型別
#### 強型別
要定義資料類型,偏向不容忍隱性的型別轉換。例如:`java`、`C#`
```java=
int x = 123 + Integer.parseInt("456");
```
#### 弱型別
即便先定義的型別,也可以很直觀的轉換,例如:`php`
```php=
$x = 123 + "456";
echo $x;
```
#### 常見資料型別

* 8`bit` = 1`byte`
### 常數、變數
* 常數`const`:宣告初始值後,內容不可改變
* 變數`var`:內容會改變
* `public`
### 命名規則
* 大小寫有分
* 英文、底線開頭
* 有意義
* 少用中文
* 保留字或關鍵字
* 
### 函式參數引用原則
[Call By Value, Call By Reference?](https://stu98832.github.io/2020/06/26/call-by-reference/)
記憶體中紀錄的是位置(Reference)還是實質型別(Value)?
#### 實值型別與參考型別
> 實值型別傳遞給其他人時是複製實值傳遞,參考型別傳遞給其他人時是複製地址傳遞。
> 實值似影印傳遞,會複製成兩份一模一樣的物件,參考傳遞似網址傳遞,會複製網址分享對方,兩人共同觀看網站同一個物件。
> [From 實值型別與參考型別](https://ithelp.ithome.com.tw/articles/10223905)
### 運算子、運算元
#### 運算元
* 單元運算子,例如:`i++`
* 二元運算子,例如:`i+j`
* 三元運算子,例如:`max=(a>b)?a:b`
#### 運算子
* 算術運算子,例如:`+`、`-`、`*`、`/`、`%`
* 關係運算子,例如:`==`、`!=`、`>`、`<`、`>=`、`<=`
* 邏輯運算子,例如:`&&`、`||`、`!`、`XOR`
* 
* 位元運算子
* 
* 位移運算子,例如:`>>`右移(/2)、`<<`左移(*2)
* 複合指定運算子,例如:`+=`、`-=`等等
##### 優先層級

### String
#### 字串相連
```csharp=
Console.WriteLine("身高是"+"150")
```
#### 字串格式化
```csharp=
stringFormat("身高是{0}", height)
```
#### 字串插值
```csharp=
$"身高是{height}"
```
### 建立方案
* 方案(.sln)
* 專案1(.csproj)
* 專案2(.csproj)
* ...
* 如果沒有載入 System 函式庫,console 需要指名從 System 函式庫
```csharp=
System.Console.writeLine("world");
```
* `white` v.s. `whiteLine`
```csharp=
Console.white("hello, ");
Console.writeLine("world"); //執行完會跳下一行
```

#### Debug
設定中斷點

### 補充:進制轉換
#### 二進制 Binary, bin
* 基數 2,逢 2 進位

#### 八進制 Octal, oct
* 基數 8,逢 8 進位
#### 十進制 Decimal, dec
* 基數 10,逢 10 進位

#### 十六進制 Hexadecimal, hex
* 基數 16,逢 16 進位
* 10(A)、11(B)、12\(C\)、13(D)、14(E)、15(F)
#### 最高有效位元 MSB:最左邊
#### 最低有效位元 LSB:最右邊
---
* **老師:戴德仁**
* 時間:2022/4/1、4/7
* 配合投影片02,版權問題不放
### console 類別常用方法
* `White`
* `WhiteLine`
* `Read`
* `ReadLine`
#### 練習題

```csharp=
using System;
namespace ConsoleEx1
{
class Program
{
static void Main(string[] args)
{
string name;
int price;
Console.Write("請輸入品名:");
name = Console.ReadLine();
Console.Write("請輸入單價:");
price = int.Parse(Console.ReadLine());
Console.WriteLine($"品名:{name} 單價:{price} 記錄儲存成功");
}
}
}
```
### 格式化輸出
從 `Write`、`WriteLine`著手
#### string
```csharp=
{index[,alignment][:formatChar]}
```
* `index` 索引值
* `,alignment` 對齊
* 為正數往右對齊,為負數則往左
* 數字大小決定欄位寬度
* 為0則維持字串原先長度
* `:formatChar` 格式化字元
* C[n]:貨幣[小數點後幾位],預設取小數點後兩位
* 會自動四捨五入


##### 實戰
```csharp=
//.NET string format
Console.WriteLine("12345678901234567890");
Console.WriteLine(string.Format("{0, 0 :C} {1, 0 :c3}\n{2, 15 :c3}\n{3, -15 :c3}", 5, -5, -5, -5));
// 完整寫法
Console.WriteLine("{0, 0 :C} {1, 0 :c3}\n{2, 15 :c3}\n{3, -15 :c3}", 5, -5, -5, -5);
// 字串加值的寫法
Console.WriteLine($"{5,0:c} {-5,0:c3}\n{-5,15:c3}\n{-5,-15:c3}");
```
#### 數值(int, float)
從`ToString`著手
* 0
* 向右對齊
* 空位補0
* \#
* 向左對其
* 空未補空格
```csharp=
double i = 0801234567;
Console.WriteLine(i.ToString("(0##) ###-####"));
// 輸出結果 (080) 123-4567
```


### 預告:隨堂小考
* 紙本考試
* 可看memo,不可以看書
### 跳脫字元
* `\n`:newline
* `\r`:return
* 游標到最前面
* `\t`:tab
* 字首8字元
* 字間5字元
* `@"C:\cs\hw1.cs"`
* 前綴`@`會讓後面字串全部以一般字元輸出,但如果有`""`仍需使用跳脫字元`\"`
### 型別轉換
#### 隱性轉換


* `大=小`才能轉換
#### 明確轉換(強制轉換)
* 利用型態轉換(Type cast)方式強制轉換
* 容易有資料遺失,將8byte轉成4byte會有4btye遺失

### 移位運算元
#### 左移`<<`
> 數學意義:
> 在數字沒有溢出的前提下,對於正數和負數,左移一位都相當於乘以2的1次方,左移n位就相當於乘以2的n次方。
#### 右移`>>`
> 數學意義:
> 右移一位相當於除2,右移n位相當於除以2的n次方。
### XOR(`^`)
兩個條件中有一個條件不成立時,就等於條件成立了
```csharp=
char c1 = '9';
char c2 = '2';
char c3 = '1';
Console.WriteLine($"原編碼訊息:{c1}{c2}{c3}");
int key = 11;
c1 = (char)(c1 ^ key);
c2 = (char)(c2 ^ key);
c3 = (char)(c3 ^ key);
Console.WriteLine($"編碼後訊息:{c1}{c2}{c3}");
c1 = (char)(c1 ^ key);
c2 = (char)(c2 ^ key);
c3 = (char)(c3 ^ key);
Console.WriteLine($"解碼後訊息:{c1}{c2}{c3}");
```
#### 運算(隱性轉換)
1. 先將9(ASCII)轉成57(十進位)再轉成111001(二進位)
2. 將key值11(十進位)轉成1011(二進位)
3. 111001與1011做XOR
* 111001
* 001011
* \-------
* 110010
4. 得到110010(二進位)再轉成2(ASCII)

#### output
```shell=
原編碼訊息:921
編碼後訊息:29:
解碼後訊息:921
```
### 列舉資料型別
#### `enum`
```csharp=
enum 物件{
屬性=值
}
```
### 結構
#### `struct`
```csharp=
struct 物件{
屬性=值
}
```
```csharp=
struct Product
{
public string No, Name;
public int Price;
}
static void Main(string[] args)
{
// 宣告一個自定義物件Product,名叫xbox,則xbox一定會有三個欄位No, Name, Price
Product xbox, ps4;
xbox.No = "TVGame001";
xbox.Name = "Xbox One(含Kinect)";
xbox.Price = 17200;
Console.WriteLine("\n===== 產品單價清單 =====\n");
Console.WriteLine($"產品編號:{xbox.No}");
Console.WriteLine($"產品名稱:{xbox.Name}");
Console.WriteLine($"產品單價:{(int)xbox.Price}");
}
```
---
## C# workflow
* **老師:戴德仁**
* 時間:2022/4/7
* 配合投影片03,版權問題不放
* 預計4/8考試
### 結構化程式設計
1. 循序
2. 選擇性
1. if/else
2. switch
3. 重複性
1. for
2. while
### if/else
* 單選
* 雙選
* 巢狀
### else if
* 多選
```csharp=
if (ans == "4")
{
Console.WriteLine("=== 答對了,真不愧是 .NET 達人....");
}
else if (ans == "1" || ans == "2" || ans == "3")
{
Console.WriteLine("=== 答錯了,正確答案是4.");
}
else
{
Console.WriteLine("=== 無此選項....");
}
```
### switch
* 多選
```csharp=
switch(ans)
{
case "1":
Console.WriteLine("=== 答錯了,正確答案是4.");
break;
case "2":
Console.WriteLine("=== 答錯了,正確答案是4.");
break;
case "3":
Console.WriteLine("=== 答錯了,正確答案是4.");
break;
case "4":
Console.WriteLine("=== 答對了,真不愧是 .NET 達人....");
break;
default:
Console.WriteLine("=== 無此選項....");
break;
}
```
其中`case`輸出內容若相同亦可精簡為:
```csharp=
switch(ans)
{
case "1":
case "2":
case "3":
Console.WriteLine("=== 答錯了,正確答案是4.");
break;
...
}
```
#### 選擇困難:用`if/else`還是`switch`?
> 1. 當分支較多時,當時用switch的效率是很高的。因為switch是隨機訪問的,就是確定了選擇值之後直接跳轉到那個特定的分支
> 但是if/else是遍歷所以得可能值,知道找到符合條件的分支。
> 如此看來,switch的效率確實比ifelse要高的多。
> 2. 由彙編程式碼可知道,switch佔用較多的程式碼空間,因為它要生成跳錶,特別是當case常量分佈範圍很大但實際有效值又比較少的情況,switch的空間利用率將變得很低。
> 3. switch只能處理case為常量的情況,對非常量的情況是無能為力的。例如 if (a > 1 && a < 100),是無法使用switch來處理的。
> 所以,switch只能是在常量選擇分支時比if/else效率高,但是if/else能應用於更多的場合,if/else比較靈活。
### 三元運算子
```csharp=
max = a>b ? a:b;
```
### for
```csharp=
for(初值;條件示;增值){
}
```
* 全域變數:變數存活於程式碼執行到結束
* 區域變數:變數僅存活於特定區塊內
* 例如`for(int i = 0; i <= 9; i++)`中的`i`
### while
```csharp=
while(條件示){
}
```
### do...while
```csharp=
do{
// 至少執行一次才去判斷條件示
}while(條件示);
```
### break
終止程式,例如:印出1~10但3之後不要印
```csharp=
for(...){
if(i==3) break
...
}
```
### continue
結束當下的迴圈,例如:印出1~10但不要印出3
```csharp=
for(...){
if(i==3) continue
...
}
```
### 防呆
限定輸入數字,使用者輸入英文怎麼辦?
#### C#內建
```csharp=
// 原型:Boolean = 預期資料型態.TryParse(輸入, out 變數)
// 轉換成功回傳true及變數
// 轉換失敗回傳false
if(int.TryParse(Console.ReadLine(), out input)) {
}else{
Console.WriteLine("輸入錯誤");
}
```
[實際應用](https://github.com/mitour/web111a_crouse_demo/blob/main/Workflow/While/Program.cs#L14)
#### try/catch
---
* 時間:2022/4/18 下午
* 老師:洪福成(代課)
## C# 練習題
2022/5/24 移至[C# 練習題](/oWxwl7GNTyGNQ9O3n3iUJw)