Kí tự và xâu kí tự
Kí tự và bảng mã ASCII
Kí tự
Kí tự là đơn vị cơ bản xuất hiện khắp nơi trong cuộc sống: từ ngôn ngữ viết hằng ngày trong sách, báo, \(\ldots\) đến các cú pháp trong lập trình. Một kí tự có thể là:
- Một chữ cái:
a
,b
,c
,X
,Y
,Z
, \(\ldots\) - Một chữ số:
0
,1
,2
, \(\ldots\),9
- Một kí tự đặc biệt:
?
,!
,~
,_
,@
,\#
, dấu cách, \(\ldots\)
Kiểu dữ liệu char
Để lưu một kí tự trong C++
ta sử dụng kiểu char
.
Cú pháp:
char <tên_biến>;
Ta sử dụng cặp dấu nháy đơn ''
để thể hiện một kí tự kiểu char
trong C++
. Cụ thể, để khai báo biến c
bằng kí tự chữ cái A
, ta viết như sau:
Mã nguồn
char c = 'A';
Ví dụ
Mã nguồn
#include <bits/stdc++.h>
using namespace std;
int main() {
cout << '0' << "\n";
cout << '?' << "\n";
char c = 'A';
cout << c << "\n";
c = 'z';
char a = c;
cout << a;
return 0;
}
Đầu ra
0
?
A
z
Bảng mã ASCII mở rộng
Bảng mã ASCII mở rộng (Extended American Standard Code for Information Interchange) là một bộ mã kí tự nền tảng, được sử dụng để biểu diễn văn bản trong máy tính và các thiết bị truyền thông kĩ thuật số. Bảng mã ASCII mở rộng bao gồm \(256\) kí tự, được đánh số từ \(0\) đến \(255\).

