C# – Các phương thức xử lý chuỗi nâng cao

CSharp_icon

Trong nhiều trường hợp bạn cần xử lý chuỗi theo một cách mà lớp String không hỗ trợ. Bạn có thể tự viết các hàm xử lý chuỗi cần thiết và tạo ra một thư viện dạng .dll (Dynamic Link Library : Thư viện liên kết động) để thêm vào ứng dụng khi cần thiết.

 

Trong bài viết này tôi sẽ tạo ra một lớp StringToolkit chứa các phương thức static để xử lý chuỗi theo các yêu cầu thường gặp khi lập trình. Bạn có thể chọn kiểu dự án là ClassLibrary hoặc gán Output type là Class Library để tạo ra file .dll.

Sau khi đọc xong các phương thức này bạn có thể nhận ra là nó hoàn toàn là nâng cao như tiêu đề đã viết. Đây chỉ là một cách viết để ta không bị nhầm lẫn với các phương thức của lớp string.

Cách viết các đoạn mã dưới đây tương đối dễ hiểu, tôi chỉ giải thích một số phần cần thiết.

 

Viết mã nguồn

1)      Chuyển chuỗi về dạng Title Case

Mô tả: In hoa các kí tự đầu tiên của mỗi từ.

-Input:                         Chào mừng ĐếN YinYang‘s blog

-Output:          Chào Mừng Đến Yinyang‘s Blog

public static string ToTitleCase(string str)
{
s = s.ToLower();
char[] charArr = s.ToCharArray();
charArr[0] = Char.ToUpper(charArr[0]);
foreach (Match m in Regex.Matches(s, @”(\s\S)”))
{
charArr[m.Index + 1] = m.Value.ToUpper().Trim()[0];
}

return new String(charArr);
}

Ý tưởng thực hiện là đầu tiên ta sẽ chuyển chuỗi về chữ thường, sau đó tìm kiếm các kí tự đứng sau một khoảng trắng bất kì, rồi thay thế kí tự này bằng kí tự in hoa của nó.

Để thực hiện trước tiên ta chuyển chuỗi sang chữ thường bằng phương thức ToLower(). Sao đó tiếp tục chuyển chuỗi thành một mảng char để dễ dàng thay đổi từng kí tự. Trước khi vào vòng lặp chính, ta cần chuyển kí tự đầu tiên thành chữ hoa bằng dòng lệnh

charArr[0] = Char.ToUpper(charArr[0]);

Vòng lặp chính như bạn có thể thấy, nó sẽ tìm tất cả các kí tự đứng sau khoảng trắng và chuyển thành chữ hoa.

foreach (Match m in Regex.Matches(s, @”(\s\S)”))
{
charArr[m.Index + 1] = m.Value.ToUpper().Trim()[0];
}

Phương thức này sử dụng lớp Regex (viết tắt của  Regular Expressions – tạm dịch là Biểu thức chính quy) trong namespace System.Text.RegularExpressions để tìm kiếm trong chuỗi truyền vào. Chuỗi pattern “\s\S” sẽ tìm kiếm các kí tự đứng sau khoảng trắng hoặc kí tự đầu câu.

Nếu cảm thấy cách làm trên khá phức tạp, bạn có thể thử cách sau, tương đối ngắn gọn và dễ hiểu hơn:

private string ToTitleCase(string input)
{
input = input.ToLower();
input = ” ” + input;
foreach(Match m in Regex.Matches(input,@”\s\S”))
input=input.Replace(m.Value,m.Value.ToUpper());
return input.Substring(1);
}

Việc thêm khoảng trắng đầu chuỗi để chắc rằng kí tự đầu tiên không bị bỏ sót khi so khớp, cuối phương thức khoảng trắng dư này sẽ được cắt bỏ bằng Substring().

(*    “\s”  đại diện cho kí tự khoảng trắng)
*  “\S”  đại diện cho mọi kí tự trừ khoảng trắng)
*  “^”  kí tự đầu dòng
* “.” Mọi kí tự trừ kí tự xuống dòng
***  Vì Regular Expressions là một chủ đề lớn tương đối phức tạp, nó được sử dụng trong nhiều phần mềm và ngôn ngữ lập trình để phục vụ tìm kiếm hoặc xử lý văn bản. Bạn có thể tìm kiếm các chủ đề hướng dẫn về Regular Expressions trên mạng hoặc sách vở trước khi cảm thấy thích thú với nó.)

2)      Chuyển chuỗi sang dạng Toggle Case

Mô tả: Chuyển các kí tự hoa thành thường và ngược lại

