Xem thêm

Bài 10: Xâu kí tự

Huy Erick
Bảng kí tự ASCII ASCII - tên đầy đủ là American Standard Code for Information Interchange - là một bảng mã chuẩn trao đổi thông tin Hoa Kỳ, bao gồm các kí tự và mã...

Bảng kí tự ASCII

ASCII - tên đầy đủ là American Standard Code for Information Interchange - là một bảng mã chuẩn trao đổi thông tin Hoa Kỳ, bao gồm các kí tự và mã của chúng dựa trên bảng chữ cái Latin được dùng trong tiếng Anh hiện đại. Bảng mã này bao gồm 256 kí tự được đánh số hiệu thập phân từ 0 tới 255, thường được dùng để hiển thị văn bản trong máy tính và các thiết bị thông tin khác. Các kí tự mà chúng ta sử dụng trong lập trình đều nằm trong bảng mã này. Để làm việc dễ dàng trên máy tính, mỗi kí tự đều được mã hóa bởi những bit nhị phân 0 và 1 và quy đổi ra giá trị thập phân tương ứng để người dùng dễ thao tác hơn. Ví dụ, kí tự A có số hiệu thập phân là 65, kí tự z có số hiệu là 122,...

Trong bảng mã ASCII có những kí tự in được và không in được. Trong chương này, chúng ta sẽ làm việc với các kí tự in được, nhiều nhất là các kí tự chữ cái và chữ số. Nếu muốn tìm hiểu kĩ hơn về bảng mã ASCII đầy đủ, bạn đọc có thể truy cập vào đường link sau: https://vi.wikipedia.org/wiki/ASCII

Kí tự và xâu kí tự

Trong máy tính, thông tin được biểu diễn ở dạng số và dạng phi số. Chúng ta đã quá quen thuộc với thông tin dạng số, vậy còn dạng phi số? Đó là văn bản, hình ảnh, âm thanh,...Đối với lập trình thi đấu, thông tin dạng văn bản cũng xuất hiện thường xuyên không kém dạng số, và các ngôn ngữ lập trình đều cung cấp những kiểu dữ liệu để lưu trữ thông tin dạng văn bản. Có hai loại dữ liệu dạng văn bản thường gặp nhất là kiểu kí tự và kiểu xâu kí tự (nhiều kí tự ghép lại với nhau).

Đối với kiểu kí tự, chúng ta có kiểu dữ liệu char để biểu diễn, còn xâu kí tự thì có hai cách khác nhau:

  • Sử dụng một mảng gồm nhiều phần tử kiểu char.
  • Sử dụng thư viện con <string> đã được xây dựng sẵn trong C++. Cách này được ưa chuộng hơn vì thao tác dữ liệu tốt hơn.

Thư viện chuẩn của C++ cung cấp cho chúng ta một thư viện con <string> hỗ trợ việc lưu trữ các xâu kí tự (xâu kí tự) và rất nhiều các phương thức xử lý đi kèm.

1. Khai báo và truy cập các phần tử xâu

Để khai báo một xâu sử dụng thư viện <string>, đầu tiên ta cần khai báo thư viện và không gian tên chứa nó bằng cú pháp:

#include <string>
using namespace std;

Sau đó, khai báo một xâu bằng cú pháp:

string {Tên_xâu};

Vẫn như thường lệ, {Tên_xâu} là một định danh do người dùng đặt ra, miễn là không trùng với từ khóa của hệ thống. Ta không cần khai báo độ dài của xâu, mà mỗi khi thêm một kí tự vào thì string sẽ tự động điều chỉnh độ dài của xâu cho vừa khớp với số lượng kí tự. Khi khai báo xâu, mặc định xâu đó sẽ là xâu rỗng (không có kí tự nào).

Các kí tự trong xâu sẽ được đánh số từ 0. Để truy cập một vị trí trong xâu (với điều kiện vị trí đó hiện đang có kí tự hoặc đã được khởi tạo), ta dùng cú pháp:

{Tên_xâu}[{Vị_trí}]

Khá giống với mảng đúng không nào! Sau khi truy cập, mỗi vị trí trong xâu có thể được thao tác giống như một kí tự và kết hợp với các câu lệnh cũng như toán tử. Ví dụ, gán một biến c bằng kí tự ở vị trí số 2 của xâu s bằng cú pháp:

