🎯 學習目標
3.1 一維數組的詳細操作
3.1.1 數組聲明和初始化的多種方式
// 方式1:先聲明後初始化
int[] numbers1;
numbers1 = new int[5]; // 創建包含5個元素的數組,默認值為0
// 方式2:聲明並初始化大小
int[] numbers2 = new int[3]; // 3個元素,都是0
// 方式3:聲明並直接賦值
int[] numbers3 = new int[] { 1, 2, 3, 4, 5 };
// 方式4:簡化語法(最常用)
int[] numbers4 = { 10, 20, 30, 40, 50 };
// 方式5:使用var關鍵字
var numbers5 = new[] { 1, 2, 3 }; // 編譯器推斷類型
3.1.2 數組內存結構示意圖
3.1.3 數組的遍歷方法
string[] fruits = { "蘋果", "香蕉", "橙子", "葡萄", "芒果" };
// 方法1:for循環(可以控制索引)
Console.WriteLine("使用for循環遍歷:");
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine($"索引 {i}: {fruits[i]}");
}
// 方法2:foreach循環(更簡潔,只讀)
Console.WriteLine("\n使用foreach循環遍歷:");
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
3.1.4 遍歷方法性能對比
|
方法
|
控制索引
|
修改元素
|
性能
|
使用場景
|
|
for循環
|
✅
|
✅
|
高
|
需要索引操作
|
|
foreach
|
❌
|
❌
|
中
|
簡單遍歷
|
|
GetEnumerator
|
❌
|
❌
|
低
|
特殊需求
|
3.1.5 數組的常用操作
// 創建測試數組
int[] scores = { 85, 92, 78, 96, 88, 90 };
// 1. 訪問和修改元素
scores[0] = 87; // 修改第一個元素
Console.WriteLine($"第一個分數: {scores[0]}");
Console.WriteLine($"最後一個分數: {scores[scores.Length - 1]}");
// 2. 數組排序
Array.Sort(scores);
Console.WriteLine("\n排序後的分數:");
foreach (int score in scores)
Console.Write(score + " ");
// 3. 數組反轉
Array.Reverse(scores);
Console.WriteLine("\n反轉後的分數:");
foreach (int score in scores)
Console.Write(score + " ");
3.1.6 數組操作效果圖
3.2 多維數組
3.2.1 二維數組(表格結構)
// 聲明和初始化二維數組
int[,] matrix = new int[3, 3]; // 3行3列
// 初始化二維數組
int[,] matrix2 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
3.2.2 二維數組結構圖
3.2.3 訪問和遍歷二維數組
// 訪問二維數組元素
matrix[0, 0] = 10; // 第一行第一列
matrix[1, 2] = 20; // 第二行第三列
// 遍歷二維數組
Console.WriteLine("二維數組內容:");
for (int row = 0; row < matrix2.GetLength(0); row++) // GetLength(0)獲取行數
{
for (int col = 0; col < matrix2.GetLength(1); col++) // GetLength(1)獲取列數
{
Console.Write(matrix2[row, col] + "\t");
}
Console.WriteLine();
}
3.2.4 鋸齒數組(數組的數組)
// 聲明鋸齒數組
int[][] jaggedArray = new int[3][];
// 初始化每個子數組(長度可以不同)
jaggedArray[0] = new int[] { 1, 2, 3 };
jaggedArray[1] = new int[] { 4, 5 };
jaggedArray[2] = new int[] { 6, 7, 8, 9 };
3.2.5 鋸齒數組結構圖
索引0: [1] [2] [3]
索引1: [4] [5]
索引2: [6] [7] [8] [9]
3.2.6 多維數組 vs 鋸齒數組
|
特性
|
多維數組
|
鋸齒數組
|
|
內存佈局
|
連續
|
不連續
|
|
每行大小
|
固定
|
可變
|
|
性能
|
更好
|
稍差
|
|
靈活性
|
低
|
高
|
3.3 實際應用:學生成績表
// 使用二維數組存儲多個學生的多科成績
int[,] studentScores = {
{85, 92, 78}, // 學生1的語文、數學、英語成績
{76, 88, 95}, // 學生2
{90, 87, 84}, // 學生3
{82, 79, 91} // 學生4
};
string[] subjects = { "語文", "數學", "英語" };
3.4 字符串操作
3.4.1 字符串的不可變性
string str1 = "Hello";
string str2 = str1; // str2和str1引用同一個字符串
Console.WriteLine($"str1: {str1}"); // Hello
Console.WriteLine($"str2: {str2}"); // Hello
// 修改str1
str1 = str1 + " World"; // 創建新的字符串對象
Console.WriteLine($"修改後str1: {str1}"); // Hello World
Console.WriteLine($"str2: {str2}"); // Hello (保持不變)
3.4.2 字符串不可變性示意圖
初始狀態:
str1 → "Hello" ← str2
修改後:
str1 → "Hello World"
str2 → "Hello"
3.4.3 重要概念對比
|
特性
|
普通字符串
|
StringBuilder
|
|
可變性
|
不可變
|
可變
|
|
線程安全
|
✅
|
❌
|
|
性能(大量修改)
|
差
|
優
|
|
內存使用
|
高
|
低
|
3.5 字符串常用方法
3.5.1 長度和空值檢查
string text = "C# Programming";
// 基本屬性
Console.WriteLine($"字符串: {text}");
Console.WriteLine($"長度: {text.Length}");
Console.WriteLine($"是否為空: {string.IsNullOrEmpty(text)}");
Console.WriteLine($"是否為空白: {string.IsNullOrWhiteSpace(text)}");
3.5.2 字符串檢查方法統計
3.5.3 子字符串操作
string sentence = "The quick brown fox jumps over the lazy dog";
// Substring - 提取子字符串
string part1 = sentence.Substring(4); // 從索引4開始到結尾
string part2 = sentence.Substring(4, 5); // 從索引4開始,取5個字符
Console.WriteLine($"原句: {sentence}");
Console.WriteLine($"從索引4開始: {part1}");
Console.WriteLine($"從索引4取5個字符: {part2}");
3.5.4 查找和定位
string text = "Hello World, Welcome to C# Programming";
// 查找方法
int index1 = text.IndexOf('W'); // 查找字符第一次出現的位置
int index2 = text.IndexOf("World"); // 查找子字符串
int index3 = text.LastIndexOf('o'); // 從後往前查找
Console.WriteLine($"'W'的位置: {index1}");
Console.WriteLine($"\"World\"的位置: {index2}");
Console.WriteLine($"最後一個'o'的位置: {index3}");
3.5.5 字符串查找性能對比
|
方法
|
方向
|
返回值
|
性能
|
|
IndexOf
|
前→後
|
第一個匹配索引
|
O(n)
|
|
LastIndexOf
|
後→前
|
最後一個匹配索引
|
O(n)
|
|
Contains
|
前→後
|
bool
|
O(n)
|
3.5.6 修改和轉換
string original = " Hello C# World ";
// 去除空格
string trimmed = original.Trim(); // 去除兩端空格
// 大小寫轉換
string upper = original.ToUpper(); // 全大寫
string lower = original.ToLower(); // 全小寫
// 替換操作
string replaced = original.Replace("C#", "CSharp");
3.5.7 字符串轉換流程圖
3.5.8 分割和連接
// 分割字符串
string data = "John,25,Developer,New York";
string[] parts = data.Split(',');
Console.WriteLine("分割結果:");
foreach (string part in parts)
{
Console.WriteLine(part);
}
// 連接字符串數組
string[] words = { "Hello", "C#", "World" };
string joined1 = string.Join(" ", words); // 用空格連接
3.5.9 字符串格式化
string name = "張三";
int age = 25;
double salary = 7500.50;
// 方法1:字符串插值(推薦)
string message1 = $"姓名: {name}, 年齡: {age}, 薪資: {salary:C}";
// 數字格式化
double number = 1234.5678;
Console.WriteLine($"默認: {number}");
Console.WriteLine($"貨幣: {number:C}");
Console.WriteLine($"小數兩位: {number:F2}");
3.5.10 格式化方法使用統計
|
方法
|
可讀性
|
性能
|
推薦度
|
|
字符串插值($")
|
⭐⭐⭐⭐⭐
|
⭐⭐⭐⭐
|
⭐⭐⭐⭐⭐
|
|
string.Format
|
⭐⭐⭐⭐
|
⭐⭐⭐⭐
|
⭐⭐⭐⭐
|
|
字符串拼接
|
⭐⭐
|
⭐⭐
|
⭐⭐
|
3.6 StringBuilder 類
3.6.1 為什麼需要StringBuilder?
using System.Text;
// 性能測試對比
DateTime start1 = DateTime.Now;
string result1 = "";
for (int i = 0; i < 10000; i++)
{
result1 += i.ToString(); // 每次拼接都創建新字符串對象
}
DateTime end1 = DateTime.Now;
DateTime start2 = DateTime.Now;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.Append(i.ToString()); // 在同一個對象上操作
}
string result2 = sb.ToString();
DateTime end2 = DateTime.Now;
3.6.2 性能對比圖表
普通字符串拼接:
操作次數: 10000
耗時: 150ms
內存分配: 10000+ 個對象
StringBuilder:
操作次數: 10000
耗時: 5ms
內存分配: 1 個主要對象
3.6.3 StringBuilder的常用方法
StringBuilder sb = new StringBuilder();
// 1. Append - 追加內容
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");
// 2. AppendLine - 追加內容並換行
sb.AppendLine();
sb.AppendLine("這是新的一行");
// 3. AppendFormat - 格式化追加
sb.AppendFormat("當前時間: {0:yyyy-MM-dd}", DateTime.Now);
3.6.4 StringBuilder方法使用頻率
3.7 實際應用場景
3.7.1 場景1:構建動態SQL查詢
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append("SELECT * FROM Users WHERE 1=1");
string nameFilter = "John";
int minAge = 18;
if (!string.IsNullOrEmpty(nameFilter))
{
sqlBuilder.Append(" AND Name = '").Append(nameFilter).Append("'");
}
if (minAge > 0)
{
sqlBuilder.Append(" AND Age >= ").Append(minAge);
}
string finalSql = sqlBuilder.ToString();
3.7.2 場景2:生成HTML內容
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.AppendLine("<!DOCTYPE html>");
htmlBuilder.AppendLine("<html>");
htmlBuilder.AppendLine("<head>");
htmlBuilder.AppendLine(" <title>用户列表</title>");
htmlBuilder.AppendLine("</head>");
string[] users = { "Alice", "Bob", "Charlie" };
foreach (string user in users)
{
htmlBuilder.AppendLine($" <li>{user}</li>");
}
3.8 學習路徑總結
3.8.1 技能掌握程度評估
|
技能點
|
初學者
|
進階
|
精通
|
|
數組聲明初始化
|
✅
|
✅
|
✅
|
|
數組遍歷
|
✅
|
✅
|
✅
|
|
多維數組
|
✅
|
✅
|
✅
|
|
字符串基本操作
|
✅
|
✅
|
✅
|
|
字符串不可變性
|
❌
|
✅
|
✅
|
|
StringBuilder
|
❌
|
✅
|
✅
|
|
性能優化
|
❌
|
❌
|
✅
|
🎉 恭喜! 你已經完成了數組和字符串的深入學習。接下來通過實踐練習來鞏固這些知識吧!
3.9 動手練習
3.9.1 練習1:數組排序和統計
1.將原始數組45 78 23 91 34 67 82 15 56 89 72 39 64 97 28 51 76 43 88 61進行正序排序。
2.統計總和、平均值、最大值、最小值 3.統計0-20、21-40、41-60、61-80、81-100的人數
提示
- 使用
Random類生成隨機數 Array.Sort()可以快速排序數組- 遍歷數組時注意邊界條件
輸出預期結果
3.9.2 練習2:字符串處理工具
輸出原始文本' Hello, this is a Sample Text for Processing! ' 1.將原始文本反轉。 2.單詞計數
3.去除原始文本多餘空格。
4.將文本首字母大寫 5.統計字母在文本中出現的頻率
額外功能測試:
原始字符為C# programming is FUN! 1.字符串長度
2.是否包含'pro' 3.將字符串中的FUN替換為awesome 4.查找'is'的位置。
提示
- 字符串是不可變的,所有修改操作都會返回新字符串
- 使用
Split()方法分割字符串時注意空條目 ToUpper()和ToLower()用於大小寫轉換
預期輸出結果
3.9.3 練習3:學生成績管理系統增強版
1.兩個數組,學生和科目,為下面數組隨機生成成績報告單
// 使用二維數組和字符串操作構建完整的學生成績管理系統
string[] studentNames = { "張三", "李四", "王五", "趙六" };
string[] subjects = { "語文", "數學", "英語", "物理", "化學" };
2.統計每個學生的平均分和等級
if (average >= 90) return "優秀";
else if (average >= 80) return "良好";
else if (average >= 70) return "中等";
else if (average >= 60) return "及格";
else return "不及格";
3.輸入一個學生學生姓名,查詢學生成績單 4.各科平均分統計 5.成績等級分佈
提示
- 二維數組使用
GetLength(0)和GetLength(1)獲取維度 - 字符串格式化使用
PadRight()對齊輸出 - 合理使用方法分解複雜邏輯
預期輸出
🎉 加油!完成所有練習後,你將熟練掌握C#數組和字符串操作!
附錄
所有示例代碼,均已上傳網盤,請自行點擊下方獲取
- 數組深入理解與字符串操作
- 數組深入理解與字符串操作
微信公眾號【.NET修仙日記】