-Input:                         Chào mừng ĐếN YinYang‘s blog

-Output:          cHÀO MỪNG đẾn yINyANG‘S BLOG

public static string ToToggleCase(string str)

{

string ret=””;

foreach (char c in str)

{

string s = c.ToString();

if (s==s.ToLower())

ret += s.ToUpper();

else

ret += s.ToLower();

}

return ret;

}

3)      Chèn một chuỗi vào chuỗi nguồn (tính từ trái hoặc phải)

public static string Insert(string input,string value,int startIndex,bool rightToLeft)

{

if (rightToLeft)

{

if (startIndex > input.Length)

startIndex = 0;

else

startIndex = input.Length – startIndex;

}

else

{

if (startIndex > input.Length)

startIndex = input.Length;

}

return input.Insert(startIndex, value);

}

Trong các phương thức này thay vì kiểm tra và thay đổi các giá trị của tham số, bạn có thể ném ra một ngoại lệ.

4)      Xóa một chuỗi từ chuỗi nguồn

public static string Remove(string input,int startIndex,int count, bool rightToLeft)
{
try
{
if (rightToLeft)
{
if (startIndex > input.Length)
startIndex = 0;
else
startIndex = input.Length – startIndex-count;
}
else
{
if (startIndex > input.Length)
startIndex = input.Length;
}

startIndex = startIndex< 0 ? 0 : startIndex;

if (count > input.Length)
count = input.Length;
else
count = count < 0 ? 0 : count;

return input.Remove(startIndex, count);
}
catch(Exception ex)
{
throw ex;

}
}

5)      Thay thế một chuỗi con

<!–[if gte mso 9]> Normal 0 false false false MicrosoftInternetExplorer4 <![endif]–><!–[if gte mso 9]> <![endif]–> <!–[endif]–>

public static string Replace(string input,string oldValue, string newValue, bool matchCase)

{

RegexOptions regexOption=RegexOptions.None;

 

if (!matchCase)

{

regexOption= RegexOptions.IgnoreCase;

}

Regex regex = new Regex(oldValue,regexOption);

input = regex.Replace(input, newValue);

return input;

}

Phương thức không làm gì khác ngoài việc sử dụng phương thức Replace của lớp Regex để thay thế. Nếu bạn thấy phương thức này không cần thiết, có thể loại bỏ khỏi lớp StringToolkit của bạn.

6)      Loại bỏ các dấu tiếng Việt khỏi chuỗi

Một phương thức sử dụng Regex bằng cách tìm tất cả các kí tự tiếng Việt có dấu và thay thế bằng kí tự không dấu tương ứng. Bạn có thể thấy tôi đặt kí tự không dấu ở đầu mỗi chuỗi pattern. Việc lặp qua từng pattern sẽ tìm và thay thế các kí tự tìm thấy bằng kí tự đầu tiên của chuỗi pattern đó.

Đây là một cách viết nhanh chóng để thay thế với số lượng lớn các chuỗi.

public static string RejectMarks(string text)

{

string[] pattern= new string[7];

pattern[0] = “a|(á|ả|à|ạ|ã|ă|ắ|ẳ|ằ|ặ|ẵ|â|ấ|ẩ|ầ|ậ|ẫ)”;

pattern[1]= “o|(ó|ỏ|ò|ọ|õ|ô|ố|ổ|ồ|ộ|ỗ|ơ|ớ|ở|ờ|ợ|ỡ)”;

pattern[2] = “e|(é|è|ẻ|ẹ|ẽ|ê|ế|ề|ể|ệ|ễ)”;

pattern[3] = “u|(ú|ù|ủ|ụ|ũ|ư|ứ|ừ|ử|ự|ữ)”;

pattern[4] = “i|(í|ì|ỉ|ị|ĩ)”;

pattern[5] = “y|(ý|ỳ|ỷ|ỵ|ỹ)”;

pattern[6] = “d|đ”;

for (int i = 0; i < pattern.Length; i++)

{

// kí tự sẽ thay thế

char replaceChar = pattern[i][0];

MatchCollection matchs = Regex.Matches(text,pattern[i]);

foreach (Match m in matchs)

{

text = text.Replace(m.Value[0],replaceChar);

}

}

return text;

}

Phần kết

Trên đây chỉ là các ví dụ đơn giản, bạn có thể có các cách viết khác tối ưu hơn và có thể tạo thêm cho mình các phương thức xử lý khác. Tuy nhiên, trong một chừng mực nào đó, phương thức của bạn không nên “ôm đồm” quá nhiều tham số và chức năng để xử lý.

