☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
C# 基礎 初學

📄 字串處理與正規表達式

📌 為什麼字串處理這麼重要?

字串就像日常生活中的語言——幾乎所有程式都需要處理文字。不論是讀取使用者輸入、處理檔案內容、還是組合 API 回應,字串無所不在。

想像你經營一家郵局

  • 字串方法就像基本的信件處理工具(拆信、蓋章、裁剪)
  • 正規表達式就像進階的地址辨識系統(自動驗證地址格式是否正確)

📝 常用字串方法

Contains、Replace、Split、Trim

// 準備一個測試字串
string message = "  Hello, World! Welcome to C#.  ";

// Trim:去除前後空白(像把信封邊緣多餘的紙裁掉)
string trimmed = message.Trim(); // "Hello, World! Welcome to C#."

// Contains:檢查是否包含某段文字(像在信裡找關鍵字)
bool hasWorld = trimmed.Contains("World"); // true

// Replace:取代文字(像用修正帶把錯字蓋掉再寫上新字)
string replaced = trimmed.Replace("World", "C# 開發者"); // "Hello, C# 開發者! Welcome to C#."

// Split:用指定字元切割字串(像把一長串珍珠項鍊拆成一顆顆珍珠)
string csv = "蘋果,香蕉,橘子,葡萄";
string[] fruits = csv.Split(','); // ["蘋果", "香蕉", "橘子", "葡萄"]

// 走訪切割後的每個元素
foreach (string fruit in fruits) // 逐一取出每顆水果
{
    Console.WriteLine(fruit); // 印出水果名稱
}

Substring 與索引

// 準備一個字串
string text = "Hello, C# World";

// Substring:擷取子字串(像從書中撕下某幾頁)
string sub1 = text.Substring(7);     // "C# World"(從索引 7 開始到結尾)
string sub2 = text.Substring(7, 2);  // "C#"(從索引 7 開始取 2 個字元)

// IndexOf:找出某段文字第一次出現的位置(像在書裡找某個詞在第幾頁)
int pos = text.IndexOf("C#");       // 7

// ToUpper / ToLower:大小寫轉換(像把小寫印章換成大寫印章)
string upper = text.ToUpper();       // "HELLO, C# WORLD"
string lower = text.ToLower();       // "hello, c# world"

// StartsWith / EndsWith:檢查開頭或結尾(像看信封上的郵遞區號)
bool startsH = text.StartsWith("Hello"); // true(是否以 Hello 開頭)
bool endsW = text.EndsWith("World");     // true(是否以 World 結尾)

🔗 字串插值 vs String.Format

// 基本資料
string name = "小明"; // 姓名
int age = 25;          // 年齡
double score = 95.5;   // 分數

// 方法 1:字串插值 $"..." — 最推薦!(像填空題,直接把答案寫在空格裡)
string msg1 = $"我叫 {name},今年 {age} 歲,考了 {score} 分";

// 方法 2:String.Format — 傳統方式(像用編號對應答案)
string msg2 = String.Format("我叫 {0},今年 {1} 歲,考了 {2} 分", name, age, score);

// 字串插值支援格式化(像指定小數點要幾位)
string formatted = $"成績:{score:F1},日期:{DateTime.Now:yyyy-MM-dd}";
// 結果類似:"成績:95.5,日期:2024-01-15"

// 字串插值支援運算式(像計算機,直接在空格裡算)
string calc = $"{name} 明年 {age + 1} 歲"; // "小明 明年 26 歲"

⚡ StringBuilder:效能的好幫手

// ❌ 不好的做法:大量串接字串(像每次都重新抄一整封信再加一行)
string result = ""; // 空字串
for (int i = 0; i < 10000; i++) // 迴圈一萬次
{
    result += $"第 {i} 行\n"; // 每次都建立新的字串物件,非常慢!
}

// ✅ 好的做法:使用 StringBuilder(像在同一張紙上持續往下寫)
using System.Text; // 引用 StringBuilder 所在的命名空間

