數學運算符-自加(++)自減(- -)
++不管是放在操作數的前面或後面,都是讓操作數+1
1
2
3
| int num = 8;
num++; //8
++num; //8
|
如果++和- -是放在運算式裡:
++如果放在操作數的後面,會先賦值運算,再自加
1
| int res = num++; //res:8, num:9
|
++如果放在操作數的前面,會先自加,再進行運算賦值
1
| int res = ++num; //res:9, num:9
|
while/ do-while 循環語句
while 會先進行條件判斷,再根據判斷的結果去判定是否執行循環體(執行次數>=0)
1
2
3
4
5
6
| int index = 1;
while (index <= 9)
{
Console.WriteLine(index);
index++;
}
|
do-while 會先執行一次循環體,再進行條件判斷(執行次數>=1)
1
2
3
4
5
6
| int index = 1;
do
{
Console.WriteLine(index);
index++;
} while (index <= 9);
|
循環中斷break(終止當前的循環)
1
2
3
4
5
6
| while (true)
{
Console.WriteLine(index);
if (index == 9) break; //立刻跳出循環
index++;
}
|
練習:接受用戶輸入,並顯示到螢幕上,直到用戶輸入一個0,結束程式。
1
2
3
4
5
6
7
8
| while (true) //死循環
{
string? str = Console.ReadLine(); //接受用戶輸入
if (str == "0")
break; //跳出循環
else
Console.WriteLine(str); //顯示用戶的輸入
}
|
循環中斷continue(只會終止當次的循環)
continue 只會終止當次的循環,繼續下一個循環
1
2
3
4
5
6
7
8
| int index = 0;
while (true)
{
index++;
if (index == 5) continue; //當index==5的時候,使用continue關鍵字,continue後面的代碼就不會去執行(終止當次循環),進行下一個循環
if (index == 10) break; //當index==10的時候,使用break關鍵字,立刻終止循環直接跳出
Console.WriteLine(index); //1,2,3,4,6,7,8,9
}
|
練習:接受用戶輸入的整數,如果用戶的輸入是大於0的偶數,就相加,如果是大於0的奇數就不相加,如果用戶輸入0,就把和輸出並退出程式。
1
2
3
4
5
6
7
8
9
10
| int sum = 0;
while (true)
{
int num = Convert.ToInt32(Console.ReadLine()); //用戶輸入
if (num == 0) break; //輸入0就立刻終止循環
if (num % 2 == 1) continue; //如果是奇數就不相加
sum += num; //求合
}
Console.WriteLine(sum);
Console.ReadKey();
|
循環中斷goto(可以直接跳到某一個位置)
練習: 接受用戶輸入,如果輸入0,就使用goto退出循環
1
2
3
4
5
6
7
8
| while (true)
{
int num = Convert.ToInt32(Console.ReadLine()); //用戶輸入
if (num == 0) goto myLabel; //輸入0,使用goto跳出循環
}
myLabel:
Console.WriteLine("跳出循環了!");
Console.ReadKey();
|
循環中斷return(跳出循環、跳出函式)
練習: 接受用戶輸入,如果輸入0,就使用return跳出循環
(基本上很少 return來跳出循環,它是用來終止方法的)
1
2
3
4
5
6
7
| while (true)
{
int num = Convert.ToInt32(Console.ReadLine());
if (num == 0) return; //用來終止方法的,表示方法運行結束,後面的代碼就不會執行了
}
Console.WriteLine("跳出循環了!");
Console.ReadKey();
|
練習: for循環
練習1:求1~1000之間可以被7整除的數,並計算和輸出每5個的和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| int count = 0; //計數器
int sum = 0; //總合
for (int i = 1; i <= 1000; i++) //1~1000之間的整數
{
if (i % 7 == 0) //可以被7整除
{
count++; //計數器+1
sum += i; //求和
Console.WriteLine($"{i}可以被7整除");
if (count == 5) //計數器==5的時候,輸出和
{
Console.WriteLine($"這5個的和是: {sum}");
count = 0; //計數器歸零
sum = 0; //歸零重新計算
}
}
}
Console.ReadKey();
|
練習2:求1~100的平方、平方根
1
2
3
4
5
6
7
| for (int i = 1; i <= 100; i++)
{
int square = i * i;
double sqrt = Math.Sqrt(i);
Console.WriteLine($"{i}的平方是{square},平方根是{sqrt}");
}
Console.ReadKey();
|
練習3:1~100能被3整除,但不能被5整除的數,並統計有多少這樣的數
1
2
3
4
5
6
7
8
9
10
11
| int count = 0;
for (int i = 1; i <= 100; i++) //1~100
{
if ((i % 3 == 0) && (i % 5 != 0)) //能被3整除,但不能被5整除的數
{
count++;
Console.WriteLine(i);
}
}
Console.WriteLine($"這樣的數總共有{count}個");
Console.ReadKey();
|
練習4:求1~1000的質數
(質數是大於1,且除了1和本身之外,不能被其他自然數整除)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| for (int i = 2; i <= 1000; i++)
{
bool isPrime = true;
for (int j = 2; j <= i - 1; j++) //檢查i是不是質數,有沒有因子,去遍歷所有比i小的所有數,看能不能被整除
{
if (i % j == 0) //可以被整除,就代表有一個因子,就不是質數
{
isPrime = false;
break; //不是質數,就跳出int j 這個迴圈
}
}
if (isPrime) Console.WriteLine(i); //是質數就輸出
}
Console.ReadKey();
|
練習5:99乘法表
1
2
3
4
5
6
7
8
9
| for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
Console.Write($"{i}*{j}={i*j}\t");
}
Console.WriteLine();
}
Console.ReadKey();
|
練習6:編寫一個擲骰子100次的程序,並印出各種點數的出現次數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| int num1 = 0, num2 = 0, num3 = 0, num4 = 0, num5 = 0, num6 = 0;
Random random = new Random();
for (int i = 0; i < 100; i++)
{
int num = random.Next(1, 7); //產生一個1~6的隨機數(random是不包含Max最大數,所以maxVaule是7)
switch (num)
{
case 1:
num1++;
break;
case 2:
num2++;
break;
case 3:
num3++;
break;
case 4:
num4++;
break;
case 5:
num5++;
break;
case 6:
num6++;
break;
}
}
Console.WriteLine($"{num1}\n{num2}\n{num3}\n{num4}\n{num5}\n{num6}");
Console.ReadKey();
|
練習7:1~5平方值(for, while, do-while)
for
1
2
3
4
| for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i * i);
}
|
while
1
2
3
4
5
6
7
| int index = 1;
while (index < 6)
{
Console.WriteLine(index*index);
index++;
}
Console.ReadKey();
|
do-while
1
2
3
4
5
6
7
| int index = 1;
do
{
Console.WriteLine(index * index);
index++;
} while (index < 6);
Console.ReadKey();
|
練習: 循環結構、字串處理
練習1:要求用戶輸入5個大寫字母,如果用戶信息不滿足要求,提示幫助訊息並要求重新輸入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| while (true) //死循環
{
string str = Console.ReadLine()!; //用戶輸入
bool isAllUpper = true;
for (int i = 0; i < 5; i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
//Todo something.
}
else
{
isAllUpper = false; break; //有不是大寫的字母,跳出for迴圈
}
}
if (!isAllUpper)
Console.WriteLine("你輸入的5個字母,不全是大寫,請重新輸入");
else
break; //5個全是大寫字母,跳出while迴圈結束
}
Console.ReadKey();
|
練習2:
- 接受一個整數n
- 如果接收值為正數,輸出1~n之間的全部整數
- 如果接收值為負數,退出程式
- 如果為0,則繼續1.接收下一個整數
1
2
3
4
5
6
7
8
9
10
11
| while (true) //死循環
{
int num = Convert.ToInt32(Console.ReadLine()); //接受用戶輸入
if (num > 0) {
for (int i = 1; i <= num; i++) {
Console.WriteLine(i);
}
} else if (num < 0) {
return;
}
}
|
練習3:列出1~1000的完全數。6=1+2+3
(完數:除了自身以外的因數的和,恰好等於它本身)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| for (int i = 1; i <= 1000; i++)
{
string str = "1";
int sum = 1; //1是所有數的因子
for (int j = 2; j < i; j++) //遍歷所有比它小的數
{
if (i % j == 0) { //取得所有因子
str += $"+ {j}";
sum += j; //計算因子和
}
}
if (sum == i) {
Console.WriteLine($"{i}是完全數: {str}");
}
}
Console.ReadKey();
|
顯式轉換、隱式轉換
- 隱式轉換:編譯器自動識別,不需要我們寫更多的代碼。
- 顯式轉換:需要我們告訴編譯器,什麼類型轉換成什麼類型。
1
2
3
| byte myByte = 123;
int myInt = myByte; //隱式轉換:把小類型的數據複製給大類型的變數,編譯器會自動進行類型的轉換
myByte = (byte)myInt; //顯式轉換:當把大類型賦值給小類型的變數,需要進行顯示轉換(強制類型轉換)
|
隱式轉換
當小盒子放進大盒子的時候,可以自動進行類型轉換。
1
2
| char c = 'a';
float myfloat = c;
|
顯式轉換
當大盒子的數據放進小盒子裡面的時候,有可能小盒子裝不下,所以編譯器不允許直接這麼寫:
1
2
| int i = 123;
short j = i;
|
我們可以通過顯式轉換的方式:
使用Convert命令進行顯式轉換: Convert.ToInt32(val)、Convert.ToDecimal(val)…
列舉類型enum
除了簡單的變數類型之外,C#還提供了三個複雜的變量:列舉enum、結構、數組。
1
2
3
4
5
6
7
8
| //定義列舉
enum GameState: byte //修改該enum的儲存類型,默認為int
{
Pause, //遊戲暫停,默認值是0
Failed, //遊戲失敗,默認值是1
Success, //遊戲成功,默認值是2
Start //開始,默認值是3
}
|
1
2
3
4
| GameState state = GameState.Start; //利用定義好的列舉 去宣告變數
if (state == GameState.Start) {
Console.WriteLine("當前處於遊戲開始狀態");
}
|
結構/結構體Struct
如果我們表示一個向量的話,需要定義三個類型x,y,z:
1
2
3
| float enemy1X = 44;
float enemy1Y = 23;
float enemy1z = 345;
|
這樣比較麻煩,不容易管理,我們可以使用結構struct:
舉例1:表示一個遊戲物體(主角或敵人的坐標),需要三個小數。
1
2
3
4
5
6
| //定義坐標位置的結構體
struct Position {
public float x;
public float y;
public float z;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
| //第一個敵人的位置
Position enemy1Position;
enemy1Position.x = 12;
enemy1Position.y = 33;
enemy1Position.z = 323;
//第二個敵人的位置
Position enemy2Position;
enemy2Position.x = 33;
enemy2Position.y = 99;
enemy2Position.z = 89;
|
舉例2:定義一個表示路徑的結構,路徑有一個方向和距離所組成,假定方向只能是東西南北
//定義方向:東西南北
enum Direction {
East,
West,
South,
North
}
//定義路徑:方向+距離
struct Path {
public float distance; //距離
public Direction dir; //方向
}
//利用結構體去宣告一個變數
Path path1;
path1.dir = Direction.South;
path1.distance = 1000;
Q:什麼時候使用列舉enum呢?
enum用來表示可取的範圍有幾個的時候(有限的範圍),我們可以聲明一個新的類型,增加可讀性。
Q:什麼時候使用結構struct呢?
結構體是幾個類型的一個結合體,它可以當成是幾個類型組合成一個新的類型。
陣列的定義和初始化
陣列初始化的方式
1
2
3
| int[] scores = { 1, 2, 3, 4, 5 }; //隱含型別,直接賦值
int[] scores = new int[] { 1, 2, 3, 4, 5 }; //不指定大小
int[] scores = new int[5] { 1, 2, 3, 4, 5 }; //指定大小
|
分開寫(宣告和初始化分開做),先宣告陣列變數,當要賦值給這變數時,就要加new關鍵字
1
2
3
4
5
| int[] scores; //宣告陣列變數
scores = new int[3]; //初始化
scores = new int[] { 1, 2, 3 }; //不指定長度,並具體表明裡面的元素
scores = new int[3] { 1, 2, 3 }; //指定長度為3
//scores = { 1,2,3 }; //Error,使用這種方式賦值,只能用在宣告陣列變數的時候賦值:int[] arr = {1,2,3}
|
陣列的遍歷for, while, foreach
for
1
2
3
4
| int[] scores = { 71, 52, 83, 45, 77, 99, 60 };
for (int i = 0; i < scores.Length; i++) {
Console.WriteLine(scores[i]);
}
|
while
1
2
3
4
5
6
| int[] scores = { 71, 52, 83, 45, 77, 99, 60 };
int i = 0;
while (i <scores.Length) {
Console.WriteLine(scores[i]);
i++;
}
|
foreach
1
2
3
4
| int[] scores = { 71, 52, 83, 45, 77, 99, 60 };
foreach (int e in scores) {
Console.WriteLine(e);
}
|
字串的處理
遍歷字串中的每一個字元
1
2
3
4
| string str = "www.google.com";
for (int i = 0; i < str.Length; i++) {
Console.WriteLine(str[i]);
}
|
其他:ToLower, ToUpper, Trim, TrimStart, TrimEnd
1
2
3
4
5
6
| string str = " www.google.COM ";
Console.WriteLine(str.ToLower()); //轉小寫
Console.WriteLine(str.ToUpper()); //轉大寫
Console.WriteLine(str.Trim()); //去掉前後空白
Console.WriteLine(str.TrimStart()); //去掉前面空白
Console.WriteLine(str.TrimEnd()); //去掉後面空白
|
Split()按照指定的字符進行拆分
1
2
3
4
5
| string str = "www.google.com";
string[] arr = str.Split('.'); //按照點(.)的字符進行拆分
foreach (var item in arr) {
Console.WriteLine(item);
}
|
練習: 找到100~999的水仙花數
1
2
3
4
5
6
7
8
9
10
11
12
| for (int i = 100; i < 1000; i++)
{
int unitsDigit = i % 10;//個位數
int tensDigits = (i / 10) % 10; //十位數(除以10先把個位數拿掉)
int hundredsDigit = i / 100; //百位數
//求立方和:(個位數3次方)+(十位數3次方)+(百位數3次方)
int res = unitsDigit * unitsDigit * unitsDigit + tensDigits * tensDigits * tensDigits + hundredsDigit * hundredsDigit * hundredsDigit; //取立方(3次方)相加
if (res == i) { //和==自己本身就是水仙花數
Console.WriteLine(i);
}
}
|
練習: 三個可樂瓶可以兌換一個可樂,現在有364瓶可樂,我們總共可以喝多少可樂,還剩餘多少空瓶。
1
2
3
4
5
6
7
8
9
10
11
12
| int sum = 364; //表示現在可以喝多少可樂(現在有364瓶可樂)
int numEmpty = sum; //表示現在有多少空瓶數
while (numEmpty >= 3) //空瓶子>=3的時候才能兌換
{
int newCount = numEmpty / 3; //可以兌換多少新的可樂
sum += newCount; //可以喝的可樂數+兌換的可樂數
int remainEmpty = numEmpty % 3; //剩餘幾個的空瓶沒有兌換
numEmpty = newCount + remainEmpty; //兌換後,還有多少空瓶
}
Console.WriteLine($"我們一共喝了{sum} 瓶可樂,剩餘的空瓶子個數是:{numEmpty}");
Console.ReadKey();
|
練習: 猜數字遊戲
請用戶輸入0~50之間的數字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| Random random = new Random();
int number = random.Next(1, 51); //隨機數0~50
Console.WriteLine("我有一個數字,請猜猜是多少,請輸入0~50之間的數字");
while (true)
{
int temp = Convert.ToInt32(Console.ReadLine()); //接收用戶輸入
if (temp > number) {
Console.WriteLine("您猜大了,比這個數字小");
} else if (temp < number) {
Console.WriteLine("您猜小了,比這個數字大");
} else {
Console.WriteLine($"您猜對了,這個數字為{number},遊戲結束");
break;
}
}
Console.ReadKey();
|
練習: 字母加密
加密規則:大小寫字母向後移動三個位置,不是字母的就不動
ex: a→d,b→e, c→f, y→b, A→D, Z→C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| string str = Console.ReadLine()!; //接收用戶輸入
string tempStr = "";
for (int i = 0; i < str.Length; i++) //遍歷每一個字母
{
if (str[i] >= 'a' && str[i] <= 'z') //說明這個字元是小寫字母
{
int num = Convert.ToInt32(str[i]); //將字元轉換成數字
num += 3;//轉換成數字後+3,相當於向後移動三個字元
char temp = (char)num; //再轉回字元,此為向後移動三個位的字元
if (temp > 'z') { //表示超過範圍
temp = (char)(temp - 'z' + 'a' - 1); //超出26個字母的範圍,就轉換到開頭'a'
}
tempStr += temp;
}
else if (str[i] >= 'A' && str[i] <= 'Z') //說明這個字元是大寫字母
{
int num = Convert.ToInt32(str[i]); //將字元轉換成數字
num += 3;//轉換成數字後+3,相當於向後移動三個字元
char temp = (char)num; //再轉回字元,此為向後移動三個位的字元
if (temp > 'Z') { //表示超過範圍
temp = (char)(temp - 'Z' + 'A' - 1); //超出26個字母的範圍,就轉換到開頭'a'
}
tempStr += temp;
}
else //不是字母的就不動
{
tempStr += str[i];
}
}
Console.WriteLine(tempStr);
Console.ReadKey();
|
練習: Array.Sort方法、冒泡排序
用戶輸入一組數字(用空格間隔),對用戶輸入的數字從小到大排序(Array.Sort方法和冒泡排序)
先將字串轉成int陣列
1
2
3
4
5
6
7
| string str = Console.ReadLine()!; //接收用戶輸入
string[] strArray = str.Split(' '); //空隔分割
int[] numArray = new int[strArray.Length];
for (int i = 0; i < strArray.Length; i++) {
numArray[i] = Convert.ToInt32(strArray[i]);
}
|
使用Array.Sort內置的快速排序(一般用這個就可以了)
1
| Array.Sort(numArray); //使用內置的快速排序
|
使用自己的冒泡排序(Array.Sort會比自已寫的快)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| //使用自己的冒泡排序
for (int j = 1; j <= str.Length-1; j++) //外層for循環,用來控制內層for循環的次數
{
for (int i = 0; i < numArray.Length - 1 -j+1; i++)
{
//numArray[i] numArray[i+1]做比較,大的放後面
if (numArray[i + 1] < numArray[i])
{
int temp = numArray[i];
numArray[i] = numArray[i + 1];
numArray[i + 1] = temp;
}
}
}
//輸出排序結果
for (int i = 0; i < numArray.Length; i++) {
Console.Write($"{numArray[i]} ");
}
Console.ReadKey();
|
內循環for的優化 -j+1,執行會更快
1
| for (int i = 0; i < numArray.Length-1-j+1; i++)
|
為什麼要-j+1呢?隨著外循環的增加,內循環的次數是要減少的。 -j+1的優化,首先我們第一次做循環的時候,最大值已經放到最後一個索引值的位置了,第二次做循環的時候,就不需要再跟最後一個位置做比較,所以當第一次執行for循環的時候,內循環是要執行Length-1次,當第二次執行的時候,裡面只要執行Length-2次就可以了,所以隨著j的增加,裡面的執行的次數是要減少的。
- j=1, 內循環 -1+1,不影響。
- j=2, 內循環 -2+1,相當於-1,比第一次減1了,就少執行一次,這一次相當於因為上一次循環已經把最大值排在最後面了,所以這一次我們就不需要跟最後一個值做比較了。
練習: 猴子吃桃
猴子吃桃問題:猴子第一天摘下若干個桃子,當即吃了一半,還不癮,又多吃了一個, 第二天早上又將剩下的桃子吃掉一半,又多吃了一個。以後每天早上都吃了前一天剩下的一半零一個。到第n天早上想再吃時,只剩下一個桃子了。求第一天共摘了多少。
1
2
3
4
5
6
7
8
| //桃子減少公式:(n/2)-1=n
//桃子增加公式:(n+1)*2=n
int n = Convert.ToInt32(Console.ReadLine());
int count = 1; //剩下的桃子
for (int i = n-1; i >= 1; i--) { //使用負循環,往前走,走到第一天
count = (count + 1) * 2;
}
Console.WriteLine($"第一天摘了{count}個桃子");
|
練習: 找出最小值,與索引為0的位置交換
輸入n個數,找出最小數,將它與最前面的數交換後,輸出這些數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| //先將字串轉成整數
string str = Console.ReadLine()!;
string[] strArray = str.Split(' '); //分割字串
int[] numArray = new int[strArray.Length];
for (int i = 0; i < strArray.Length; i++) {
numArray[i] = Convert.ToInt32(strArray[i]);
}
//找出最小數
int min = numArray[0];//最小數
int minIndex = 0;//記錄最小數的索引
for (int i = 1; i < numArray.Length; i++)
{
if (numArray[i] < min) {
minIndex = i;
min = numArray[i];
}
}
//最小值與第一個數(索引為0的位置)交換
int temp = numArray[0];
numArray[0] = min;
numArray[minIndex] = temp;
//輸出
for (int i = 0; i < numArray.Length; i++) {
Console.Write($"{numArray[i]} ");
}
Console.ReadKey();
|
練習: 將一整數插入到已經從小到大排序好的序列中,其新的序列仍然有序
有n個整數,已經從小到大排序好,現在另外給新的整數x,請將該數插入序列中,並使新的序列仍然有序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| int[] numArray = { 1, 2, 4, 5, 6, 9, 66 };
int num = Convert.ToInt32(Console.ReadLine());
int[] newNum = new int[numArray.Length + 1];
int index = 0; //臨時索引
bool isInsert = false; //被插入
for (int i = 0; i < newNum.Length; i++)
{
//表示最大值且還沒被插入
if (i == numArray.Length && isInsert == false) {
newNum[i] = num; //插入
isInsert = true;
break;
}
if (num <= numArray[index] && isInsert == false)
{
newNum[i] = num; //插入
isInsert = true;
}
else
{
newNum[i] = numArray[index];
index++;
}
}
for (int i = 0; i < newNum.Length; i++) {
Console.Write($"{newNum[i]} ");
}
Console.ReadKey();
|
練習: 計算發工資要準備多少鈔票及硬幣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| int num = Convert.ToInt32(Console.ReadLine()); //輸入工資
int count1000 = num / 1000; //一千的
int remain = num % 1000; //剩餘的錢
int count500 = remain / 500;
remain = remain % 500;
int count100 = remain / 100;
remain = remain % 100;
int count50 = remain / 50;
remain = remain % 50;
int count10 = remain / 10;
remain = remain % 10;
int count5 = remain / 5;
remain = remain % 5;
Console.WriteLine($"1000準備{count1000}");
Console.WriteLine($"500準備{count500}");
Console.WriteLine($"100準備{count100}");
Console.WriteLine($"50準備{count50}");
Console.WriteLine($"10準備{count10}");
Console.WriteLine($"5準備{count5}");
Console.WriteLine($"1準備{remain}");
Console.ReadKey();
|
練習: 字串校驗: C#合法標識符
- 字首:允許a-z,A-Z,_,@,不允許0-9
- 後續字符:允許a-z,A-Z,,0-9,不允許@
```c# string str = Console.ReadLine()!; bool isRight = true; //字首:表示合法的大小寫字母、_底線、@符號 if ((str[0] >= ‘a’ && str[0] <= ‘z’) || (str[0] >= ‘A’ && str[0] <= ‘Z’ || str[0] == ‘’ || str[0] == ‘@’)) {
} else { isRight = false; } //後續字符:允許a-z,A-Z,,0-9 for (int i = 0; i < str.Length; i++) { `if ((str[i] >= ‘a’ && str[i] <= ‘z’) || (str[i] >= ‘A’ && str[i] <= ‘Z’) || (str[i] >= ‘0’ && str[i] <= ‘9’) || str[i] == ‘’) {
1
2
3
| } else {
isRight = false;
} }
|
if(isRight==false) Console.WriteLine(“不是合法的標識符”); else Console.WriteLine(“是合法的標識符”); Console.ReadKey();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
## 練習: 判斷字串是否"回文串"
"回文串"是一個正讀和反讀都一樣的字符串,比如 level 或者 noon 等等就是回文串。
```c#
string str = Console.ReadLine()!;
bool isPalindrome = true;
for (int i = 0; i < str.Length/2; i++) //從一半開始
{
//i str.length-1-i 當前索引對應的另一個索引
if (str[i] != str[str.Length - 1 - i]) {
isPalindrome = false; break; //不是回文串,跳出迴圈
}
}
if (isPalindrome) {
Console.WriteLine("是回文串");
} else {
Console.WriteLine("不是回文串");
}
Console.ReadKey();
|
練習: 設定安全密碼
1.長度>=8,不超過16 2.密碼字符應符合下面四組中的至少三組
- 大寫字母: A-Z
- 小寫字母: a-z
- 數字: 0-9
- 特殊符號:~!@#$%^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| string str = Console.ReadLine()!;
if (str.Length >= 8 && str.Length <= 16) {
bool isUpper = false;
bool isLower = false;
bool isHaveNumber = false;
bool isHaveSpacial = false;
for (int i = 0; i < str.Length; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') isUpper = true;
if (str[i] >= 'a' && str[i] <= 'z') isLower = true;
if (str[i] >= '0' && str[i] <= '9') isHaveNumber = true;
if (str[i] == '~' || str[i] == '!' || str[i] == '@' || str[i] == '#' ||
str[i] == '$' || str[i] == '%' || str[i] == '^') isHaveSpacial = true;
}
int count = 0;
if (isUpper) count++;
if (isLower) count++;
if (isHaveNumber) count++;
if (isHaveSpacial) count++;
if (count >= 3) {
Console.WriteLine("這是安全密碼");
} else {
Console.WriteLine("這密碼不安全");
}
} else {
Console.WriteLine("這密碼不安全,密碼長度不符合規則");
}
Console.ReadKey();
|
函數的定義與使用
為什麼使用函數呢?
- 如果想要重複執行某段代碼,就需要寫重複的代碼。
- 目前我們寫的代碼,寫多了,結構非常混亂,不容易閱讀。
所以函數來了,函數也叫做方法.
定義函數(定義方法)
1
2
3
| void Write() {
//Todo
}
|
使用函數(調用方法)
函數定義的時候,參數叫形式參數(形參)
1
2
3
4
5
| //num1,num2在這裡就是形參
static int Plus(int num1, int num2) {
int sum = num1 + num2;
return sum;
}
|
當調用函數的時候,這裡傳遞的參數叫實際參數(實參)
實參的值會傳遞給形參做運算
1
2
3
4
5
6
7
| int num1 = 2;
int num2 = 3;
int res1 = Plus(num1, num2); //num1,num2叫實際參數(實參)
int res2 = Plus(1, 2);
Console.WriteLine(res1);
Console.WriteLine(res2);
Console.ReadKey();
|
練習: 輸入一個數,找出該數字所有的因數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| int number = Convert.ToInt32(Console.ReadLine()); //接收用戶輸入
int[] array = GetDivisor(number); //調用方法,找出該數字所有的因數
foreach (int temp in array) { //印出所有的因數
Console.Write($"{temp} ");
}
Console.ReadKey();
//找出該數字所有的因數
static int[] GetDivisor(int number) {
int count = 0; //記錄因子的個數
for (int i = 1; i <= number; i++) { //計算因子的個數
if (number % i == 0) count++;
}
//找出因子,並放入陣列中
int[] array = new int[count]; //存放因子的陣列
int index = 0; //記錄陣列的索引值
for (int i = 1; i <= number; i++) {
if (number % i == 0) { //表示因子
array[index] = i; //因子放入陣列
index++; //索引+1
}
}
return array;
}
|
練習: 從一組陣列中找到最大值
定義一個函數,用來取得一個數組中的最大值
1
2
3
4
5
6
7
8
9
10
11
| int[] array = { 324, 6546, 687, 9, 234, 46, 95276 };
Console.WriteLine(Max(array));
Console.ReadKey();
static int Max(int[] array) {
int max = array[0]; //從索引0第一個值開始做比較
for (int i = 1; i < array.Length; i++) { //i=1開始跟max做比較
if (array[i] > max) max = array[i]; //依次跟max做比較
}
return max;
}
|
參數數組params
參數數組params 與數組參數的不同,在於函數的調用:
- 參數數組params,可以傳遞任意多個參數,編譯器會自動幫我們自動組成一個數組。
- 參數數組params,可以幫我們減少了一個創建數組的過程。
1
| int sum2 = Plus(1, 2, 3, 4, 5); //編譯器會自動這些參數構造成一個數組
|
參數如果是數組參數,這個數組我們要自己手動去創建。
1
| int sum1 = Sum(new int[] { 1, 2, 3, 4, 5 }); //需要自己構造一個數組
|
範例: 定義一個函數,用來取得數字的和,但是數字的個數不確定
解決方法:
- 定義一個函數,參數傳遞過來一個數組。
- 定義一個參數個數不確定的函式,這時候我們就要使用參數數組params。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| int sum1 = Sum(new int[] {1, 2, 3, 4, 5 }); //需要自己構造一個數組
Console.WriteLine(sum1);
int sum2 = Plus(1, 2, 3, 4, 5); //編譯器會自動把這些參數構造成一個數組
Console.WriteLine(sum2);
Console.ReadKey();
//方法1:數組參數
static int Sum(int[] array) {
int sum = 0;
for (int i = 0; i < array.Length; i++) {
sum += array[i];
}
return sum;
}
//方法2:參數數組params
//加上params,調用方法時,我們可以傳遞任意多個參數,編譯器會幫我們自動組成一個數組
static int Plus(params int[] array) {
int sum = 0;
for (int i = 0; i < array.Length; i++) {
sum += array[i];
}
return sum;
}
|
結構函數的定義和使用
1
2
3
4
5
6
7
8
9
10
11
12
| struct CustomerName {
public string firstName;
public string lastName;
public string GetName() { //定義結構函數
return $"My name is {firstName} {lastName}";
}
}
CustomerName myName;
myName.firstName = "Rii";
myName.lastName = "La";
Console.WriteLine(myName.GetName()); //使用結構函數
|
練習: 結構函數
定義一個Vector3的類(這個類可以表示坐標、向量),在裡面定義Distance方法,用來取得一個向量的長度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| Vector3 myVector3;
myVector3.x = 3;
myVector3.y = 3;
myVector3.z = 3;
Console.WriteLine(myVector3.Distance());
Console.ReadKey();
struct Vector3 {
//向量x,y,z
public float x;
public float y;
public float z;
//向量的長度
public double Distance() {
return Math.Sqrt(x * x + y * y + z * z);
}
}
|
函數的重載Overload
函數名相同,參數不同,這個叫做函數的重載(編譯器通過不同的參數去識別應該調用哪一個函式)
假如我們有一個函數用來實現求得一個數組的最大值
1
| static int MaxValue(params int[] array) { ... } //處理int類型
|
上面這個函數只能用於處理int類型,如果想要處理double類型的話,就要再定義一個函數,如下:
1
| static double MaxValue(params double[] array) { ... } //處理double類型
|
範例:定義兩個名為MaxValue的函式,分別用來處理int和double類型
1
2
3
4
5
6
7
8
9
10
11
| static int MaxValue(params int[] array)
{
Console.WriteLine("int類型的MaxValue被調用");
int maxValue = array[0]; //默認第一個值為最大值
for (int i = 1; i < array.Length; i++) { //從第二個值開始依序與max做比較
if (array[i] > maxValue) {
maxValue = array[i];
}
}
return maxValue;
}
|
1
2
3
4
5
6
7
8
9
10
11
| static double MaxValue(params double[] array)
{
Console.WriteLine("double類型的MaxValue被調用");
double maxValue = array[0]; //默認第一個值為最大值
for (int i = 1; i < array.Length; i++) { //從第二個值開始依序與max做比較
if (array[i] > maxValue) {
maxValue = array[i];
}
}
return maxValue;
}
|
調用函式:編譯器會依據你傳遞過來的實參的類型去判定調用哪一個函數
1
2
3
4
5
| int res1 = MaxValue(23, 4, 76, 8, 9); //編譯器會依據你傳遞過來的實參的類型去判定調用哪一個函數
double res2 = MaxValue(33.4, 76.22, 457.99);
Console.WriteLine(res1);
Console.WriteLine(res2);
Console.ReadKey();
|
委託(delegate)的定義
委託相當於聲明一個函數(指向一個函數),指定了一個返回類型和參數列表
可以利用委託聲明的變量,去指向一個函數。
可以通過委託去宣告一個變數,這個變數它可以儲存一個函數(方法),就是它可以指向一個函數。
目前我們定義的這些變數,都是儲存數據的:字串、整數、小數、數組…
委託的使用分兩步:
- 定義
- 聲明(宣告變數) 結構體struct, 列舉enum同上使用,都分為定義和聲明
整數、數組、字串類型,都是直接聲明變量的,因為類型的定義已經完成了(CLR中已經完成定義)
舉例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| //定義delegate
//定義一個委託跟函數差不多,區別在於
//1.定義委託需要加上delegate關鍵字
//2.委託的定義不需要函數體
public delegate double MyDelegate(double param1, double param2);
class Program {
static double Multiply(double param1, double param2) {
return param1 * param2;
}
static double Divide(double param1, double param2) {
return param1 / param2;
}
static void Main(int[] args) {
MyDelegate de; //利用我們定義的委託類型聲明一個新的變量
de = Multiply; //將de指向乘法函數。當我們給一個委託的變量賦值的時候,返回值與參數列表必須一樣,否則無法賦值
Console.WriteLine(de(34.23, 66.99));
de = Divide;
Console.WriteLine(de(10.4,2.2));
Console.ReadKey();
}
}
|
練習: 函數的遞迴調用
一個函數調用它自身的時候,就叫做函數的遞迴調用。
函數調用自身,叫做遞迴調用
f(n)=f(n-1)+f(n-2), f(0)=2, f(1)=3, 求得f(40)
1
2
3
4
5
| static int F(int n) {
if (n == 0) return 2; //這兩個是函數終止遞迴的條件
if (n == 1) return 3;
return F(n - 1) + F(n - 2); //函數調用自身,叫做遞迴調用
}
|
1
2
3
4
5
| int res = F(40);
Console.WriteLine(res);
int res2 = F(2);
Console.WriteLine(res2);
Console.ReadKey();
|
練習: 自由落體反彈距離與高度
一球從100米高度自由落下,每落地後反跳回原高度的一半,再落下,求它第10次落地時,共經過多少米?第10次反彈多高?
1
2
3
4
5
6
7
8
9
| float height = 100; //目前高度
float distance = 0; //距離
for (int i = 0; i < 10; i++)
{
distance += height;
height /= 2; //每落地後反跳回原高度的一半
}
Console.WriteLine($"經過了{distance}米,第10次反彈{height/2}米");
Console.ReadKey();
|
練習: 求1+2!+3!…+20!的和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| //計算階乘
static int Factorial(int n) {
int res = 1;
for (int i = 1; i <= n; i++) {
res *= i; //n=3, 1*2*3
}
return res;
}
//1~20階乘的和
int sum = 0;
for (int i = 1; i <= 20; i++) {
sum += Factorial(i);
}
Console.WriteLine(sum);
Console.ReadKey();
|
練習: 利用遞迴求5!
公式:f(n) = n*f(n-1)
1
2
3
4
5
6
| static int Factorial(int n) {
if (n == 1) return 1; //終止遞迴的條件
return n * Factorial(n - 1); //f(n) = n*f(n-1)
}
Console.WriteLine(Factorial(5));
Console.ReadKey();
|
練習: 結構體struct
編寫一個程序,定義結構類型(有學號、姓名、性別、成績),聲明結構類型變量,用賦值語句對變量賦值後輸出。
1
2
3
4
5
6
7
8
9
10
| struct Student {
public string number;
public string name;
public bool isGirl;
public int score;
public void Show() {
Console.WriteLine($"學號:{number}、姓名:{name}、性別:{(isGirl?"女":"男")}、成績:{score}");
}
}
|
1
2
3
4
5
6
7
| Student stu;
stu.number = "1002";
stu.name = "Rii";
stu.isGirl = true;
stu.score = 99;
stu.Show();
Console.ReadKey();
|
練習: 四捨五入
編寫一個程序,輸入一個正數,對該數進行四捨五入到個位數
1
2
3
4
5
6
7
8
| double number = Convert.ToDouble(Console.ReadLine());
int numberInteger = (int)number / 1; //取得整數部分
double numberDouble = number - numberInteger; //取得小數部分
if (numberDouble >= 0.5f) {
numberInteger++;
}
Console.WriteLine(numberInteger);
Console.ReadKey();
|
更簡單的做法: 直接加上0.5後,轉成整數,相當於把小數部分自動略掉
1
| int res = (int)(number + 0.5f); //直接加上0.5,轉成整數,會自動略掉小數
|