Đến thời điểm này, các kiểu dữ liệu cơ bản mà chúng ta đã tìm hiểu để sử dụng cho việc giữ các số (số nguyên và dấu phẩy động) hoặc giá trị đúng / sai (booleans). Nhưng nếu chúng ta muốn lưu trữ chữ thì sao? Kiểu dữ liệu char được thiết kế cho mục đích như vậy.

Kiểu dữ liệu char là một kiểu tích phân, có nghĩa là giá trị cơ bản được lưu trữ dưới dạng một số nguyên và nó được đảm bảo có kích thước 1 byte. Tuy nhiên, tương tự như cách giá trị boolean được hiểu là true hay false, giá trị char được hiểu là ký tự ASCII.

ASCII là viết tắt của Code tiêu chuẩn của Mỹ để trao đổi thông tin và nó định nghĩa một cách cụ thể để biểu thị các ký tự tiếng Anh (cộng với một vài ký hiệu khác) là các số từ 0 đến 127 (được gọi là code ASCII). Ví dụ, code ASCII 97 được hiểu là ký tự ‘a.

Ký tự char luôn được đặt giữa các dấu nhấy đơn.

Ở đây, một bảng đầy đủ các ký tự ASCII:

CodeSymbolCodeSymbolCodeSymbolCodeSymbol
0NUL (null)32(space)64@96`
1SOH (start of header)33!65A97a
2STX (start of text)3466B98b
3ETX (end of text)35#67C99c
4EOT (end of transmission)36$68D100d
5ENQ (enquiry)37%69E101e
6ACK (acknowledge)38&70F102f
7BEL (bell)3971G103g
8BS (backspace)40(72H104h
9HT (horizontal tab)41)73I105i
10LF (line feed/new line)42*74J106j
11VT (vertical tab)43+75K107k
12FF (form feed / new page)44,76L108l
13CR (carriage return)4577M109m
14SO (shift out)46.78N110n
15SI (shift in)47/79O111o
16DLE (data link escape)48080P112p
17DC1 (data control 1)49181Q113q
18DC2 (data control 2)50282R114r
19DC3 (data control 3)51383S115s
20DC4 (data control 4)52484T116t
21NAK (negative acknowledge)53585U117u
22SYN (synchronous idle)54686V118v
23ETB (end of transmission block)55787W119w
24CAN (cancel)56888X120x
25EM (end of medium)57989Y121y
26SUB (substitute)58:90Z122z
27ESC (escape)59;91[123{
28FS (file separator)60<92\124|
29GS (group separator)61=93]125}
30RS (record separator)62>94^126~
31US (unit separator)63?95_127DEL (delete)

Code 0-31 được gọi là ký tự không thể in được và chúng chủ yếu được sử dụng để thực hiện định dạng và điều khiển máy in. Hầu hết trong số này đã lỗi thời.

Code 32-127 được gọi là các ký tự có thể in được và chúng đại diện cho các chữ cái, ký tự số và dấu chấm câu mà hầu hết các máy tính sử dụng để hiển thị văn bản tiếng Anh cơ bản.

1. Khởi tạo ký tự

Bạn có thể khởi tạo các biến char bằng cách sử dụng các ký tự:

char ch2{ 'a' }; // initialize with code point for 'a' (stored as integer 97) (preferred)

Bạn cũng có thể khởi tạo ký tự bằng số nguyên, nhưng điều này nên tránh nếu có thể

char ch1{ 97 }; // initialize with integer 97 ('a') (not preferred)


Cẩn thận không trộn lẫn số ký tự với số nguyên. Hai khởi tạo sau không giống nhau:

char ch{5}; // initialize with integer 5 (stored as integer 5)
char ch{'5'}; // initialize with code point for '5' (stored as integer 53)

Số dưới dạng ký tự sẽ được sử dụng khi chúng ta muốn biểu diễn số dưới dạng văn bản, thay vì số để áp dụng các phép toán.

in ký tự

Khi sử dụng std :: cout để in char, std :: cout xuất ra biến char dưới dạng ký tự ASCII:

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

#include <iostream>
 
int main()
{
    char ch1{ 'a' }; // (preferred)
    std::cout << ch1; // cout prints a character
 
    char ch2{ 98 }; // code point for 'b' (not preferred)
    std::cout << ch2; // cout prints a character
 
 
    return 0;
}

Điều này tạo ra kết quả:

ab

Chúng ta cũng có thể xuất chữ char trực tiếp:

cout << 'c';

Điều này tạo ra kết quả:

c

Số nguyên chiều rộng cố định int8_t thường được xử lý giống như một char trong C ++, do đó, nó thường sẽ in dưới dạng char thay vì số nguyên.

2. In ký tự dưới dạng số nguyên thông qua static_cast

Nếu chúng ta muốn xuất một char dưới dạng một số thay vì một ký tự, chúng ta phải nói với std :: cout để in char như thể nó là một số nguyên. Một cách để làm điều này là gán char cho một số nguyên và in số nguyên:

#include <iostream>
 
int main()
{
    char ch{97};
    int i(ch); // assign the value of ch to an integer
    std::cout << i; // print the integer value
    return 0;
}

Tuy nhiên, điều này là khó khăn. Một cách tốt hơn là sử dụng một kiểu cast. Một cast sẽ tạo ra một giá trị cho một kiểu nào đó từ một giá trị của kiểu khác. Để chuyển đổi giữa các kiểu dữ liệu cơ bản (ví dụ: từ char thành int hoặc ngược lại), chúng ta sử dụng static_cast.

Cú pháp cho cast như sau:

static_cast<new_type>(expression)

static_cast lấy giá trị từ một biểu thức làm đầu vào và chuyển đổi nó thành bất kỳ loại cơ bản nào new_type đại diện (ví dụ: int, bool, char, double).

Ở đây, sử dụng static_cast để tạo giá trị nguyên từ giá trị char của chúng ta:

#include <iostream>
 
int main()
{
    char ch{ 'a' };
    std::cout << ch << '\n';
    std::cout << static_cast<int>(ch) << '\n';
    std::cout << ch << '\n';
    return 0;
}

Kết quả này trong:

a
97
a

Điều quan trọng cần lưu ý là tham số tới static_cast đánh giá là một biểu thức. Khi chúng ta truyền vào một biến, biến đó được ước tính để tạo ra giá trị của nó, sau đó được chuyển đổi sang kiểu mới. Biến không bị ảnh hưởng bằng cách chuyển giá trị của nó sang kiểu mới. Trong trường hợp trên, biến ch vẫn là char và vẫn giữ nguyên giá trị.

Cũng lưu ý rằng việc static_cast không thực hiện bất kỳ kiểm tra phạm vi(độ lớn), vì vậy nếu bạn truyền một số nguyên lớn vào một char, bạn sẽ tràn kiểu char của mình.

Chúng ta sẽ nói nhiều hơn về các static_cast và các kiểu khác nhau trong một bài học trong tương lai.

3. Nhập ký tự

Chương trình sau đây yêu cầu người dùng nhập một ký tự, sau đó in ra cả ký tự và code ASCII của nó:

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

#include <iostream>
 
int main()
{
    std::cout << "Input a keyboard character: ";
 
    char ch{};
    std::cin >> ch;
    std::cout << ch << " has ASCII code " << static_cast<int>(ch) << '\n';
 
    return 0;
}

Đây là đầu ra từ một lần chạy:

Input a keyboard character: q
q has ASCII code 113

Lưu ý rằng std :: cin sẽ cho phép bạn nhập nhiều ký tự. Tuy nhiên, biến ch chỉ có thể chứa 1 ký tự. Do đó, chỉ có ký tự đầu vào đầu tiên được trích xuất thành biến ch. Phần còn lại của đầu vào người dùng được để lại trong bộ đệm đầu vào mà std :: cin sử dụng và có thể được trích xuất bằng các lệnh gọi tiếp theo đến std :: cin.

Bạn có thể thấy hành vi này trong ví dụ sau:

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

#include <iostream>
 
int main()
{
    std::cout << "Input a keyboard character: "; // assume the user enters "abcd" (without quotes)
 
    char ch{};
    std::cin >> ch; // ch = 'a', "bcd" is left queued.
    std::cout << ch << " has ASCII code " << static_cast<int>(ch) << '\n';
 
    // Note: The following cin doesn't ask the user for input, it grabs queued input!
    std::cin >> ch; // ch = 'b', "cd" is left queued.
    std::cout << ch << " has ASCII code " << static_cast<int>(ch) << '\n';
    
    return 0;
}
Input a keyboard character: abcd
a has ASCII code 97
b has ASCII code 98

4. Kích thước Char, phạm vi và dấu hiệu mặc định

Char được định nghĩa bởi C ++ để luôn có kích thước 1 byte. Theo mặc định, một char có thể được có dấu hoặc không dấu (mặc dù nó thường được có dấu). Nếu bạn sử dụng ký tự để giữ các ký tự ASCII, bạn không cần chỉ định một ký hiệu (vì cả hai ký tự có ký hiệu và không dấu có thể giữ các giá trị trong khoảng từ 0 đến 127).

Nếu bạn sử dụng char để giữ các số nguyên nhỏ (điều bạn không nên làm trừ khi bạn tối ưu hóa rõ ràng cho không gian), bạn phải luôn chỉ định xem nó có dấu hay không dấu. Một char có dấunhân vật có thể giữ một số trong khoảng từ -128 đến 127. Một char không dấu có thể giữ một số trong khoảng từ 0 đến 255.

5. Trình tự thoát khỏi một dòng nào đó

Có một số ký tự trong C ++ có ý nghĩa đặc biệt. Những ký tự này được gọi là trình tự thoát. Một chuỗi thoát bắt đầu bằng một ký tự ‘\ (dấu gạch chéo ngược) và sau đó là một chữ cái hoặc số sau đây.

Bạn đã thấy trình tự thoát phổ biến nhất: ‘\ n, có thể được sử dụng để nhúng một dòng mới trong một chuỗi văn bản:

#include <iostream>
 
int main()
{
    std::cout << "First line\nSecond line\n";
    return 0;
}

Kết quả này:

First line
Second line

Một chuỗi thoát thường được sử dụng khác là ‘\ t, trong đó nhúng một tab ngang:

#include <iostream>
 
int main()
{
    std::cout << "First part\tSecond part";
    return 0;
}

Đầu ra nào:

First part        Second part

Ba chuỗi thoát đáng chú ý khác là:
\ In in một trích dẫn
\ ‘. In một trích dẫn kép
\\ In dấu gạch chéo ngược

Ở đây, một bảng của tất cả các chuỗi để giúp chúng ta thoát trong 1 line:

NameSymbolÝ nghĩa
Alert\aTạo ra một cảnh báo, chẳng hạn như tiếng bíp
Backspace\bDi chuyển con trỏ trở lại một khoảng trắng
Formfeed\fDi chuyển con trỏ đến trang logic tiếp theo
Newline\nDi chuyển con trỏ đến dòng tiếp theo
Carriage return\rDi chuyển con trỏ đến đầu dòng
Horizontal tab\tIn một tab ngang
Vertical tab\vIn một tab dọc
Single quote\’In một trích dẫn
Double quote\”In một trích dẫn kép
Backslash\\In dấu gạch chéo ngược.
Question mark\?In một dấu hỏi.
Octal number\(number)Dịch sang char từ số bát phân
Hex number\x(number)Dịch sang char từ số hex

Dưới đây là một số ví dụ:

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

#include <iostream>
 
int main()
{
    std::cout << "\"This is quoted text\"\n";
    std::cout << "This string contains a single backslash \\\n";
    std::cout << "6F in hex is char '\x6F'\n";
    return 0;
}

Bản in

"This is quoted text"
This string contains a single backslash \
6F in hex is char 'o'

6. Dòng mới (\ n) với std :: endl

Chúng ta đã tìm hiểu tại bài Giới thiệu về iostream: cout, cin và endl.

7. Điều khác biệt giữa việc đặt ký hiệu trong dấu ngoặc đơn hay dấu ngoặc kép

Các ký tự độc lập luôn được đặt trong các trích dẫn đơn (ví dụ: ’a’,’+’, ‘5’). Một char chỉ có thể đại diện cho một ký hiệu (ví dụ: chữ a, ký hiệu cộng, số 5). Ví dụ sau đây là sai:

char ch('56'); // a char can only hold one symbol

Văn bản đặt giữa hai dấu ngoặc kép (ví dụ: “Hello, world!”) được gọi là một chuỗi. Chuỗi là một tập hợp các ký tự liên tiếp (và do đó, một chuỗi có thể chứa nhiều ký hiệu).

Hiện tại, bạn có thể sử dụng chuỗi ký tự trong code của mình:

std::cout << "Hello, world!"; // "Hello, world!" is a string literal

Tuy nhiên, các chuỗi không phải là kiểu dữ liệu cơ bản trong C ++ và nó phức tạp hơn một chút, vì vậy chúng ta sẽ bảo lưu thảo luận về các kiểu dữ liệu đó cho đến khi chúng tôi đề cập đến các kiểu dữ liệu ghép.

Luôn đặt các ký tự độc lập trong các dấu ngoặc đơn. Điều này giúp trình biên dịch tối ưu hóa hiệu quả hơn.

8. Còn các loại char khác, wchar_t, char16_t và char32_t thì sao?

Nên tránh sử dụng wchar_t trong hầu hết các trường hợp (trừ khi giao tiếp với API Windows). Kích thước của nó được xác định, và không đáng tin cậy. Nó phần lớn đã bị phản đối khi dùng.

Giống như ASCII ánh xạ các số nguyên 0-127 sang các ký tự tiếng US, các tiêu chuẩn code hóa ký tự khác tồn tại để ánh xạ các số nguyên (có kích thước khác nhau) sang các ký tự trong các ngôn ngữ khác. Ánh xạ nổi tiếng nhất bên ngoài ASCII là tiêu chuẩn Unicode, ánh xạ hơn 110.000 số nguyên sang các ký tự trong nhiều ngôn ngữ khác nhau. Vì Unicode chứa rất nhiều điểm code, một điểm code Unicode duy nhất cần 32 bit để thể hiện một ký tự (được gọi là UTF-32). Tuy nhiên, các ký tự Unicode cũng có thể được mã hóa bằng nhiều ký tự 16 bit hoặc 8 bit (được gọi là UTF-16 và UTF-8 tương ứng).

char16_t và char32_t đã được thêm vào C ++ 11 để cung cấp hỗ trợ rõ ràng cho các ký tự Unicode 16 bit và 32 bit. char8_t đã được thêm vào trong C ++ 20.

Bạn có nhu cầu sử dụng char8_t, char16_t hoặc char32_t trừ khi bạn có kế hoạch làm một chương trình có liên quan tới Unicode. Unicode và ngôn ngữ bản địa nói chung nằm ngoài phạm vi của các hướng dẫn này, vì vậy chúng ta sẽ tìm hiểu trong phần tiếp theo.

Trong khi đó, bạn chỉ nên sử dụng các ký tự ASCII khi làm việc với các ký tự (và chuỗi). Sử dụng các ký tự từ các bộ ký tự khác có thể khiến các ký tự của bạn hiển thị không chính xác.

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!