首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 尋找字串中指定字元的所有位置

     編輯:關於C#

前言

在字串處理中,尋找特定字元出現的所有位置是常見需求。本文示範使用 ToCharArray 轉換字串為字元陣列,配合迴圈查找的基本做法,並提供更現代化的 LINQ 與 IndexOf 進階寫法。

基本實作:字元陣列遍歷

using System;
using System.Windows.Forms;

public class CharPositionFinder
{
    public void FindAllPositions(string input, char target)
    {
        char[] charArray = input.ToCharArray();
        
        for (int i = 0; i < charArray.Length; i++)
        {
            if (charArray[i] == target)
            {
                MessageBox.Show(
                    $"字元 '{target}' 在字串 \"{input}\" 中的位置為:{i}",
                    "查找結果");
            }
        }
    }
}

改良版:收集所有位置一次顯示

public void FindAllPositionsImproved(string input, char target)
{
    var positions = new List();
    char[] charArray = input.ToCharArray();
    
    for (int i = 0; i < charArray.Length; i++)
    {
        if (charArray[i] == target)
            positions.Add(i);
    }

    if (positions.Count > 0)
    {
        MessageBox.Show(
            $"字元 '{target}' 在 \"{input}\" 中出現 {positions.Count} 次,位置:[{string.Join(", ", positions)}]",
            "查找結果");
    }
    else
    {
        MessageBox.Show($"字元 '{target}' 在 \"{input}\" 中未找到", "查找結果");
    }
}

現代化寫法:LINQ 一行搞定

using System.Linq;

public IEnumerable FindPositionsLinq(string input, char target)
{
    return input.Select((c, index) => c == target ? index : -1)
                .Where(index => index != -1);
}

// 使用方式
var positions = FindPositionsLinq("hello world", 'l').ToList();
// 結果:[2, 3, 9]

高效能寫法:IndexOf 迴圈


public List FindPositionsIndexOf(string input, char target)
{
    var positions = new List();
    int index = input.IndexOf(target);
    
    while (index != -1)
    {
        positions.Add(index);
        index = input.IndexOf(target, index + 1);
    }
    
    return positions;
}

效能比較

方法時間複雜度記憶體適用場景
ToCharArray + forO(n)O(n) 額外陣列教學、簡單案例
LINQ Select/WhereO(n)O(n) 疊代器函數式風格、鏈式操作
IndexOf 迴圈O(n)O(1) 額外大字串、高效能需求
Regex.MatchesO(n)O(m) 比對結果複雜模式匹配

擴充功能:支援字串搜尋


public List FindSubstringPositions(string input, string substring)
{
    if (string.IsNullOrEmpty(substring))
        return new List();

    var positions = new List();
    int index = input.IndexOf(substring, StringComparison.Ordinal);
    
    while (index != -1)
    {
        positions.Add(index);
        index = input.IndexOf(substring, index + 1, StringComparison.Ordinal);
    }
    
    return positions;
}

// 不區分大小寫版本
public List FindSubstringPositionsIgnoreCase(string input, string substring)
{
    var positions = new List();
    int index = input.IndexOf(substring, StringComparison.OrdinalIgnoreCase);
    
    while (index != -1)
    {
        positions.Add(index);
        index = input.IndexOf(substring, index + 1, StringComparison.OrdinalIgnoreCase);
    }
    
    return positions;
}

完整 WinForms 範例


public partial class Form1 : Form
{
    private TextBox txtInput;
    private TextBox txtTarget;
    private Button btnFind;
    private ListBox lstResults;

    public Form1()
    {
        InitializeComponent();
    }

    private void btnFind_Click(object sender, EventArgs e)
    {
        string input = txtInput.Text;
        string target = txtTarget.Text;
        
        lstResults.Items.Clear();
        
        if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(target))
        {
            MessageBox.Show("請輸入字串與搜尋目標");
            return;
        }

        if (target.Length == 1)
        {
            // 單字元搜尋
            char c = target[0];
            var positions = FindPositionsIndexOf(input, c);
            DisplayResults(positions, c.ToString());
        }
        else
        {
            // 子字串搜尋
            var positions = FindSubstringPositions(input, target);
            DisplayResults(positions, target);
        }
    }

    private void DisplayResults(List positions, string target)
    {
        if (positions.Count == 0)
        {
            lstResults.Items.Add($"未找到 '{target}'");
        }
        else
        {
            lstResults.Items.Add($"找到 {positions.Count} 個 '{target}':");
            foreach (int pos in positions)
            {
                lstResults.Items.Add($"  位置 {pos} (第 {pos + 1} 個字元)");
            }
        }
    }

    // ... 上述尋找方法放在這裡
}

Unicode 與字元編碼注意事項

  • 代理配對:Emoji 等字元佔 2 個 char(UTF-16 代理配對),ToCharArray 會拆分
  • 解決方案:使用 StringInfo 或 Rune (NET Core 3.0+) 處理 Unicode 字素簇

using System.Globalization;

// 正確處理 Unicode 字素簇
public List FindGraphemePositions(string input, string target)
{
    var positions = new List();
    StringInfo si = new StringInfo(input);
    StringInfo targetSi = new StringInfo(target);
    
    if (targetSi.LengthInTextElements != 1)
        throw new ArgumentException("目標必須為單一字素簇");
    
    string targetGrapheme = targetSi.SubstringByTextElements(0, 1);
    
    for (int i = 0; i < si.LengthInTextElements; i++)
    {
        if (si.SubstringByTextElements(i, 1) == targetGrapheme)
            positions.Add(si.ParseCombiningCharacters[i]);
    }
    
    return positions;
}

總結

尋找字元位置的基本方法是遍歷字元陣列,但 IndexOf 迴圈效能最佳且記憶體效率最高。現代 C# 可使用 LINQ 簡化程式碼。處理 Unicode 字串時需注意代理配對問題,建議使用 StringInfo 或 Rune 正確處理字素簇。實務開發中建議封裝為擴充方法,方便重複使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved