- 1 1. Giới thiệu
- 2 2. Chuỗi trong ngôn ngữ C là gì? Khái niệm cơ bản và tầm quan trọng của ký tự kết thúc
- 3 3. Cách trích xuất chuỗi con trong ngôn ngữ C [Phiên bản Thư viện chuẩn]
- 4 4. Phương pháp cắt chuỗi con bằng ngôn ngữ C [phiên bản tự viết hàm]
- 5 5. Phương pháp cắt chuỗi theo mã ký tự
- 6 6. Cách phân tách chuỗi trong ngôn ngữ C
- 7 7. Ứng dụng: Cách trích xuất phần trước và sau của ký tự cụ thể
- 8 8. Tóm tắt
1. Giới thiệu
Việc thao tác chuỗi trong ngôn ngữ C là một trong những kỹ năng quan trọng khi học lập trình. Đặc biệt, cắt chuỗi (trích xuất chuỗi con) thường được sử dụng khi xử lý dữ liệu hoặc chuyển đổi định dạng.
Trong bài viết này, cách cắt chuỗi trong ngôn ngữ C sẽ được giải thích, bao gồm cách sử dụng các hàm thư viện chuẩn, cách tạo hàm tự viết, hỗ trợ ký tự đa byte (tiếng Nhật), và cách phân tách chuỗi và nhiều hơn nữa. Ngoài ra, chúng tôi cũng sẽ giới thiệu các ví dụ ứng dụng và xử lý lỗi, vì vậy hãy đọc đến cuối.
Những gì bạn sẽ học trong bài viết này
Bằng cách đọc bài viết này, bạn có thể nắm được các kỹ năng sau.
- C ngôn ngữ lập trình chuỗi ký tự cơ bản khái niệm và ký tự kết thúc vai trò
strncpy
strchr
hàm thư viện chuẩn để trích xuất chuỗi con- Hàm tự làm
- Xem xét ký tự đa byte (tiếng Nhật)
strtok
phương pháp chia tách chuỗi- Cách lấy ký tự trước và sau ký tự cụ thể
Chúng tôi sẽ giải thích kèm các ví dụ mã để người mới bắt đầu cũng dễ hiểu.
Tại sao việc cắt chuỗi trong ngôn ngữ C lại quan trọng?
Ngôn ngữ C xử lý chuỗi như một “mảng (mảng kiểu char)” nên không thể lấy chuỗi con một cách đơn giản như các ngôn ngữ cấp cao khác (Python, JavaScript, v.v.). Do đó, việc chọn phương pháp phù hợp trong các tình huống sau là rất quan trọng.
1. Xử lý dữ liệu đầu vào
Ví dụ, khi phân tích dữ liệu như log hoặc tệp CSV, bạn cần trích xuất các mục cụ thể.
2. Tìm kiếm từ khóa cụ thể
Việc tìm kiếm từ khóa cụ thể trong một chuỗi và lấy thông tin xung quanh nó là điều thiết yếu cho chức năng tìm kiếm và trích xuất dữ liệu.
3. Nâng cao độ an toàn của chương trình
strncpy
bằng cách sử dụng đúng các hàm như vậy, bạn có thể ngăn chặn buffer overflow (ghi dữ liệu vượt quá kích thước bộ đệm). Điều này quan trọng để tránh các rủi ro bảo mật.
Cấu trúc của bài viết
Trong bài viết này, chúng tôi sẽ giải thích theo trình tự sau.
- Chuỗi trong ngôn ngữ C là gì? Khái niệm cơ bản và tầm quan trọng của ký tự kết thúc
- Cách cắt chuỗi con trong ngôn ngữ C【Phần thư viện chuẩn】
- C ngôn ngữ cách trích xuất chuỗi con【Tự viết hàm】
- Phương pháp cắt chuỗi theo mã ký tự
- Cách chia chuỗi trong ngôn ngữ C
- Ví dụ ứng dụng: Cách trích xuất trước và sau ký tự cụ thể
- Tóm tắt
- FAQ
Vậy thì, trước tiên chúng ta hãy xem chi tiết về “Chuỗi trong ngôn ngữ C? Khái niệm cơ bản và tầm quan trọng của ký tự kết thúc”.
2. Chuỗi trong ngôn ngữ C là gì? Khái niệm cơ bản và tầm quan trọng của ký tự kết thúc
2.1 Khái niệm cơ bản về chuỗi trong ngôn ngữ C
Chuỗi là “mảng char”
Trong ngôn ngữ C, chuỗi được xử lý như mảng các ký tự (mảng kiểu char) . Ví dụ, đoạn mã dưới đây là ví dụ cơ bản về định nghĩa và hiển thị chuỗi.
#include <stdio.h>
int main() {
char str[] = "Hello, World!"; // Define a string literal as an array
printf("%s ", str); // Output the string
return 0;
}
Trong đoạn mã này, "Hello, World!"
là một chuỗi được lưu trữ như mảng kiểu char
, và được xuất ra bằng printf("%s\n", str);
.
Cấu trúc bên trong của chuỗi
Chuỗi "Hello"
được lưu trữ trong bộ nhớ như sau.
chỉ mục | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
chữ | H | e | l | l | o | \0 |
Trong C, ký tự đặc biệt chỉ kết thúc chuỗi (ký tự null '\0'
) được tự động thêm vào cuối nên độ dài chuỗi là “số ký tự thực tế + 1” .
2.2 Tầm quan trọng của ký tự kết thúc (ký tự null 'Ký tự null là gì?
'
)
Ký tự null là gì?
'Vấn đề khi không có ký tự null
Ký tự null('\0'
)là ký tự đặc biệt chỉ kết thúc chuỗi . Để xử lý chuỗi trong C một cách đúng đắn, cần hiểu sự tồn tại của ký tự null này.
#include <stdio.h>
int main() {
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicitly specify the null terminator
printf("%s ", str); // Display correctly
return 0;
}
Trong đoạn mã trên, nếu không có '\0'
thì kết thúc của "Hello"
sẽ không được nhận diện, có thể gây ra hành vi không mong muốn .
2.3 Cách định nghĩa chuỗi đúng
Như sau, nếu quên ký tự kết thúc có thể gây ra hoạt động bất thường của bộ nhớ.
#include <stdio.h>
int main() {
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // Does not include the null terminator
printf("%s ", str); // May cause unexpected behavior
return 0;
}
Nguyên nhân lỗi
printf("%s\n", str);
ký tự null'\0'
- Nếu không tồn tại, có thể dữ liệu khác trên bộ nhớ sẽ được xuất ra。
Phương pháp ① Sử dụng literal chuỗi
Phương pháp ② Định nghĩa mảng một cách rõ ràng
Cách định nghĩa chuỗi phổ biến nhất là sử dụng literal chuỗi.
char str[] = "Hello";
Trong cách này, trình biên dịch C sẽ tự động thêm ký tự null '\0'
, vì vậy không cần xử lý đặc biệt.
2.4 Cách kiểm tra kích thước chuỗi
Nếu định nghĩa thủ công bao gồm '\0'
, thì viết như sau.
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
- Kích thước số ký tự và cuối cùng là là quan trọng。
- Nếu quên đặt vào , sẽ xảy ra hành vi không mong muốn.
Hoạt động của strlen
Để lấy độ dài (số ký tự) của chuỗi, sử dụng hàm strlen
.
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello";
printf("Length of the string: %lu\n", strlen(str)); // Outputs 5 (does not include the null terminator)
return 0;
}
2.5 Tổng kết
strlen
ký tự null'\0'
đếm số ký tự cho đến khi gặpsizeof(str)
3. Cách trích xuất chuỗi con trong ngôn ngữ C [Phiên bản Thư viện chuẩn]
- Chuỗi trong ngôn ngữ C được biểu diễn bằng mảng
char
- Ký tự kết thúc (ký tự null
'\0'
) được dùng để chỉ kết thúc chuỗi, vì vậy phải luôn bao gồm nó - Để lấy độ dài chuỗi
strlen
sử dụng - Nếu không định nghĩa chuỗi theo cách thích hợp, có thể xảy ra lỗi không mong muốn
3.1 strncpy
để lấy chuỗi con
Có thể sử dụng thư viện chuẩn để trích xuất chuỗi con trong C. Trong phần này, chúng tôi sẽ giải thích cách lấy một phần của chuỗi bằng cách sử dụng các hàm thư viện chuẩn như strncpy
và strchr
và các phương pháp sử dụng các hàm thư viện chuẩn để lấy một phần của chuỗi sẽ được giải thích。
strncpy
Cú pháp cơ bản
strncpy
là hàm sao chép một phần của chuỗi vào bộ đệm khác.
Ví dụ sử dụng cơ bản
char *strncpy(char *dest, const char *src, size_t n);
dest
src
n
'\0'
strncpy
Lưu ý
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6]; // Buffer to store the substring
strncpy(dest, src, 5); // Copy the first 5 characters "Hello"
dest[5] = '\0'; // Manually add the null terminator
printf("Substring: %s\n", dest); // Output "Hello"
return 0;
}
3.2 strncpy_s
Sao chép chuỗi an toàn
- ヌル文字
'\0'
を手動で追加する必要がある は最大 文字をコピーするが、ため、明示的に を追加する必要があります。 - Chú ý tràn bộ đệm kích thước lớn hơn có thể ghi vượt quá bộ đệm。
strncpy_s
Cú pháp cơ bản
strncpy_s
là phiên bản nâng cao tính an toàn của strncpy
, có thể ngăn chặn tràn bộ đệm.
Ví dụ
errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
dest
destsz
dest
src
n
strncpy_s
Ưu điểm
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
if (strncpy_s(dest, sizeof(dest), src, 5) == 0) {
dest[5] = '\0'; // Add null terminator just in case
printf("Substring: %s\n", dest);
} else {
printf("Copy error\n");
}
return 0;
}
3.3 strchr
Cắt chuỗi đến ký tự xác định
- Kích thước bộ đệm () để chỉ định, có thể sao chép an toàn.
destsz
n
Tuy nhiên, strncpy_s
được thêm vào tiêu chuẩn C11, do đó cần lưu ý rằng một số môi trường có thể không hỗ trợ.
strchr
Cú pháp cơ bản
strchr
cho phép tìm vị trí của ký tự xác định và lấy chuỗi đến phần đó.
Ví dụ
char *strchr(const char *str, int c);
str
c
char
Điểm chú ý
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strchr(str, ','); // Find the position of ','
if (pos != NULL) {
int length = pos - str; // Calculate the number of characters up to ','
char result[20];
strncpy(result, str, length);
result[length] = '\0'; // Add the null terminator
printf("Substring: %s\n", result); // Output "Hello"
}
return 0;
}
3.4 strstr
Tìm kiếm từ khóa và cắt chuỗi
strchr
c
đầu tiên được tìm thấypos - str
strncpy
strstr
Cú pháp cơ bản
strstr
hữu ích để tìm kiếm chuỗi con và lấy phần còn lại của chuỗi.
Ví dụ
char *strstr(const char *haystack, const char *needle);
haystack
needle
Điểm chú ý
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strstr(str, "World"); // Search for the position of "World"
if (pos != NULL) {
printf("Found substring: %s\n", pos);
} else {
printf("Substring not found.\n");
}
return 0;
}
3.5 Tổng kết
strstr
needle
NULL
needle
haystack
4. Phương pháp cắt chuỗi con bằng ngôn ngữ C [phiên bản tự viết hàm]
strncpy
khi sử dụng, có thể sao chép chuỗi con an toàn nhưng cần thêm ký tự null thủ công。strncpy_s
cho phép chỉ địnhdestsz
,nâng cao tính an toàn。strchr
Nếu sử dụng, bạn có thể lấy đoạn chuỗi đến một ký tự nhất định。strstr
nếu dùng, bạn có thể lấy vị trí của một từ khóa cụ thể và cắt phần sau đó。
Bằng cách tận dụng thư viện chuẩn, bạn có thể triển khai xử lý chuỗi trong C một cách đơn giản và an toàn.
4.1 Lợi ích của việc tạo hàm tự viết
Nếu tận dụng thư viện chuẩn, việc cắt chuỗi con cơ bản là khả thi, nhưng trong một số trường hợp có thể cần một phương pháp linh hoạt hơn . Vì vậy, trong phần này, chúng tôi sẽ giải thích về việc cắt chuỗi con bằng hàm tự viết .
4.2 Hàm trích xuất chuỗi con cơ bản
Khi sử dụng thư viện chuẩn, có thể sao chép và tìm kiếm chuỗi con, nhưng có những vấn đề như sau.
strncpy
không tự động thêm ký tự null'\0'
strchr
vàstrstr
chỉ có thể thực hiện tìm kiếm một phần- Thao tác chuỗi linh hoạt hơn là khó khăn
Do đó, việc tạo hàm tự viết có thể tùy chỉnh theo mục đích cụ thể là hiệu quả.
Đặc tả hàm
Đầu tiên, chúng ta sẽ tạo một hàm cơ bản để cỗi từ vị trí chỉ định.
Mã thực thi
- đối số
const char *source
int start
int length
char *dest
- Nội dung xử lý
start
length
dest
'\0'
Điểm chú ý
#include <stdio.h>
#include <string.h>
void substring(const char *source, int start, int length, char *dest) {
int i;
for (i = 0; i < length && source[start + i] != '\0'; i++) {
dest[i] = source[start + i];
}
dest[i] = '\0'; // Add null terminator
}
int main() {
char text[] = "Hello, World!";
char result[10];
substring(text, 7, 5, result); // Extract "World"
printf("Substring: %s\n", result);
return 0;
}
4.3 malloc
Lấy chuỗi con động bằng cách sử dụng
for
length
'\0'
dest[i] = '\0';
luôn đặt ký tự null ở cuối
Đặc tả hàm
Trong hàm trên, cần phải dự trữ trước kích thước của dest
. Tuy nhiên, nếu có thể dự trữ kích thước cần thiết một cách động, hàm sẽ trở nên đa dụng hơn.
Mã thực thi
- Cần bộ nhớ được cấp phát bằng
start
length
- Cần thực hiện ở bên gọi
Điểm chú ý
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *substring_dynamic(const char *source, int start, int length) {
char *dest = (char *)malloc(length + 1); // +1 for the null terminator
if (dest == NULL) {
return NULL; // Memory allocation failed
}
int i;
for (i = 0; i < length && source[start + i] != '\0'; i++) {
dest[i] = source[start + i];
}
dest[i] = '\0';
return dest;
}
int main() {
char text[] = "Hello, World!";
char *result = substring_dynamic(text, 7, 5);
if (result != NULL) {
printf("Substring: %s\n", result);
free(result); // Free allocated memory
} else {
printf("Memory allocation failed.\n");
}
return 0;
}
4.4 Hỗ trợ ký tự đa byte (tiếng Nhật)
malloc
cấp phát bộ nhớ động- Sau khi sử dụng, cần giải phóng bộ nhớ bằng cần giải phóng bộ nhớ.
Triển khai có tính đến ký tự đa byte
Khi làm việc với tiếng Nhật (các ký tự đa byte như UTF-8), một ký tự không nhất thiết chỉ chiếm 1 byte, vì vậy hàm substring
đơn giản sẽ không hoạt động đúng.
Mã thực thi (hỗ trợ UTF-8)
mbstowcs
wchar_t
wcsncpy
wcstombs
Điểm chú ý
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // Set the locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert UTF-8 string to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring in wide characters
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert back to multibyte string
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 string
char result[20];
substring_utf8(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
4.5 Tổng kết
setlocale(LC_ALL, "");
mbstowcs
wcsncpy
wcstombs
5. Phương pháp cắt chuỗi theo mã ký tự
substring
nếu tự tạo, bạn có thể lấy chuỗi con một cách linh hoạt。- Sử dụng cấp phát bộ nhớ động (
malloc
) thì có thể lấy được chuỗi con có kích thước thay đổi。 - Khi xử lý ký tự đa byte (tiếng Nhật),
mbstowcs
/wcstombs
sử dụng。
Khi thư viện chuẩn như strncpy
hoặc strchr
khó đáp ứng, việc tạo hàm tự viết có thể làm cho xử lý chuỗi trong ngôn ngữ C mạnh mẽ hơn.
5.1 Trường hợp ASCII (ký tự 1 byte)
Trong ngôn ngữ C, nếu không chú ý đến sự khác nhau của mã ký tự, việc cắt chuỗi có thể không hoạt động đúng . Đặc biệt, khi xử lý các ký tự đa byte như tiếng Nhật (UTF-8, Shift_JIS, EUC-JP, v.v.), vì 1 ký tự không luôn bằng 1 byte, các hàm đơn giản như strncpy
và substring
không thể xử lý đúng.
Trong phần này, phương pháp cắt chuỗi theo mã ký tự sẽ được giải thích chi tiết.
Lấy chuỗi con cơ bản
Ví dụ thực hiện
Ký tự ASCII là 1 ký tự = 1 byte nên có thể xử lý dễ dàng bằng các hàm strncpy
hoặc substring
.
5.2 Trường hợp UTF-8 (ký tự đa byte)
#include <stdio.h>
#include <string.h>
void substring_ascii(const char *source, int start, int length, char *dest) {
strncpy(dest, source + start, length);
dest[length] = '\0'; // Add null terminator
}
int main() {
char text[] = "Hello, World!";
char result[6];
substring_ascii(text, 7, 5, result); // Extract "World"
printf("Substring: %s\n", result);
return 0;
}
Lưu ý
- ASCII ký tự (chỉ ký tự tiếng Anh và số) nếu
strncpy
đủ đáp ứng '\0'
(ký tự null) phải luôn được thêm vào
Đặc tính của UTF-8
Phương pháp xử lý đúng
Trong UTF-8, số byte của một ký tự có thể thay đổi từ 1-4 byte , vì vậy nếu dùng strncpy
đơn giản có thể dẫn đến việc cắt giữa chừng một ký tự.
Lấy chuỗi con hỗ trợ UTF-8
Trong ngôn ngữ C, để xử lý UTF-8 một cách an toàn, nên dùng mbstowcs
để chuyển đổi sang chuỗi rộng ( wchar_t
) và sau đó lấy chuỗi con.
5.3 Trường hợp Shift_JIS (ký tự đa byte)
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // Set the locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Get the substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 string
char result[20];
substring_utf8(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
Lưu ý
setlocale(LC_ALL, "");
mbstowcs
wchar_t
wcsncpy
wcstombs
Đặc tính của Shift_JIS
Lấy chuỗi con hỗ trợ Shift_JIS
Trong Shift_JIS, một ký tự có thể là 1 byte hoặc 2 byte , vì vậy việc dùng strncpy
đơn giản sẽ gây ra lỗi hiển thị ký tự.
Triển khai trong Shift_JIS
Trong trường hợp Shift_JIS, cũng nên sử dụng phương pháp chuyển sang chuỗi rộng rồi xử lý .
5.4 Trường hợp EUC-JP (ký tự đa byte)
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_sjis(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "Japanese"); // Set locale to handle Shift_JIS
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string (Shift_JIS) to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (Shift_JIS)
}
int main() {
char text[] = "こんにちは、世界!"; // Shift_JIS string (depending on environment)
char result[20];
substring_sjis(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
Lưu ý
- Để xử lý Shift_JIS đúng cách, hãy đặt .
mbstowcs
wcstombs
Đặc tính của EUC-JP
Lấy chuỗi con hỗ trợ EUC-JP
EUC-JP cũng giống như Shift_JIS, do số byte của một ký tự thay đổi, nên cần sử dụng chuyển đổi sang chuỗi rộng .
5.5 Tổng kết
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_eucjp(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "ja_JP.eucJP"); // Set locale to handle EUC-JP
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // Convert multibyte string (EUC-JP) to wide-character string
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // Extract substring
wresult[length] = L'\0';
wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (EUC-JP)
}
int main() {
char text[] = "こんにちは、世界!"; // EUC-JP string (depending on environment)
char result[20];
substring_eucjp(text, 5, 3, result); // Extract "世界"
printf("Substring: %s\n", result);
return 0;
}
Lưu ý
setlocale(LC_ALL, "ja_JP.eucJP");
mbstowcs
wcstombs
6. Cách phân tách chuỗi trong ngôn ngữ C
Mã ký tự | số byte | Phương pháp xử lý được khuyến nghị |
---|---|---|
ASCII | 1 byte | strncpy |
UTF-8 | 1-4 byte | mbstowcs wcstombs |
Shift_JIS | 1 hoặc 2 byte | mbstowcs wcstombs |
EUC-JP | 1 hoặc 2 byte | mbstowcs wcstombs |
- Nếu chỉ có ký tự ASCII
strncpy
được - Trong trường hợp UTF-8, Shift_JIS, EUC-JP
mbstowcs
/wcstombs
sử dụng - Tùy theo môi trường
setlocale(LC_ALL, \"...\");
đặt đúng cách
6.1 strtok
để tách chuỗi
Quá trình tách chuỗi được sử dụng trong phân tích dữ liệu CSV, xử lý đối số dòng lệnh, phân tích dữ liệu log và nhiều trường hợp khác. Trong ngôn ngữ C, có thể dùng các hàm thư viện chuẩn như strtok
hoặc strtok_r
hoặc tự viết hàm riêng.
Trong phần này, chúng tôi sẽ giải thích chi tiết về cách tách chuỗi bằng ký tự phân tách cụ thể.
Cú pháp cơ bản
strtok
là hàm tách chuỗi dựa trên ký tự phân tách (delimiter) được chỉ định.
Ví dụ sử dụng: tách chuỗi bằng dấu phẩy ,
char *strtok(char *str, const char *delim);
str
delim
- Giá trị trả về
- Lưu ý
strtok
'\0'
Kết quả thực thi
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,orange,grape"; // String to be split
char *token = strtok(str, ","); // Get the first token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, ","); // Get the next token
}
return 0;
}
strtok
lưu ý
token: apple
token: banana
token: orange
token: grape
6.2 strtok_r
để tách chuỗi an toàn trong môi trường đa luồng
- Thay đổi chuỗi gốc
strtok
ký tự phân cách được thay thế bằng'\0'
để,
- không an toàn luồng
strtok
sử dụng biến tĩnh toàn cục bên trong
Cú pháp cơ bản
strtok_r
là phiên bản an toàn đa luồng của strtok
, lưu trạng thái vào saveptr
nên có thể sử dụng an toàn trong môi trường đa luồng.
Ví dụ sử dụng: tách chuỗi bằng dấu cách
char *strtok_r(char *str, const char *delim, char **saveptr);
str
delim
saveptr
Ưu điểm của strtok_r
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World from C"; // String to be split
char *token;
char *saveptr; // Pointer to store internal state
token = strtok_r(str, " ", &saveptr); // Get the first token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok_r(NULL, " ", &saveptr); // Get the next token
}
return 0;
}
6.3 Tự viết hàm tách chuỗi (không dùng strtok
)
- Thread-safe
- có thể xử lý nhiều chuỗi song song
Đặc tả hàm tự viết
strtok
thay đổi chuỗi gốc, vì vậy có thể tự tạo hàm tách chuỗi mà không làm thay đổi chuỗi gốc.
Mã thực hiện
- Nhập
const char *source
const char delim
char tokens[][50]
- Xử lý
source
delim
tokens
Kết quả thực thi
#include <stdio.h>
#include <string.h>
void split_string(const char *source, char delim, char tokens[][50], int *count) {
int i = 0, j = 0, token_index = 0;
while (source[i] != '\0') {
if (source[i] == delim) {
tokens[token_index][j] = '\0';
token_index++;
j = 0;
} else {
tokens[token_index][j] = source[i];
j++;
}
i++;
}
tokens[token_index][j] = '\0';
*count = token_index + 1;
}
int main() {
char text[] = "dog,cat,bird,fish";
char tokens[10][50]; // Can store up to 10 words
int count;
split_string(text, ',', tokens, &count);
for (int i = 0; i < count; i++) {
printf("Token: %s\n", tokens[i]);
}
return 0;
}
Điểm chú ý
Token: dog
Token: cat
Token: bird
Token: fish
6.4 Ứng dụng tách chuỗi (xử lý dữ liệu CSV)
source
tokens
Ví dụ phân tích dữ liệu CSV
Dữ liệu CSV (các trường ngăn cách bằng dấu phẩy) có thể được phân tích bằng strtok
.
Kết quả thực thi
#include <stdio.h>
#include <string.h>
int main() {
char csv[] = "Alice,24,Female\nBob,30,Male\nCharlie,28,Male"; // CSV data
char *line = strtok(csv, "\n"); // Process line by line
while (line != NULL) {
char *name = strtok(line, ",");
char *age = strtok(NULL, ",");
char *gender = strtok(NULL, ",");
printf("Name: %s, Age: %s, Gender: %s\n", name, age, gender);
line = strtok(NULL, "\n");
}
return 0;
}
6.5 Tổng kết
Name: Alice, Age: 24, Gender: Female
Name: Bob, Age: 30, Gender: Male
Name: Charlie, Age: 28, Gender: Male
Kết luận
phương pháp | Lợi ích | điểm bất lợi |
---|---|---|
strtok | Có thể chia nhỏ một cách đơn giản | Thay đổi chuỗi gốc |
strtok_r | an toàn luồng | Cách sử dụng hơi phức tạp |
hàm tự viết | Không thay đổi chuỗi gốc | mã trở nên dài |
Phân tích CSV | điều tiện cho xử lý dữ liệu | strtok Lưu ý hạn chế |
7. Ứng dụng: Cách trích xuất phần trước và sau của ký tự cụ thể
- Nếu chia đơn giản
strtok
- Nếu đa luồng
strtok_r
- Nếu bạn không muốn thay đổi bản gốc, hãy dùng hàm tự làm
- Có thể áp dụng cho phân tích dữ liệu CSV
Trong phần tiếp theo, chúng tôi sẽ giải thích chi tiết về «Ứng dụng: cách trích xuất ký tự trước và sau một ký tự cụ thể».
7.1 strchr
để lấy chuỗi trước ký tự cụ thể
Trong xử lý chuỗi, trích xuất phần trước và sau của ký tự hoặc từ khóa cụ thể thường cần thiết. Ví dụ, có thể có các trường hợp như sau.
- Lấy phần tên miền duy nhất từ URL
- Trích xuất tên tệp từ đường dẫn tệp
- Lấy chuỗi trước và sau các thẻ hoặc ký hiệu cụ thể
Trong ngôn ngữ C, strchr
và strstr
có thể được sử dụng để thực hiện các xử lý này. Ngoài ra, nếu cần xử lý linh hoạt hơn, việc tạo hàm tự viết cũng là một phương pháp hiệu quả.
Cú pháp cơ bản
strchr
khi sử dụng, có thể xác định vị trí của ký tự (được tìm thấy đầu tiên).
Ví dụ: Lấy tên tệp từ đường dẫn tệp
char *strchr(const char *str, int c);
str
c
char
strchr
nếu tìm thấy c
, sẽ trả về địa chỉ của nó.
Kết quả thực thi
#include <stdio.h>
#include <string.h>
void get_filename(const char *path, char *filename) {
char *pos = strrchr(path, '/'); // Search for the last '/'
if (pos != NULL) {
strcpy(filename, pos + 1); // Copy from the character after '/'
} else {
strcpy(filename, path); // If no '/', copy the whole path
}
}
int main() {
char path[] = "/home/user/documents/report.txt";
char filename[50];
get_filename(path, filename);
printf("Filename: %s\n", filename);
return 0;
}
Điểm chú ý
Filename: report.txt
7.2 strstr
để lấy chuỗi sau từ khóa cụ thể
strrchr
最後に出現した特定の文字(/
)の位置を取得pos + 1
chỉ tên tệp
Cú pháp cơ bản
strstr
khi sử dụng, có thể tìm kiếm chuỗi cụ thể (từ khóa) và lấy chuỗi sau vị trí đó.
Ví dụ: Lấy miền từ URL
char *strstr(const char *haystack, const char *needle);
haystack
needle
strstr
nếu tìm thấy needle
, sẽ trả về địa chỉ của vị trí đó.
Kết quả thực thi
#include <stdio.h>
#include <string.h>
void get_domain(const char *url, char *domain) {
char *pos = strstr(url, "://"); // Search for the position of "://"
if (pos != NULL) {
strcpy(domain, pos + 3); // Copy from the character after "://"
} else {
strcpy(domain, url); // If "://" is not found, copy the entire string
}
}
int main() {
char url[] = "https://www.example.com/page.html";
char domain[50];
get_domain(url, domain);
printf("Domain part: %s\n", domain);
return 0;
}
Điểm chú ý
Domain part: www.example.com/page.html
7.3 strchr
để phân tách phần trước và sau của ký tự cụ thể
strstr
"https://"
"http://"
"//"
pos + 3
://
Ví dụ: Tách tên người dùng và miền từ địa chỉ email
strchr
nếu sử dụng, có thể phân tách và lấy chuỗi trước và sau ký tự cụ thể.
Kết quả thực thi
#include <stdio.h>
#include <string.h>
void split_email(const char *email, char *username, char *domain) {
char *pos = strchr(email, '@'); // Search for the position of '@'
if (pos != NULL) {
strncpy(username, email, pos - email); // Copy the part before '@'
username[pos - email] = '\0'; // Add null terminator
strcpy(domain, pos + 1); // Copy the part after '@'
}
}
int main() {
char email[] = "user@example.com";
char username[50], domain[50];
split_email(email, username, domain);
printf("Username: %s\n", username);
printf("Domain: %s\n", domain);
return 0;
}
Điểm chú ý
Username: user
Domain: example.com
7.4 Ứng dụng: Trích xuất thuộc tính cụ thể trong thẻ HTML
strchr
'@'
strncpy
'@'
phần trước, sao chép và thêm ký tự nullstrcpy
'@'
Ví dụ: <a href="URL">
để lấy URL
Ngay cả khi lấy thuộc tính cụ thể từ thẻ HTML, strstr
có thể được sử dụng.
Kết quả thực thi
#include <stdio.h>
#include <string.h>
void get_href(const char *html, char *url) {
char *start = strstr(html, "href=\""); // Search for the position of href="
if (start != NULL) {
start += 6; // Move past href="
char *end = strchr(start, '"'); // Search for the next "
if (end != NULL) {
strncpy(url, start, end - start);
url[end - start] = '\0'; // Add null terminator
}
}
}
int main() {
char html[] = "<a href=\"https://example.com\">Click Here</a>";
char url[100];
get_href(html, url);
printf("Extracted URL: %s\n", url);
return 0;
}
Điểm chú ý
Extracted URL: https://example.com
7.5 Tổng kết
- bằng cách sử dụng ” vị trí tìm kiếm và di chuyển 6 ký tự。
strchr
"
Kết luận
Nội dung xử lý | Sử dụng hàm | lợi ích |
---|---|---|
Lấy phần trước ký tự cụ thể | strchr / strrchr | Đơn giản và nhanh |
Lấy phần sau ký tự cụ thể | strstr | Có thể tìm kiếm theo từ khóa |
Chia trước và sau bằng ký tự cụ thể | strchr + strncpy | Có tiện lợi cho việc phân tách tên người dùng・miền, v.v. |
Lấy thuộc tính của thẻ HTML | strstr + strchr | Có thể ứng dụng cho web scraping |
8. Tóm tắt
strchr
やstrstr
を活用すると、特定の文字・キーワードの前後を簡単に取得できる- Xử lý đường dẫn tệp, phân tích URL, tách địa chỉ email, v.v., rất hữu ích trong nhiều tình huống
- Có thể áp dụng cho các xử lý nâng cao như trích xuất dữ liệu web
8.1 Nhìn lại bài viết
Trong bài viết này, Phương pháp cắt chuỗi con trong ngôn ngữ C về điều đó, chúng tôi đã giải thích chi tiết từ cơ bản đến nâng cao. Ở đây, hãy ôn lại các điểm quan trọng của từng phần và sắp xếp phương pháp tối ưu theo mục đích sử dụng.
8.2 Phương pháp tối ưu cho từng mục đích
Phần | Nội dung | Điểm quan trọng |
---|---|---|
C ngôn ngữ chuỗi cơ bản | Trong ngôn ngữ C, chuỗi được coi là mảng , ký tự kết thúc rất quan trọng. | Khi xử lý chuỗi, |
Phân tách bằng thư viện chuẩn | strncpy strchr | strncpy cần thêm ký tự null thủ công |
Tách ra bằng hàm tự viết | Tạo hàm linh hoạt | malloc trích xuất chuỗi con có độ dài biến thể có thể |
Xử lý theo mã ký tự | Cách xử lý UTF-8, Shift_JIS, EUC-JP | mbstowcs wcstombs để chuyển đổi sang ký tự rộng là an toàn |
Cách phân tách chuỗi | strtok strtok_r | strtok thay đổi chuỗi gốc |
Trích xuất ký tự trước và sau ký tự cụ thể | strchr strstr | Lấy tên tệp, phân tích URL, phân tích HTML |
1. Cắt chuỗi con
2. Phân tách chuỗi
điểm sử dụng | phương pháp tối ưu |
---|---|
Tôi muốn lấy một chuỗi có độ dài cố định | strncpy or substring() |
Muốn thực hiện cắt an toàn | strncpy_s |
Xử lý ký tự đa byte (UTF-8, Shift_JIS, EUC-JP) | mbstowcs / wcstombs |
3. Lấy ký tự trước và sau một ký tự cụ thể
điều kiện sử dụng | phương pháp tối ưu |
---|---|
Muốn tách chuỗi một cách đơn giản | strtok |
Muốn thực hiện chia tách an toàn luồng | strtok_r |
Muốn tách mà không thay đổi chuỗi gốc | Hàm tự viết(split_string() ) |
8.3 Lưu ý khi xử lý chuỗi trong C
điều kiện sử dụng | phương pháp tối ưu |
---|---|
Lấy tên tệp từ đường dẫn tệp | strrchr(path, '/') |
Lấy phần tên miền từ URL | strstr(url, "://") |
Tách tên người dùng và miền từ địa chỉ email | strchr(email, '@') |
Lấy giá trị thuộc tính từ thẻ HTML | strstr(tag, "href=\"") + strchr(tag, '"') |
1. Quản lý chặt chẽ ký tự kết thúc null ‘__0__’ việc quản lý phải triệt để
Ví dụ sao chép chuỗi an toàn
Trong xử lý chuỗi C, việc quản lý đúng ký tự kết thúc ‘\0’ là quan trọng nhất. Đặc biệt khi sử dụng strncpy hoặc strchr, hãy chú ý phải thêm ký tự null một cách thủ công.
2. Cẩn thận với tràn bộ đệm
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, 5);
dest[5] = '\0'; // Add null terminator for safety
printf("Substring: %s\n", dest);
return 0;
}
3. Xử lý ký tự đa byte bằng mbstowcs
sử dụng
Trong thao tác chuỗi C, cần cẩn thận để không truy cập ngoài phạm vi mảng. Đặc biệt khi dùng strncpy, việc kiểm soát số byte sao chép là quan trọng.
Ví dụ sao chép chuỗi an toàn
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, sizeof(dest) - 1);
dest[5] = '\0'; // Explicitly add null terminator
printf("Substring: %s\n", dest);
return 0;
}
4. Quản lý kích thước bộ đệm
Khi làm việc với ký tự đa byte như UTF-8 hoặc Shift_JIS, strncpy hoặc strlen đơn giản sẽ không hoạt động đúng.
Do đó, khi xử lý ký tự đa byte, nên chuyển sang chuỗi rộng bằng mbstowcs rồi xử lý thích hợp.
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, ""); // Set the locale
char text[] = "こんにちは、世界!"; // UTF-8
wchar_t wtext[256];
mbstowcs(wtext, text, 256); // Convert to wide-character string
printf("Converted wide-character string: %ls\n", wtext);
return 0;
}
8.4 Hướng tới việc học sâu hơn
Trong xử lý chuỗi, việc tính toán trước kích thước bộ nhớ cần thiết và ngăn ngừa tràn bộ đệm là quan trọng. Đặc biệt khi dùng malloc để cấp phát bộ nhớ động, hãy chắc chắn biết chính xác kích thước.
Các chủ đề để học sâu hơn
Xử lý chuỗi trong C là kỹ năng quan trọng giúp nâng cao tính an toàn và khả năng đọc của chương trình. Dựa trên nội dung đã giới thiệu, nếu học thêm các chủ đề dưới đây, bạn sẽ có thể thực hiện xử lý chuỗi nâng cao hơn.
8.5 Tóm tắt
- Biểu thức chính quy (regex)
- Thao tác tệp (xử lý chuỗi bằng fgets, fscanf)
- Quản lý bộ nhớ (xử lý chuỗi động bằng malloc, realloc)
- Phân tích dữ liệu(Phương pháp phân tích JSON, XML)
8.5 Tóm tắt
- Trong ngôn ngữ C, chuỗi là
char
do được quản lý trong mảng, ký tự kết thúc'\0'
việc xử lý là quan trọng - Để cắt chuỗi con, hãy sử dụng
strncpy
,substring()
,malloc
- Để tách chuỗi, sử dụng
strtok
/strtok_r
/ sử dụng hàm tự viết - Khi muốn lấy ký tự trước và sau một ký tự cụ thể, hãy sử dụng
strchr
,strstr
- Khi xử lý ký tự đa byte (tiếng Nhật),
mbstowcs
hãy sử dụng - Hãy chú ý đến xử lý chuỗi an toàn, cẩn thận với tràn bộ đệm
Nếu áp dụng nội dung của bài viết này, bạn sẽ có thể thực hiện xử lý chuỗi thực tế trong C. Sau khi hiểu các hàm cơ bản, hãy thử tạo hàm tự viết và các xử lý nâng cao, để viết mã hiệu quả hơn!