[Học lập trình C] Sử dụng chuỗi trong lập trình C/C++

Trong C và C++, chuỗi thì được miêu tả như một mảng các ký tự mà có null terminator. Null terminator có nghĩa là chuỗi được kết thúc với một kí tự ‘\0’ (nó có mã ASCII là 0)

Để khai báo một chuỗi trong C, cách đơn giản là khai báo một mảng char và khởi tạo giá trị cho mảng đó khi khai báo’, N’

Trong C chuẩn, bạn phải sử dụng mảng char để miêu tả một chuỗi. Một chuỗi là một mảng kết hợp nhiều kí tự kiểu char lại với nhau mà nó một phần của văn bản.Chúng ta cùng xem một chuỗi dưới đây :

cout << “Day la mot string ” ;

Trong C và C++, chuỗi thì được miêu tả như một mảng các char mà có null terminator. Null terminator có nghĩa là string được kết thúc với một kí tự ‘\0’ (nó có mã ASCII là 0)

Để khai báo một chuỗi trong C, cách đơn giản là khai báo một mảng char và khởi tạo giá trị cho mảng đó khi khai báo

char szString[] = “string”;

Mặc dù “szString” chỉ có 6 kí tự, nhưng thực ra mảng này có độ dài bằng 7. Chương trình dưới đây sẻ in ra độ dài của chuổi và sau đó xuất giá trị ASCII của tất cả kí tự :

cout << sizeof(szString) << endl;

for (int nChar = 0; nChar < sizeof(szString); nChar++)

cout << static_cast(szString[nChar]) << ” “;

Kết quả :

7

115 116 114 105 110 103 0

0 là giá trị ASCII của null terminator mà nó được gán thêm vào để đánh dấu sự kết thúc của chuỗi.

Giống như một mảng bình thường, một mảng khi được khai báo thì có kích thước cụ thể, nó không thể thay đổi. mảng szString ở trên có độ dài bằng 7 nghĩa là nó chứa 6 kí tự mà chúng ta đưa ra và null terminator. Nếu bạn cố gắng khai báo cụ thể độ dài của mảng là 6, bạn sẻ ghi đè lên null terminator và CPU không biết đâu là nơi kết thúc chuỗi.

Khi bạn khai báo string trong trường hợp này, một cách tốt là bạn sử dụng [] và cho trình biên dịch tự tính toán kích thước của mảng. Sử dụng cách này, nếu bạn thay đổi string sau đó, bạn không phải thay đổi lại kích thước của mảng.

Bạn phải chú ý một điều quan trọng là một char thì được cấp 1 byte bộ nhớ. Nhưng một string(ví dụ “a”) có một kí từ thì được cấp phát 2 byte bộ nhớ, môt byte dành cho char (“a”) và một byte dành cho null terminator.

Từ khi khai báo mảng string , bạn có thể sử dụng toán tử [] để thay đổi một kí tự nào đó trong string :

char szString[] = “string”;

szString[1] = ”p”;

cout << szString;

Chuỗi kết quả :

spring

Một chú ý quan trọng là string thỏa mản tất cả các quy tắc giống như một mảng bình thường.

Điều này có nghĩa là bạn có thể khởi tạo cho nó khi khai báo nhưng bạn không thể gán giá trị cho nó sử dụng toán tử gán sau đó.

char szString[] = “string”; // được phép

szString = “rope”; // khong được phép!

Buffers và buffer overflow

Bạn có thể đọc một đoạn text vào trong string bằng cách sử dụng cin :

char szString[255];

cin >> szString;

cout << “You entered: ” << szString << endl;

Tại sao chúng ta khai báo độ dài của string là 255 kí tự ? Câu trả lời là tại vì chúng ta không biết chuổi mà người dùng nhập vào có độ dài bao nhiêu kí tự. Chúng ta sử dụng mảng 255 kí tự này như là một buffer. Buffer là một vùng bộ nhớ được đưa ra để dành để lưu trữ dữ liệu.