Trong các bài viết tới, có thể tôi sẽ dùng đến lớp này để tìm hiểu về nạp chồng toán tử trong C#, và cách sử dụng các phương thức này để hiện thức hóa một chương trình đổi tên file hàng loạt.

https://yinyangit.wordpress.com

14/6/2009

<!–[if gte mso 9]> Normal 0 false false false MicrosoftInternetExplorer4 <![endif]–><!–[if gte mso 9]> <![endif]–> <!–[endif]–>

14/6/2009

Advertisements

18 thoughts on “C# – Các phương thức xử lý chuỗi nâng cao

  1. string chuoi = “Mot, Hai, Ba, Bon, Nam.”;
    //tạo pattern
    //luật: xem chuỗi nào có chứa khoảng trắng hay dấu phẩy
    string pattern = ” |, “;
    Regex myRegex = new Regex(pattern);
    string[] sKetQua = myRegex.Split(chuoi);
    foreach (string subString in sKetQua)
    {
    label1.Text = ” ” + subString;
    }
    __________
    Nếu chạy nó thì LABEL1 sẽ là Năm
    mình ko biết làm thế nào để cho cái

    label2 có kết quả là bốn
    label3 có kết quả là ba
    label4 có kết quả là hai.
    Mong bạn chỉ giúp
    ______________________________

    Trả lời
  2. Nếu chỉ split chuỗi theo token thì bạn ko cần dùng đến Regex chỉ dùng phương thức Split của lớp string là được. Còn vòng lặp bạn chỉ dùng mỗi label1 để gán text, ko biết bạn có bao nhiêu label và có ứng với số chuỗi con được tách ra ko? Bạn có thể dùng vòng lặp for thông thường và gán vào thuộc tính Text của label thôi.

    Trả lời
  3. Không biết Yang đã để ý tới việc tận dụng sức mạng của C++ chưa.

    cấu trúc chương trình mà Phi Y sử dụng thường là : Giao diện và những ứng dụng bên trên ( form, web) thì dùng C#, còn các tầng phía dưới thì CPP, thậm chí là C.

    nếu được thì những hàm, những template bên STL chuyển qua bên C# hiệu suất sẽ nâng cao 1 cách đáng kể

    Trả lời
  4. Thank Phi Y, trước đây chưa nghĩ tới điều này với lại cũng bận quá nên cũng lâu rồi chưa đụng tới lập trình. Sau này khi làm ứng phải dành thời gian nghiên cứu sâu hơn. Thực sự thì cũng ko ưng ý lắm tốc độ các chương trình viết trên C#, nó cũng hạn chế để có thể lập trình sâu như C/C++ được.

    Trả lời
    • Bạn chỉ cần dùng phương thức IndexOf của đối tượng string để tìm vị trí của dấu “.” và dùng Substring hoặc Remove để xóa đi. Ví dụ chuỗi s là “abc.123” bạn có thể tách “abc” như sau:

      s=s.Remove(s.IndexOf(‘.’));

      Thân!

      Trả lời
  5. Mình dùng cách này để chuyển chuỗi về dạng Title Case, đơn giản hơn chút
    str = ” ” + str;
    for (i = 0; i <= str.Length-1; i++)
    if ((str[i].ToString()==" " )&&(str[i+1].ToString()!=" "))
    {
    st1=str.Substring(i+1,1);
    st = st1.ToUpper();
    str = str.Remove(i + 1, 1);
    str = str.Insert(i + 1, st);
    }

    Trả lời
  6. hoặc dùng phương thức có sẵn trong VS2010-copy tu help
    using System;
    using System.Globalization;
    public class SamplesTextInfo {
    public static void Main() {
    // Defines the string with mixed casing.
    string myString = “wAr aNd pEaCe”;

    // Creates a TextInfo based on the “en-US” culture.
    TextInfo myTI = new CultureInfo(“en-US”,false).TextInfo;

    // Changes a string to lowercase.
    Console.WriteLine( “\”{0}\” to lowercase: {1}”, myString, myTI.ToLower( myString ) );

    // Changes a string to uppercase.
    Console.WriteLine( “\”{0}\” to uppercase: {1}”, myString, myTI.ToUpper( myString ) );

    // Changes a string to titlecase.
    Console.WriteLine( “\”{0}\” to titlecase: {1}”, myString, myTI.ToTitleCase( myString ) );

    }

    }

    /*
    This code produces the following output.

    “wAr aNd pEaCe” to lowercase: war and peace
    “wAr aNd pEaCe” to uppercase: WAR AND PEACE
    “wAr aNd pEaCe” to titlecase: War And Peace

    */

    Trả lời

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s