StringBuilder sb = new StringBuilder(); // 建立 StringBuilder 實例
for (int i = 0; i < 10000; i++) // 迴圈一萬次
{
    sb.AppendLine($"第 {i} 行"); // 在現有內容後面附加新行,不會建立新物件
}
string output = sb.ToString(); // 最後一次轉成字串

// StringBuilder 常用方法
StringBuilder builder = new StringBuilder("Hello"); // 初始內容
builder.Append(" World");    // 附加文字:"Hello World"
builder.Insert(5, ",");      // 在索引 5 插入逗號:"Hello, World"
builder.Replace("World", "C#"); // 取代文字:"Hello, C#"
builder.Remove(5, 2);          // 從索引 5 移除 2 個字元:"HelloC#"

💡 何時用 StringBuilder? 當你需要在迴圈中拼接超過 10 次以上的字串時,就該考慮使用 StringBuilder。就像蓋房子,如果只釘一兩根釘子用手動就好,但要釘一萬根就需要電動釘槍。


🔍 正規表達式 (Regex)

正規表達式就像一個超級搜尋引擎——你給它一個「模式」,它就能在文字中找出所有符合模式的內容。

基本使用

using System.Text.RegularExpressions; // 引用正規表達式命名空間

// IsMatch:檢查字串是否符合模式(像安檢門,通過就 true)
string phone = "0912-345-678"; // 要驗證的電話號碼
bool isValid = Regex.IsMatch(phone, @"^\d{4}-\d{3}-\d{3}$"); // true
// ^ 表示開頭,\d 表示數字,{4} 表示剛好 4 個,$ 表示結尾

// Match:找出第一個符合的結果(像在人群中找到第一個穿紅衣的人)
string text = "我的電話是 0912-345-678,辦公室是 02-1234-5678";
Match match = Regex.Match(text, @"\d{4}-\d{3}-\d{3}"); // 找手機號碼模式
if (match.Success) // 如果有找到
{
    Console.WriteLine($"找到:{match.Value}"); // "找到:0912-345-678"
}

// Matches:找出所有符合的結果(像找出人群中所有穿紅衣的人)
MatchCollection allMatches = Regex.Matches(text, @"\d+"); // 找出所有連續數字
foreach (Match m in allMatches) // 走訪每一個符合的結果
{
    Console.WriteLine(m.Value); // 印出:0912、345、678、02、1234、5678
}

Replace 與常用模式

// Regex.Replace:用模式取代文字(像自動修正所有錯別字)
string dirty = "價格是   100    元"; // 多餘的空白
string clean = Regex.Replace(dirty, @"\s+", " "); // 把多個空白變成一個
// 結果:"價格是 100 元"

// Email 驗證模式
string email = "user@example.com"; // 要驗證的 email
string emailPattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
bool isEmail = Regex.IsMatch(email, emailPattern); // true
// [a-zA-Z0-9._%+-]+ 表示使用者名稱可以包含英文、數字、點等字元

// 手機號碼驗證(台灣格式)
string phonePattern = @"^09\d{2}-?\d{3}-?\d{3}$"; // 09 開頭,可選的破折號
bool isPhone1 = Regex.IsMatch("0912345678", phonePattern);  // true(沒有破折號)
bool isPhone2 = Regex.IsMatch("0912-345-678", phonePattern); // true(有破折號)

📜 Verbatim 字串與 C# 11 原始字串

// 一般字串:需要用 \\ 來表示反斜線(像要寫特殊符號時需要前面加暗號)
string path1 = "C:\\Users\\Desktop\\file.txt"; // 需要跳脫每個反斜線

// Verbatim 字串 @"...":所見即所得(像照片,拍什麼就是什麼)
string path2 = @"C:\Users\Desktop\file.txt"; // 不需要跳脫,直接寫路徑
string multiLine = @"第一行
第二行
第三行"; // 可以直接換行,不需要 \n

