======Cách sử dụng chuỗi trong Lua======
----
=====Giới thiệu=====
Chuỗi trong Lua là một kiểu dữ liệu cơ bản được dùng để lưu trữ và xử lý dữ liệu văn bản. Chuỗi biểu diễn **một dãy ký tự, bao gồm chữ cái, số, ký hiệu, khoảng trắng và các ký tự đặc biệt khác**.
Trong Lua, chuỗi có thể được tạo ra bằng cách đặt văn bản vào trong **dấu nháy đơn ( ' ), dấu nháy kép ( " ) hoặc dấu phân cách chuỗi (Ngoặc kép vuông) để tạo chuỗi nhiều dòng**. Ví dụ, "Hello, Mini World!" và 'Mini World is great!' đều là các cách biểu diễn chuỗi hợp lệ trong Lua.\\
Chuỗi có thể được gán cho biến, giúp bạn lưu trữ và xử lý dữ liệu văn bản. Ví dụ:\\
* Một chuỗi ký tự nằm giữa dấu nháy đơn.
local str1 = 'This is a string.'
local str2 = "This is also a string."
* Một chuỗi ký tự nằm giữa dấu nháy kép.
local str = "Hello, "
str = str .. "World!" -- Create a new string and assign it to str
print ( str ) -- Output "Hello, World!"
* Một chuỗi ký tự nằm giữa [[ và ]] .
local multilineString = [[
This is a multiline string.
It can contain multiple lines of text.
No need for escape characters.
]]
print(multilineString)
Ví dụ về chuỗi theo ba cách trên như sau:\\
string1 = "Lua"
Chat:sendSystemMsg(" \" String1 is \" " .. string1,0)
string2 = 'Mini World'
Chat:sendSystemMsg(" \" String2 is \" " .. string2,0)
string3 = [["Lua Tutorial"]]
Chat:sendSystemMsg(" \" String3 is \" " .. string3,0)
Kết quả xuất ra khi chạy đoạn mã trên là:\\
String 1 is Lua
String 2 is Mini World
String 3 is Lua Tutorial
----
=====Tính độ dài chuỗi=====
Trong Lua, bạn có thể tính độ dài của một chuỗi bằng cách sử dụng hàm **string.len()**. Độ dài của chuỗi thể hiện số lượng ký tự mà chuỗi đó chứa. Dưới đây là hướng dẫn từng bước cách tính độ dài chuỗi trong Lua:\\
__**Bước 1: Định nghĩa một chuỗi**__\\
Đầu tiên, hãy định nghĩa một biến chuỗi mà bạn sẽ dùng để tính độ dài. Ví dụ, bạn có thể đặt một biến tên là **myString** với giá trị là **"Hello, Lua!"**:\\
local myString = "Hello, Lua!"
__**Bước 2: Tính độ dài**__\\
Để tính độ dài chuỗi, bạn dùng hàm **string.len()**. Hàm này nhận vào một chuỗi và trả về độ dài của chuỗi đó. Ở đây, ta truyền biến **myString** vào hàm **string.len()**:\\
local length = string.len(myString)
__**Bước 3: Hiển thị kết quả**__
Để xem độ dài chuỗi vừa tính, bạn có thể in ra bảng điều khiển bằng hàm **print()**:\\
print("The length of the string is: " .. length)
**Ví dụ mã hoàn chỉnh:** Tổng hợp lại, đây là ví dụ mã hoàn chỉnh:\\
-- Định nghĩa chuỗi
local myString = "Hello, Lua!"
-- Tính độ dài
local length = string.len(myString)
-- Hiển thị kết quả
print("The length of the string is: " .. length)
**Kết quả:** Khi chạy đoạn mã trên, kết quả in ra sẽ là:\\
The length of the string is: 12
:!: Tuy nhiên, hàm **string.len()** trong Lua dựa trên mã hóa ASCII, có nghĩa là nó đếm số byte trong một chuỗi. Nếu bạn sử dụng **string.len()** trên một chuỗi chứa các ký tự ngoài phạm vi ASCII hoặc các ký tự được mã hóa bằng nhiều byte trong UTF-8, kết quả có thể không chính xác.\\
__Ví dụ:__ Nếu bạn muốn đếm độ dài một chuỗi không phải là tiếng Anh hoặc số, thì kết quả trả về có thể sai lệch.\\
Trong trường hợp này, bạn nên dùng **utf8.len()** thay cho **string.len()** khi làm việc với chuỗi chứa các ký tự được mã hóa UTF-8. Dưới đây là lý do và khi nào bạn nên sử dụng **utf8.len()**:\\
- **Xử lý ký tự UTF-8:** UTF-8 là dạng mã hóa có độ dài thay đổi, cho phép biểu diễn các ký tự từ nhiều ngôn ngữ khác nhau. Một số ký tự UTF-8 có thể được biểu diễn bằng nhiều byte. Khi bạn làm việc với các chuỗi chứa ký tự UTF-8, việc dùng **utf8.len()** sẽ đảm bảo đếm đúng số lượng ký tự hiển thị.
- **Đếm "Grapheme":** Trong một số ngôn ngữ, một ký tự hiển thị duy nhất (gọi là grapheme) có thể bao gồm nhiều mã code point. Ví dụ, trong các ngôn ngữ như tiếng Thái hoặc chữ Devanagari, một ký tự có thể được tạo nên từ nhiều phần. Hàm **utf8.len()** xử lý mỗi grapheme như một đơn vị duy nhất và trả về đúng số lượng ký tự hiển thị.
- **Tính độ dài chính xác:** **string.len()** chỉ đếm số byte trong chuỗi mà không quan tâm đến cách mã hóa. Điều này không phản ánh chính xác số lượng ký tự hoặc grapheme hiển thị trong chuỗi khi làm việc với UTF-8. Hàm **utf8.len()** sẽ trả về số lượng ký tự chính xác theo mã hóa UTF-8.
Dưới đây là ví dụ minh họa sự khác biệt giữa **string.len()** và **utf8.len()**:
local myString = "Café"
print(string.len(myString)) -- Output: 6
print(utf8.len(myString)) -- Output: 4
Trong ví dụ này, **string.len()** đếm tổng số byte trong chuỗi, bao gồm cả hai byte được dùng để biểu diễn ký tự “é” theo mã hóa UTF-8. Ngược lại, **utf8.len()** đếm chính xác số ký tự hiển thị (grapheme), nên kết quả là 4.\\
Tóm lại, Hãy dùng **utf8.len()** khi làm việc với các chuỗi chứa ký tự mã hóa UTF-8 để đảm bảo việc đếm số lượng ký tự hoặc grapheme được chính xác. Còn nếu chuỗi không chứa ký tự UTF-8 (chỉ toàn ký tự ASCII như chữ cái tiếng Anh, số, v.v.), thì bạn vẫn có thể dùng **string.len()** để tính độ dài chuỗi một cách đơn giản nha!\\
----
=====Xử lý chuỗi trong Lua=====
^ **STT** ^ **Phương thức & Cách dùng** ^
| 1 | **string.upper(argument)** \\ Chuyển tất cả các ký tự trong chuỗi thành chữ in hoa. |
| 2 | **string.lower(argument)** \\ Chuyển tất cả các ký tự trong chuỗi thành chữ thường. |
| 3 | **string.gsub(mainString, findString, replaceString, num):** \\ Trả về một chuỗi bằng cách thay thế `findString` bằng `replaceString` trong `mainString`. \\ __mainString:__ chuỗi gốc \\ __findString:__ ký tự cần thay thế \\ __replaceString:__ ký tự thay thế \\ __num:__ số lần thay thế (có thể bỏ qua, khi đó sẽ thay hết) |
| 4 | **string.find(str, substr, [init, [plain]])** \\ Tìm chuỗi `substr` trong chuỗi `str`. Nếu tìm thấy, trả về chỉ số bắt đầu và kết thúc của chuỗi con. Nếu không tìm thấy, trả về nil. |
| 5 | **string.format(arg)** \\ Trả về một chuỗi được định dạng, tương tự như printf trong ngôn ngữ C. |
| 6 | **string.char(arg) và string.byte(arg[,int])** \\ `char`: chuyển các số nguyên thành ký tự và nối chúng lại. \\ `byte`: chuyển ký tự thành giá trị số nguyên (có thể chỉ định ký tự, mặc định là ký tự đầu tiên). |
| 7 | **string.len(arg)** \\ Tính độ dài (số ký tự) của chuỗi. |
| 8 | **string.rep(string, n)** \\ Trả về chuỗi `string` được lặp lại `n` lần. |
| 9 | **.. (toán tử nối chuỗi)** \\ Dùng để nối hai chuỗi lại với nhau. |
| 10 | **string.gmatch(str, pattern)** \\ Trả về một hàm lặp. Mỗi lần gọi hàm sẽ trả về chuỗi con kế tiếp trong `str` phù hợp với `pattern`. Nếu không tìm thấy, trả về nil. |
| 11 | **string.match(str, pattern, init)** \\ Tìm chuỗi khớp đầu tiên trong `str` với `pattern`. `init` là tùy chọn, chỉ vị trí bắt đầu tìm (mặc định là 1). Nếu khớp: \\ – Có capture → trả về capture. \\ – Không có capture → trả về toàn bộ chuỗi khớp. \\ – Không khớp → trả về nil. |
Dưới đây là các ví dụ cho từng hàm xử lý chuỗi đã liệt kê ở trên:\\
**1. string.upper(argument)**\\
local str = "hello world"
local result = string.upper(str)
print(result) -- Kết quả: "HELLO WORLD"
**2. string.lower(argument)**\\
local str = "Hello World"
local result = string.lower(str)
print(result) -- Kết quả: "hello world"
**3. string.gsub(mainString, findString, replaceString, num)**\\
local str = "Hello, World!"
local result = string.gsub(str, "o", "a")
print(result) -- Kết quả: "Hella, Warld!"
**4. string.find(str, substr, [init, [plain]])**\\
local str = "Hello, World!"
local startPos, endPos = string.find(str, "World")
print(startPos, endPos) -- Kết quả: 8 12
**5. string.format(arg)**\\
local name = "John"
local age = 30
local result = string.format("My name is %s and I am %d years old.", name, age)
print(result) -- Kết quả: "My name is John and I am 30 years old."
**6. string.char(arg) và string.byte(arg[,int])**\\
local str = string.char(65, 66, 67) -- Mã ASCII
print(str) -- Kết quả: "ABC"
local char = string.byte("A")
print(char) -- Kết quả: 65 (Mã ASCII)
**7. string.len(arg)**\\
local str = "Hello, World!"
local length = string.len(str)
print(length) -- Kết quả: 13
**8. string.rep(string, n)**\\
local str = "Hello!"
local result = string.rep(str, 3)
print(result) -- Kết quả: "Hello!Hello!Hello!"
**9. .. (toán tử nối chuỗi)**\\
local str1 = "Hello"
local str2 = "World"
local result = str1 .. " " .. str2
print(result) -- Kết quả: "Hello World"
**10. string.gmatch(str, pattern)**\\
local str = "The quick brown fox"
for word in string.gmatch(str, "%a+") do
print(word)
end
-- Kết quả:
-- "The"
-- "quick"
-- "brown"
-- "fox"
**11. string.match(str, pattern, init)**\\
local str = "Hello, World!"
local match = string.match(str, "%a+")
print(match) -- Kết quả: "Hello"
----