Bảng mã ASCII mở rộng.
Kiểu dữ liệu char
giới hạn trong 256 kí tự của bảng mã ASCII
mở rộng.
Ở bảng mã ASCII
mở rộng có rất nhiều kí tự, tuy nhiên để có thể lập trình hiệu quả, lập trình viên chỉ cần phải nhớ chỉ số trong bảng mã của một số kí tự sau đây:
- Kí tự chữ số
'0'
đến'9'
: Từ \(48\) đến \(57\). - Kí tự chữ cái in hoa
'A'
đến'Z'
: Từ \(65\) đến \(90\). - Kí tự chữ cái in thường
'a'
đến'z'
: Từ \(97\) đến \(122\).
Kí tự điều khiển
Ta đã quen với cách viết xuống dòng như sau:
Mã nguồn
cout << "\n";
Bản chất '\n'
là một kí tự trong bảng mã ASCII
mở rộng (số hiệu 10). Do đó các bạn cũng có thể viết:
Mã nguồn
cout << '\n';
Ngoài '\n'
, một số kí tự điều khiển khác thường gặp là kí tự '\t'
(Kí tự Tab
, số hiệu 9), kí tự '\0'
(Kí tự NULL
, số hiệu 0)
Ép kiểu
Trong lập trình, đôi khi ta cần đổi từ một kiểu dữ liệu này sang một kiểu dữ liệu khác để thuận tiện cho việc xử lí. Kĩ thuật này được gọi là \textbf{ép kiểu}.
Cú pháp:
(<kiểu_cần_ép_sang>) <biểu_thức_cần_ép_kiểu>;
Kiểu kí tự và kiểu số nguyên
Việc ép kiểu được thể hiện rất rõ qua bảng mã ASCII
: từ một kí tự có thể tìm được chỉ số, từ chỉ số có thể tìm ra kí tự.
Ví dụ
Mã nguồn
char c = 'a';
cout << "Ki tu: " << c << " --> Chi so: " << (int)c << '\n';
int x = 90;
cout << "Chi so: " << x << " --> Ki tu: " << (char)x;
Đầu ra
Ki tu: a --> Chi so: 97
Chi so: 90 --> Ki tu: Z
Kiểu số nguyên và kiểu số thực
Một biểu thức kiểu số thực có thể được ép sang kiểu số nguyên, khi đó phần thập phân của biểu thức đó sẽ bị lược bỏ đi.
Ví dụ
Mã nguồn
cout << (int)3.14 << '\n';
double e = 2.71;
cout << (int)e;
Đầu ra
3
2
Ép kiểu bằng cách gán
Một biểu thức có thể được ép kiểu bằng cách gán cho một biến có kiểu dữ liệu khác.
Ví dụ
Mã nguồn
int n = 3.14 * 2.71;
cout << n << '\n';
char c = 97 + n;
cout << c;
Đầu ra
8
i
Phép tính 3.14 * 2.71
có giá trị là \(8.5094\), khi được gán vào biến kiểu số nguyên \(n\) thì được ép kiểu thành số \(8\).
Phép tính 97 + n
có giá trị là \(105\). Khi được gán vào biến kiểu kí tự c
thì c
nhận giá trị là kí tự có chỉ số \(105\) trong bảng mã ASCII
là 'i'
.
Ép kiểu ngầm định
Trong các nội dung ép kiểu được giới thiệu phía trên, các cách ép kiểu sử dụng cú pháp và ép kiểu bằng cách gán được gọi chung là ép kiểu thủ công, khi lập trình viên cần phải tự viết mã nguồn ép kiểu.
Bên cạnh ép kiểu thủ công, tồn tại một phương thức ép kiểu được gọi là ép kiểu tự động. Từ "tự động" ở đây có thể được hiểu rằng trình biên dịch C++
tự động thực hiện việc ép kiểu các biến và các biểu thức mà không cần người lập trình tự viết.
Trước hết, cần xem xét độ rộng trong khoảng giá trị của từng kiểu dữ liệu:
- Kiểu kí tự: Các kí tự có chỉ số từ 0 đến 255.
- Kiểu số nguyên: Các số nguyên.
- Kiểu số thực: Các số thực.
Có thể thấy, theo cách sắp xếp trên, độ rộng của các kiểu dữ liệu tăng dần:
\(\text{Kiểu kí tự} \subset \text{Kiểu số nguyên} \subset \text{Kiểu số thực}\)
Khi thực hiện một phép toán gồm nhiều biểu thức có kiểu dữ liệu khác nhau, C++
tự động ép kiểu tất cả các biểu thức thành kiểu dữ liệu có độ rộng lớn nhất trong biểu thức, sau đó thực hiện tính toán.
Ví dụ
Mã nguồn
cpp
cout << 5 / 2 << '\n';
cout << 5 / 2.0 << '\n';
cout << 'A' + 9 << '\n';
cout << ('a' + 20) * 2.5;
!!! primary "Đầu ra"
cpp
2
2.5
74
292.5
Giải thích các biểu thức:
5 / 2
: Cả hai số đều là số nguyên. Phép chia hai số nguyên trả về một số nguyên.5 / 2.0
: Kiểu dữ liệu có độ rộng lớn nhất là kiểu số thực. Số nguyên \(5\) được ép kiểu về kiểu số thực, phép chia hai số thực trả về một số thực.'A' + 9
: Kiểu dữ liệu có độ rộng lớn nhất là kiểu số nguyên. Kí tự'A'
được ép kiểu về giá trị nguyên là \(65\).'A' + 9 = 65 + 9 = 74
.('a' + 20) * 2.5
: Kiểu dữ liệu có độ rộng lớn nhất là kiểu số thực. Kí tự'a'
được ép về kiểu số thực là \(97.0\). Số nguyên \(20\) được ép kiểu về kiểu số thực là \(20.0\).(97.0 + 20.0) * 2.5 = 292.5
.
Xâu kí tự
Khái niệm
Xâu kí tự (hay còn gọi là chuỗi kí tự) là một dãy các kí tự. Trong C++
, một xâu được biểu diễn bằng cặp dấu ngoặc kép ("")
.
Ví dụ
"HNCode"
, "abc@example.com"
, "f\n"
, \(\ldots\)
Câu lệnh cout
thực chất đang in một xâu kí tự ra màn hình.
Số lượng kí tự trong một xâu được gọi là độ dài của xâu. Trong một số tài liệu hoặc bài tập lập trình, người viết có thể kí hiệu độ dài của xâu S
là |S|
.
Xâu ""
không chứa một kí tự nào được gọi là một xâu rỗng. Xâu rỗng có độ dài bằng \(0\).
Khởi tạo xâu kí tự
Trong C++
, string
là kiểu dữ liệu dùng để lưu trữ một xâu kí tự.
Cú pháp:
string <tên_biến>;
Ví dụ
Mã nguồn
string a;
string b = "HNCode";
Nếu không khởi tạo giá trị cho một xâu, xâu đó có giá trị mặc định là một xâu rỗng.
Truy cập kí tự trong xâu
Việc truy cập các phần tử được thực hiện thông qua chỉ số của từng kí tự, giống như trong mảng. Xâu bắt đầu từ chỉ số 0, vì vậy kí tự đầu tiên trong xâu sẽ có chỉ số 0, kí tự thứ hai có chỉ số \(1\), và cứ thế tiếp tục. Việc truy cập các phần tử trong xâu có thể giúp chúng ta thực hiện nhiều thao tác như in ra kí tự tại vị trí nào đó, thay đổi giá trị của kí tự đó, hoặc thực hiện các phép toán trên từng kí tự trong xâu.
Ví dụ
In ra phần tử có chỉ số 3
trong xâu s
, gọi s[3]
Ví dụ
Mã nguồn
#include <bits/stdc++.h>
using namespace std;
int main() {
string s = "HNCode";
for (int i = 0; i < 6; i++) {
cout << s[i] << " ";
}
return 0;
}
Đầu ra
H N C o d e
Nhập xâu kí tự
Ta có thể dùng lệnh cin
để nhập vào một xâu kí tự từ bàn phím.
Ví dụ 1
Chương trình nhập vào tên người dùng và in ra lời chào.
!!! primary "Mã nguồn"
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
cout << "Hello, " << s << "!";
return 0;
}
!!! primary "Đầu vào"
Duy
!!! primary "Đầu ra"
Hello, Duy!
Tuy nhiên, khi thử nhập tên đầy đủ như "Nguyen Van A" vào chương trình trên, nó lại chỉ in ra "Hello, Nguyen!". Điều này là do lệnh cin
sẽ kết thúc đọc dữ liệu vào biến khi gặp một khoảng trắng như dấu cách, dấu xuống dòng Enter
,\ldots
Để đọc đầy đủ toàn bộ kí tự trên một dòng bao gồm cả dấu cách, các bạn cần sử dụng lệnh getline
với cú pháp như sau:
getline(cin, <tên_biến>);
Khi đó ví dụ trên cần sửa như sau để đọc toàn bộ tên đầy đủ:
Ví dụ 2
Mã nguồn
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
getline(cin, s);
cout << "Hello, " << s << "!";
return 0;
}
Đầu vào
Nguyen Van A
Đầu ra
Hello, Nguyen Van A!
Thao tác xử lí trên xâu
Hàm s.size()
hoặc s.length()
được sử dụng để lấy độ dài xâu s
.
Ví dụ 1
Mã nguồn
string s = "HNCode";
cout << s.size();
Đầu ra
6
Toán tử +
được sử dụng để ghép hai xâu với nhau.
Ví dụ 2
Mã nguồn
string s = "HN" + "Code";
cout << s;
Đầu ra
HNCode
Toán tử +=
được sử dụng để thêm một kí tự hoặc một xâu vào cuối một xâu.
Ví dụ 3
Mã nguồn
string S = "HN";
S += "Code";
cout << S << '\n';
S += '!';
cout << S;
Đầu ra
HNCode
HNCode!
Các toán tử so sánh >
, >=
, <
,... cũng có thể so sánh hai xâu với nhau. Chúng được so sánh dựa trên thứ tự từ điển.
Ví dụ 4
Mã nguồn
cout << ("Hoang" < "Tung");
Đầu ra
1