// 在 verbatim 字串中要表示雙引號,用兩個雙引號
string quote = @"他說:""你好"",然後離開了"; // 他說:"你好",然後離開了

// C# 11 原始字串字面值 """..."""(像超強的保護套,裡面寫什麼都不用跳脫)
string json = """
{
    "name": "小明",
    "age": 25
}
"""; // 不需要跳脫任何雙引號

// 原始字串也支援插值
string name = "小明";
string rawInterpolated = $"""
{{
    "name": "{name}",
    "greeting": "你好"
}}
"""; // 用雙大括號 {{ }} 表示 JSON 的大括號

🤔 我這樣寫為什麼會錯?

❌ 錯誤 1:混淆 null、空字串和空白字串

// ❌ 錯誤寫法:用 == 檢查 null 和空字串
string input = GetUserInput(); // 取得使用者輸入
if (input == null || input == "") // 這樣寫可以,但不夠好
{
    Console.WriteLine("沒有輸入"); // 印出提示
}
// ✅ 正確寫法:使用 string.IsNullOrEmpty 或 string.IsNullOrWhiteSpace
string input = GetUserInput(); // 取得使用者輸入

// 檢查 null 或空字串
if (string.IsNullOrEmpty(input)) // 同時處理 null 和 ""
{
    Console.WriteLine("沒有輸入"); // 印出提示
}

// 更嚴格:還能抓到只有空白的情況(如 "   ")
if (string.IsNullOrWhiteSpace(input)) // 同時處理 null、"" 和 "   "
{
    Console.WriteLine("沒有有效輸入"); // 印出提示
}

解釋: string.IsNullOrWhiteSpace 最安全,因為使用者可能只輸入空白鍵。就像檢查信封裡有沒有信,不只要看信封是不是空的,還要看裡面是不是只塞了白紙。

❌ 錯誤 2:字串比較時忽略文化差異

// ❌ 錯誤寫法:直接用 == 比較使用者輸入(可能因大小寫不同而失敗)
string userInput = "hello"; // 使用者輸入的文字
if (userInput == "Hello") // false!大小寫不同
{
    Console.WriteLine("匹配"); // 永遠不會執行到這裡
}
// ✅ 正確寫法:指定比較方式
string userInput = "hello"; // 使用者輸入的文字

// 忽略大小寫比較
if (userInput.Equals("Hello", StringComparison.OrdinalIgnoreCase)) // true
{
    Console.WriteLine("匹配"); // 會印出
}

// 或者用 ToLower/ToUpper 統一後再比(但效能較差,因為會建立新字串)
if (userInput.ToLower() == "hello") // true,但不推薦
{
    Console.WriteLine("匹配"); // 會印出
}

解釋: 就像問路時,"台北車站" 和 "台北車站 " 應該是同一個地方,但電腦會認為它們不同。使用 StringComparison.OrdinalIgnoreCase 可以讓比較更有彈性,不會因為大小寫而出錯。

❌ 錯誤 3:在迴圈中用 + 拼接大量字串

// ❌ 錯誤寫法:在迴圈中用 + 拼接字串(每次都會建立新物件)
string html = ""; // 空字串
for (int i = 0; i < 1000; i++) // 迴圈一千次
{
    html += $"<li>項目 {i}</li>"; // 每次 += 都會建立一個新的字串物件
}
// 這會建立 1000 個暫時的字串物件,浪費記憶體!
// ✅ 正確寫法:使用 StringBuilder
StringBuilder sb = new StringBuilder(); // 建立 StringBuilder
for (int i = 0; i < 1000; i++) // 迴圈一千次
{
    sb.Append($"<li>項目 {i}</li>"); // 在同一個緩衝區附加文字
}
string html = sb.ToString(); // 最後一次性轉為字串

解釋: 字串在 C# 中是不可變的(immutable)。每次 += 都會建立一個全新的字串物件,舊的就變成垃圾等待回收。就像每次想加一頁就把整本書重新印一次——用 StringBuilder 就像在同一本筆記本上繼續寫,效率高很多。

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