Nếu người dùng nhập vào nhiều hơn số kí tự mà mảng có thể giữ (trong trường hợp này là hơn 255 kí tự), chương trình sẻ bị buffer overflow. Buffer overflow xảy ra khi chương trình cố gắng chứa nhiều dữ liệu hơn trong buffer mà buffer đó có thể nắm giữ. Buffer overflow thường dẩn đến phần bộ nhớ khác sẽ bị overwritten (ghi đè lên) và kết quả là chương trình của bạn thường bị crash. Việc tạo ra một buffer có đội dài 255 kí tự là tại vì chúng ta ước chừng rằng người dùng sẽ không nhập nhiều hơn chừng đó kí tự. Điều này thường được thấy trong chương trình C/C++ và nó dẫn đến một chương trình tệ.

Một phương pháp được đề cập dưới đây giúp bạn đọc string sử dụng cin có thể tránh được lỗi như trên :

char szString[255];

cin.getline(szString, 255);

cout << “You entered: ” << szString << endl;

Lời gọi hàm cin.getline() sẽ đọc 254 kí tự vào szString (để lại một kí tự cho null terminator). Những kí tự vượt quá số kí tự trên sẽ bị loại bỏ. Trong cách này, chúng ta có thể đảm bảo được buffer overflow không xảy ra.

Xử lý Strings

C++ cung cấp nhiều hàm để xử lý string. Ví dụng strcpy() cho phép bạn copy string.

char szSource[] = “Copy this!”;

char szDest[50];

strcpy(szDest, szSource);

cout << szDest; // in ra “Copy this!”

Tuy nhiên, strcpy có thể là nguyên nhân dẫn đến buffer overflow. Trong chương trình ở dưới đây, szDest không đủ để chứa toàn bộ chuỗi, cho nên sẻ xảy ra buffer overflow.

char szSource[] = “Copy this!”;

char szDest[4];

strcpy(szDest, szSource); // buffer overflow!

cout << szDest;

Cách tốt nhất để sử dụng strncpy() là chúng ta thêm vào một đối số để ngăn chặn buffer overflow:

char szSource[] = “Copy this!”;

char szDest[50];

strncpy(szDest, szSource, 49); // copy cho den 49 ki tu (index tu 0-48)

szDest[49] = 0; // gan ki tu thu 49 cho null terminator

cout << szDest;

Những hàm khác thường dùng :

strcat()- nối một string vào 1 string khác

strncat()- nối một string và 1 string khác.

strcmp()- so sánh 2 string (trả về 0 nếu bằng nhau)

strlen() – trả về độ dài của chuỗi

Dưới đây là chương trình minh họa một số khái niệm trong bài học này :

// yeu cau người dung nhap vao string

char szBuffer[255];

cout << “Nhap vao mot string: “;

cin.getline(szBuffer, 255);

int nSpacesFound = 0;

// vong lap qua tat ca ki tu ma nguoi dung nhap vao

for (int nChar = 0; nChar < strlen(szBuffer); nChar++)

{

     // neu kit u cua no bang khoang trang, dem no

     if (szBuffer[nChar] == ” ”)

         nSpacesFound++;

}

cout << “You typed ” << nSpacesFound << ” spaces!” << endl;

std :: string

Vì string được sử dụng nhiều trong chương trình của bạn, nên bạn thường xuyên sử dụng std :: string. Để sử dụng các hàm trong hổ trợ cho string trong C++. Bạn khai báo string header.

Chúng ta xem xét chương trình ngắn dưới đây sử dụng std::string :

#include // khai báo std::string

#include

int main()

{

     using namespace std; // danh cho cả cout and string

     cout << “Enter your name: “;

     string strString;

     cin >> strString;

     cout << “Hello, ” << strString << “!” << endl;

     cout << “Ten cua bạn có : ” << strString.length() <<

” kí tự trong đó” << endl;

     cout << “Ki tu thu 2 la : ” << strString[1] << endl;

     strString = “Dave”;

     cout << “Ten cua ban bay gio la: ” << strString << endl;

     cout << “Goodbye, ” << strString << endl;

     return 0;

}

Một trong những hàm quan trọng trong việc sử dụng std::string là getline(). Hàm này có thể giúp bạn đọc toàn bộ chuổi mà người dùng nhập vào string, thậm chí bao gồm của whitespace :

cout << “Nhap Vao Ten cua ban: “;

string strName;

getline(cin, strName);

cout << “Ban Nhap Vao: “<< strName <

Những chia sẻ trên hi vọng sẽ giúp các bạn hiểu rõ về cách sử dụng chuỗi trong lập trình C/C++.

Đánh giá của bạn

Add Comment