6.1 Các thao tác cơ bản với mảng kí tự Thursday, September 21, 2017 7:19 PM
Được cắt từ: https://cpp.daynhauhoc.com/6/1-cac-thao-tac-co-ban-voi- mang-ki-tu/
Chao cdc ban hoc viên đang theo dõi khóa học lập trình trực tuyến ngôn ngữ C++
Trong bài học này, chúng ta sẽ cùng tìm hiểu một số cách để thao tác với C-style string thông qua các hàm đã được định nghĩa sẵn trong thư viện cstring Vì có rất nhiêu công việc cần giải quyết khi thao tác với mảng kí tự nên người ta đã tạo ra thư viện cstring để định nghĩa một tập hợp các hàm xử lý mảng kí tự, giúp chúng ta tiết kiệm thời gian và công sức viết code hơn trong khi chúng ta chỉ cần sử dụng lại những gì đã có sẵn Các bạn cần include thư viện cstring để có thể sử dụng các hàm được định nghĩa bên trong nó
Thiết lập giá trị cho một vùng nhớ thuộc mảng kí tự
Hàm memset sẽ giúp chúng ta lấp vào một số ô nhớ liên tiếp nhau trong mảng kí tự bằng một giá trị xác định Dưới đây là khai báo của hàm
memset:
void* memset( void *ptr, int value, size t num);
Các ban có thé hiéu ham memset thiét lap num bytes 6 nhớ đầu tiên bắt đầu từ địa chỉ ptr bang gia tri value dinh san Vi du nhu sau:
char foo[] = "Almost every programmer should know memset!"; cout << foo << endl;
memset(foo, '-', 7); cout << foo << endl;
Sau khi chạy đoạn chương trình này, kết quả mình nhận được trên màn hình console là 2 dòng text như sau:
Almost every programmer should know memset! - every programmer should know memset!
Như vậy, 7 bytes đầu tiên (tương đương với 7 kí tự trong mảng foo) đã bị hàm memset thiết lập bằng kí tự dấu trừ
Chúng ta cũng thường sử dụng hàm memset để khởi tạo toàn bộ mảng kí tự bằng một giá trị xác định nào đó
char foo[ 20];
memset(foo, 'a', sizeof(foo));
foo[sizeof(foo) - 1] = '\@'; //Don't forget to set the ending character at the end of C-style string
Trang 2và kí tự cuối cùng sẽ được thiết lập là kí tự kết thúc chuỗi như mình đã
trình bày trong bài học vê mảng kí tự Xem độ dài của chuỗi kí tự
Các bạn cần phân biệt rõ số lượng ô nhớ được cấp phát cho mảng kí tự sizeof(c_string) và độ dài của chuỗi kí tự (length of c_string)
Độ dài của chuỗi kí tự được tính từ kí tự đầu tiên cho đến kí tự kết thúc
chuỗi ( '\0"), trong khi đó, số lượng ô nhớ được cấp phát cho mảng kí tự được trả về thơng qua tốn tử sizeof
Để lấy được giá trị là độ dài của chuỗi kí tự được lưu bên trong mảng kí
tự, chúng ta có thể sử dụng hàm strlen được khai báo như sau: size_t strlen ( const char * str );
Hàm strlen nhận vào tên mảng kí tự mà các bạn muốn lấy độ dài va trả vê một số nguyên là độ dài chuỗi kí tự lưu trong mang Vi du:
char foo[50]| = "C++ Programming language" ;
cout << "Length of foo string: " << strlen(foo) << endl;
Đoạn code trên sẽ cho ra kết quả độ dài của chuỗi kí tự "C++ Programming language" là 24 Trong khi đó, nếu các bạn dùng toán tử sizeof(foo) thì kết quả sẽ là 50, vì mình yêu câu cấp phát 50 ô nhớ cho mảng kí tự foo Sao chép mảng kí tự
Khi sử dụng thư viện cstring, chúng ta có 2 cách để sao chép chuỗi kí tự từ một mảng kí tự sang mảng kí tự khác
Sử dụng hàm strcpy
Khai báo của hàm strcpy trong thư viện cstring:
char * strcpy ( char * destination, const char * source );
Hàm strcpy cho phép bạn sao chép toàn bộ chuỗi kí tự được lưu bên trong mảng kí tự source sang mảng kí tự destination
Ví dụ:
char str_source[] = "This is source string"; char str_destination| 30];
strcpy(str_destination, str_source);
Trang 3Lưu ý: Mảng kí tự str_ destination phải được cấp phát đủ bộ nhớ để lưu trữ chuối kí tự được copy từ mảng ki tu str_source
Sử dụng hàm strncpy
Hàm strncpy trong thư viện cstring được khai báo như sau:
char * strncpy ( char * destination, const char * source, size t num );
Hàm strncpy cho phép bạn sao chép num kí tự tử màng kí tu source sang mang ki tu destination
Vi du:
char str_source[] = "This is source string";
char str_destination|[ 30];
strncpy(str_destination, str_source, strlen(str_source) / 2);
Với đoạn code trên, chỉ có một nữa số lượng kí tự của mảng str._source được copy sang mang str_destination
Su dung ham strncpy_s khi su’ dung Visual studio 2015
Khi sử dụng hàm strcpy và strncpy, có một số trường hợp dẫn đến việc copy dữ liệu không an toàn Ví dụ:
char str_source[] = “*aaaaaaaaaaaaaaaaaaaaaa ' ; char str_destination[10];
strcpy(str_destination, str_source) ;
Đoạn code trên có thể gây xung đột vùng nhớ vì số lượng kí tự được copy vượt ra ngoài giới hạn vùng nhớ của str_destination Dó do, Visual
studio 2015 sẽ ngăn chặn hành vi build chương trình
Vi Visual studio 2015 ap dụng chuẩn C++~+11 trở lên, nên chúng ta cần sử dung ham strncpy_s thay thé cho 2 hàm copy mảng kí tự trong thư viện cstring
Trang 4char str_destination|[ 30];
strncpy_s(str_destination, str_source, strlen(str_source) ); Trong ví dụ trên, minh thuc hién copy toan b6 mang str_source vao
mảng str._destination bằng cách truyền vào đối số thứ ba của hàm là độ dài toàn bộ chuỗi kí tự bên trong mảng str_source
Nếu gặp trường hợp số lượng ô nhớ của mảng str._destination không đủ để chứa số lượng phần tử được copy từ mảng str._source, Visual studio sẽ đưa ra thông báo vi phạm Assertion của hàm strncpy_s
So sánh hai chuỗi kí tự
Hàm strcmp sẽ giúp chúng ta so sánh hai chuỗi kí tự int strcmp ( const chan * str1, const char * str2 );
Khi sử dụng hàm so sánh 2 chuỗi strcmp, có 3 trường hợp có thể xảy ra: ¢ Gia tri trả về là 0: - Điêu này có nghĩa nội dung của hai chuỗi kí tự này hoàn toàn giống nhau Ví dụ: char stri[ | char str2[ | "This is a string"; "This is a string"; if(strcmp(str1, str2) == 6) { cout << "str1 and str2 are equal" << endl; } else { cout << "str1 ans str2 are not equal" << endl; } ¢ Gia trị trả về nhỏ hơn 0: Điêu này có nghĩa tại vị trí phát hiện cặp kí tự không tương xứng giữa str1 và str2 tạm gọi là vị trí index_not_match, ta có: stri[index_not_match] < str[index_not_ match | Ví dụ: char stri[ | "abcDEF"; char str2[] = “abcdef”";
Khi so sánh chuỗi str1 và chuỗi str2 như trên bằng dòng lệnh
strcmp(str1, str2), ta nhận được giá trị trả vê nhỏ hơn 0, vì tại vị trí có chỉ số là 3, kí tự 'Ð' của str1 có mã ASCII nhỏ hơn kí tự 'd' của
str2
« Giá trị trả vê lớn hơn 0:
Ngược lại với việc giá trị trả vê nhỏ hơn 0 Mình lấy lại ví dụ trên: char stri[] = “abcDEF”;
char str2[] = "“abcdef";
Nếu các bạn thực hiện so sánh như sau: strcmp(str2, str1);
Giá trị trả vê sẽ lớn hơn 0 Nối chuỗi kí tự bằng một chuỗi kí tự khác
Để thực hiện thao tác nối một chuỗi bằng chuỗi kí tự khác, chúng ta sử
Trang 5char * strcat ( char * destination, const char * source );
Ý nghĩa của hàm này là nối vào sau chuỗi destination một bản copy của chuỗi kí tự source
Lưu ý: Mảng kí tự destination phải có đủ bộ nhớ để chứa được thêm chuôi mới được nối vào
char str_destination[ 50] "Hello"; strcat( str_destination, " " ); strcat( str_destination, "every" ); strcat( str_destination, "one"); cout << str destination << endl;
Tuy nhiên, Visual studio 2015 sử dụng chuẩn C++~+11 trở lên, vì thế đối với môi trường làm việc là Visual studio 2015, chúng ta nên sử dụng hàm
strcat_s
Hàm strcat_s có cách sử dụng hoàn toàn giống với hàm strcat, các bạn chỉ cần đổi lại tên hàm:
char str_destination[5@] = "Hello"; strcat_s( str_destination, " " ); strcat_s( str_destination, "every" ); strcat_s( str_destination, "one"); Tìm kiếm chuỗi kí tự trong một chuỗi kí tự khác
Phần này có liên quan đến khái niệm con trỏ mà các bạn sẽ được học trong các bài học sắp tới, vì thế, mình sẽ chưa giải thích nhiều về thao tác của hàm tìm kiếm chuôi mà thư viện cstring cung cấp
Để thực hiện tìm kiếm chuỗi kí tự pattern bên trong chuỗi kí tự text nào
đó, chúng ta sử dụng hàm strstr:
const char * strstr ( const char * text, const char * pattern ); Có thể tạm hiểu, hàm này sẽ trả về địa chỉ của ô nhớ của mảng kí tự text mà hàm này tìm thấy sự trùng khớp giữa chuỗi kí tự pattern với chuỗi kí tự text Nếu không tìm thấy, hàm này trả vé gia tri NULL
Để biết được vị trí mà hàm strstr tìm thấy chuỗi pattern trong chuỗi
text, các bạn có thể lấy địa chỉ của hàm strstr trả về trừ đi địa chỉ của ô nhớ đầu tiên trong mảng kí tự text
char text[] = "This is a simple string"; char pattern[] = "simple";
char *p = strstr(text, pattern);
if (p == NULL) {
cout << "Could not find the pattern string in the text string" << endl;
Trang 6else {
int32_t match_index = (p - text) / sizeof(char);
cout << "The pattern string match the text string at: " << match_index << endl; } This is a |simple] string simple point to Pp match index p Text | Tilh{iils ifs a s|i]l m|] p| lle s[tlrlilnløl`0 << + _ “ (b - text) Tổng kết Trong bài học này, chúng ta vừa làm quen với một số thao tác cơ bản với C-style string
Một số hàm trong thư viện cstring khi sử dụng trong môi trường làm việc
Visual studio 2015 sẽ bị cảnh bảo khơng an tồn, và chương trình không
thể biên dịch Đối với những hàm này, chúng ta cần sử dụng theo chuẩn
của Visual studio 2015, nhưng đó không phải là những hàm chuẩn, nó chỉ
dùng trong môi trường của Visual studio 2015
Thư viện cstring còn hổ trợ cho chúng ta rất nhiều những hàm khác,
nhưng thường ít được sử dụng Các bạn có thể truy cập liên kết bên dưới
để tham khảo thêm về thư viện cstring:
http ://www.cplusplus.com/reference/cstring/
Bài tập cơ bản
1/ Viết chương trình nhập một chuỗi kí tự vào từ bàn phím, chuyển tất cả
các kí tự trong chuồi thành dạng in hoa Ví dụ: Chuỗi kí tự nhập vào: "This is a simple string"
Output: "THIS IS A SIMPLE STRING"
2/ Viết chương trình nhập vào một chuỗi kí tự str và một kí tự ch từ bàn
phím, đếm trong chuỗi kí tự str có bao nhiêu lần xuất hiện kí tự ch mà