char c = s[2];

2. Cách nhập xuất một xâu

2.1. Nhập xuất các biến kiểu <string>

Khi nhập xuất một biến xâu kí tự, ta có thể coi xâu đó như một biến đơn và sử dụng hai câu lệnh cincout để nhập xuất. Cú pháp như sau:

cin >> {Tên_biến_xâu}; // Nhập vào một biến xâu.
cout << {Tên_biến_xâu}; // Viết ra một biến xâu.

Tuy nhiên, có một lưu ý khi sử dụng lệnh cin đối với string, đó là nếu như trong quá trình nhập liệu gặp phải dấu cách, thì việc nhập sẽ bị ngắt tại đó, cho dù người dùng có nhập thêm bao nhiêu kí tự đi chăng nữa thì xâu cũng sẽ chỉ lưu trữ phần ở phía trước dấu cách mà thôi. Cùng xem ví dụ dưới đây:

#include <iostream>
#include <string>
using namespace std;
int main() {
  string name;
  cin >> name;
  cout << "Tên vừa nhập là: " << name;
  return 0;
}

Nếu người dùng nhập vào một tên là "Vũ Quế Lâm", thì khi chạy chương trình ta sẽ thu được kết quả này:

Tên vừa nhập là: Vũ

Do đó, trong trường hợp cần đọc vào một xâu có cả dấu cách, ta sẽ sử dụng kết họp hai cú pháp:

getline(cin, {Tên_xâu});

Lệnh getline() sẽ thu nhận cả dòng dữ liệu nhập vào, bao gồm cả những dấu cách. Nó sẽ dừng việc đọc lại khi gặp kí tự \n - tức là kí tự xuống dòng:

#include <iostream>
#include <string>
using namespace std;
int main() {
  string name;
  getline(cin, name);
  cout << "Tên vừa nhập là: " << name;
  return 0;
}

Lúc này, với tên nhập vào là "Vũ Quế Lâm", chạy chương trình sẽ thu được kết quả chính xác:

Tên vừa nhập là: Vũ Quế Lâm

2.2. Nhập nhiều xâu kí tự hoặc chuyển đổi từ nhập số sang nhập xâu bằng getline()

Nếu như chúng ta chỉ nhập một xâu kí tự duy nhất, thì sẽ không có điều gì đáng lưu tâm cả, bạn chỉ cần lựa chọn giữa cingetline(cin) tùy vào việc xâu bạn nhập vào có dấu cách hay không. Tuy nhiên, khi dữ liệu đầu vào có nhiều xâu kí tự khác nhau, hoặc khi dữ liệu đầu vào bao gồm cả số và xâu, thì câu chuyện sẽ khác đi. Về bản chất, khi các bạn nhập bất cứ thứ gì vào từ bàn phím, chúng sẽ được đẩy vào bộ nhớ đệm, rồi hàm cin sẽ "đọc" dữ liệu ra từ bộ nhớ đệm rồi nạp vào biến.

Chẳng hạn, nếu như các bạn nhập vào một số là 123, rồi ấn phím Enter (chính là kí tự xuống dòng), thì 123 và kí tự \n sẽ được đẩy vào bộ nhớ đệm trước, sau đó hàm cin mới "quét qua" dữ liệu trong bộ nhớ đệm và đưa nó vào biến phía sau. Trong trường hợp biến phía sau là một biến kiểu số, thì chỉ có các chữ số mới được ghi nhận vào biến, còn những kí tự như \n sẽ bị bỏ qua, nhờ đó nên trong trường hợp đọc nhiều số khác nhau, chương trình vẫn sẽ phân tách đúng các số, dù các bạn dùng dấu cách hay dấu xuống dòng. Tuy nhiên, nếu như theo sau số nhập vào là một kí tự, hoặc một xâu kí tự, thì nó sẽ đọc được cả kí tự \n (vì kí tự xuống dòng chỉ bị bỏ qua chứ nó vẫn còn tồn tại trong bộ nhớ đệm), dẫn đến xâu kí tự sẽ bị đọc sai.

1