Trong lập trình, một hằng số là một giá trị cố định không thể thay đổi. C ++ có hai loại hằng số: hằng số theo nghĩa đen và hằng số tượng trưng. Cafedev sẽ đề cập đến các hằng chữ trong bài học này và hằng số tượng trưng trong bài học tiếp theo.

Hằng số nghĩa đen (thường chỉ được gọi là các ký tự) là các giá trị được chèn trực tiếp vào code. Ví dụ:

return 5; // 5 is an integer literal
bool myNameIsAlex { true }; // true is a boolean literal
std::cout << 3.4; // 3.4 is a double literal

Chúng là hằng số vì các giá trị của chúng không thể thay đổi động (bạn phải thay đổi chúng, sau đó biên dịch lại để thay đổi có hiệu lực).

Giống như các đối tượng có một kiểu, tất cả các chữ đều có một kiểu dữ liệu. Kiểu của một chữ được giả định từ giá trị và định dạng của chính chữ đó.

Theo mặc định:

Giá trị ký tự chữVí dụKiểu dữ liệu
Giá trị số nguyên5, 0, -3int
Giá trị booleantrue, falsebool
Giá trị floating point3.4, -2.2double (not float)!
Giá trị char‘a’char
C-style string“Hello, world!”const char[14]

1. Hậu tố của ký tự chữ(gọi tắc là ký tự)

Nếu kiểu ký tự mặc định không như mong muốn, bạn có thể thay đổi kiểu của ký tự bằng cách thêm hậu tố:

Kiểu dữ liệuhậu tốý nghĩa
intu or Uunsigned int
intl or Llong
intul, uL, Ul, UL, lu, lU, Lu, or LUunsigned long
intll or LLlong long
intull, uLL, Ull, ULL, llu, llU, LLu, or LLUunsigned long long
doublef or Ffloat
doublel or Llong double

Bạn thường không cần sử dụng hậu tố cho các kiểu số nguyên, nhưng đây là các ví dụ:

unsigned int value1 { 5u }; // 5 has type unsigned int
long value2 { 6L }; // 6 has type long

Theo mặc định, hằng số ký tự dấu chấm động có kiểu kép. Thay vào đó, để làm cho chúng nổi các ký tự, hậu tố f (hoặc F) nên được sử dụng:

float f { 5.0f }; // 5.0 has type float

Các lập trình viên mới thường bối rối về lý do tại sao những điều sau đây không hoạt động như mong đợi:

float f { 4.1 }; // warning: 4.1 is a double literal, not a float literal

Vì 4.1 không có hậu tố nên nó được coi là một ký tự kép, không phải một ký tự float. Khi C ++ xác định kiểu của một ký tự, nó không quan tâm bạn đang làm gì với ký tự (ví dụ: trong trường hợp này, sử dụng nó để khởi tạo một biến float). Do đó, 4.1 phải được chuyển đổi từ double sang float trước khi nó có thể được gán cho biến f, và điều này có thể dẫn đến mất độ chính xác.

Chữ ký tự có thể sử dụng trong code C ++ miễn là nghĩa của chúng rõ ràng. Điều này thường xảy ra nhất khi được sử dụng để khởi tạo hoặc gán giá trị cho một biến, làm toán hoặc in một số văn bản ra màn hình.

2. Chuỗi ký tự

Trong bài – Chars, chúng ta đã định nghĩa một chuỗi là một tập hợp các ký tự tuần tự. C ++ hỗ trợ chuỗi ký tự:

std::cout << "Hello, world!"; // "Hello, world!" is a C-style string literal
std::cout << "Hello," " world!"; // C++ will concatenate sequential string literals

Các ký tự chuỗi được xử lý rất kỳ lạ trong C ++ vì lý do lịch sử. Hiện tại, bạn có thể sử dụng chuỗi ký tự để in văn bản với std :: cout, nhưng đừng thử và gán chúng cho các biến hoặc chuyển chúng cho các hàm – nó sẽ không hoạt động hoặc sẽ không hoạt động như bạn  mong đợi. Chúng ta sẽ nói thêm về chuỗi kiểu C (và cách giải quyết tất cả những vấn đề kỳ quặc đó) trong các bài học trong tương lai.

3. Kí hiệu khoa học cho các ký tự dấu phẩy động

Có hai cách khác nhau để khai báo các ký tự dấu phẩy động:

double pi { 3.14159 }; // 3.14159 is a double literal in standard notation
double avogadro { 6.02e23 }; // 6.02 x 10^23 is a double literal in scientific notation

Ở dạng thứ hai, số sau số mũ có thể là số âm:

double electron { 1.6e-19 }; // charge on an electron is 1.6 x 10^-19

Chữ bát phân và chữ thập lục phân

Trong cuộc sống hàng ngày, chúng ta đếm bằng cách sử dụng số thập phân, trong đó mỗi chữ số có thể là 0, 1, 2, 3, 4, 5, 6, 7, 8 hoặc 9. Số thập phân còn được gọi là “cơ số 10”, bởi vì có 10 các chữ số có thể có (0 đến 9). Trong hệ thống này, chúng ta đếm như sau: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,… Theo mặc định, các số trong chương trình C ++ được giả định là số thập phân.

int x { 12 }; // 12 is assumed to be a decimal number

Trong hệ nhị phân, chỉ có 2 chữ số: 0 và 1, vì vậy nó được gọi là “cơ số 2”. Trong hệ nhị phân, chúng ta đếm như sau: 0, 1, 10, 11, 100, 101, 110, 111,…

Có hai “cơ số” khác đôi khi được sử dụng trong máy tính: bát phân và thập lục phân.

Hệ bát phân là cơ số 8 – nghĩa là các chữ số duy nhất có sẵn là: 0, 1, 2, 3, 4, 5, 6 và 7. Trong Hệ bát phân, chúng ta đếm như sau: 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12,… (lưu ý: không có 8 và 9, vì vậy chúng ta bỏ qua từ 7 đến 10).

Decimal01234567891011
Octal0123456710111213

Để sử dụng một chữ bát phân, hãy đặt tiền tố cho chữ của bạn bằng một số 0

#include <iostream>
 
int main()
{
    int x{ 012 }; // 0 before the number means this is octal
    std::cout << x;
    return 0;
}

Chương trình này in:

10

Tại sao 10 thay vì 12? Bởi vì các số được in dưới dạng thập phân, và 12 bát phân = 10 thập phân.

Octal hiếm khi được sử dụng và chúng tôi khuyên bạn nên tránh nó.

Hệ thập lục phân là cơ số 16. Trong hệ thập lục phân, chúng ta đếm như sau: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12 ,…

Decimal01234567891011121314151617
Hexadecimal0123456789ABCDEF1011

Để sử dụng một chữ thập lục phân, hãy đặt tiền tố cho chữ của bạn bằng 0x.

#include <iostream>
 
int main()
{
    int x{ 0xF }; // 0x before the number means this is hexadecimal
    std::cout << x;
    return 0;
}

Chương trình này in:

15

Bởi vì có 16 giá trị khác nhau cho một chữ số thập lục phân, chúng ta có thể nói rằng một chữ số thập lục phân duy nhất bao gồm 4 bit. Do đó, một cặp chữ số thập lục phân có thể được sử dụng để biểu diễn chính xác một byte đầy đủ.

Hãy xem xét một số nguyên 32 bit có giá trị 0011 1010 0111 1111 1001 1000 0010 0110. Do độ dài và sự lặp lại của các chữ số nên điều đó không dễ đọc. Trong hệ thập lục phân, giá trị tương tự này sẽ là: 3A7F 9826. Điều này làm cho các giá trị thập lục phân hữu ích như một cách ngắn gọn để biểu diễn một giá trị trong bộ nhớ. Vì lý do này, các giá trị thập lục phân thường được sử dụng để biểu diễn địa chỉ bộ nhớ hoặc giá trị thô trong bộ nhớ.

Trước C ++ 14, không có cách nào để gán một ký tự nhị phân. Tuy nhiên, các cặp thập lục phân cung cấp cho chúng ta một giải pháp hữu ích:

/*
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
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/

#include <iostream>
 
int main()
{
    int bin{};
    bin = 0x01; // assign binary 0000 0001 to the variable
    bin = 0x02; // assign binary 0000 0010 to the variable
    bin = 0x04; // assign binary 0000 0100 to the variable
    bin = 0x08; // assign binary 0000 1000 to the variable
    bin = 0x10; // assign binary 0001 0000 to the variable
    bin = 0x20; // assign binary 0010 0000 to the variable
    bin = 0x40; // assign binary 0100 0000 to the variable
    bin = 0x80; // assign binary 1000 0000 to the variable
    bin = 0xFF; // assign binary 1111 1111 to the variable
    bin = 0xB3; // assign binary 1011 0011 to the variable
    bin = 0xF770; // assign binary 1111 0111 0111 0000 to the variable
 
    return 0;
}

4. C ++ 14 ký tự nhị phân và dấu phân tách chữ số

Trong C ++ 14, chúng ta có thể gán các ký tự nhị phân bằng cách sử dụng tiền tố 0b:

#include <iostream>
 
int main()
{
    int bin{};
    bin = 0b1;  // assign binary 0000 0001 to the variable
    bin = 0b11; // assign binary 0000 0011 to the variable
    bin = 0b1010; // assign binary 0000 1010 to the variable
    bin = 0b11110000; // assign binary 1111 0000 to the variable
 
    return 0;
}

Vì các ký tự dài có thể khó đọc, C ++ 14 cũng bổ sung khả năng sử dụng dấu ngoặc kép (‘) làm dấu phân tách chữ số.

#include <iostream>
 
int main()
{
    int bin{ 0b1011'0010 };  // assign binary 1011 0010 to the variable
    long value{ 2'132'673'462 }; // much easier to read than 2132673462
 
    return 0;
}

Nếu trình biên dịch của bạn không tương thích với C ++ 14, trình biên dịch của bạn sẽ khiếu nại nếu bạn cố gắng sử dụng một trong hai.

In số thập phân, bát phân, thập lục phân và số nhị phân

Theo mặc định, C ++ in giá trị ở dạng thập phân. Tuy nhiên, bạn có thể yêu cầu nó in ở các định dạng khác. Dễ dàng in ở dạng thập phân, bát phân hoặc hex bằng cách sử dụng std :: dec, std :: oct và std :: hex:

#include <iostream>
 
int main()
{
    int x { 12 };
    std::cout << x << '\n'; // decimal (by default)
    std::cout << std::hex << x << '\n'; // hexadecimal
    std::cout << x << '\n'; // now hexadecimal
    std::cout << std::oct << x << '\n'; // octal
    std::cout << std::dec << x << '\n'; // return to decimal
    std::cout << x << '\n'; // decimal
 
    return 0;

Bản in này:

12
c
c
14
12
12

In ở dạng nhị phân khó hơn một chút vì std :: cout không được tích hợp sẵn khả năng này. May mắn thay, thư viện chuẩn C ++ bao gồm một kiểu gọi là std :: bitset sẽ thực hiện việc này cho chúng ta (trong phần tiêu đề <bitset>). Để sử dụng std :: bitset, chúng ta có thể xác định một biến std :: bitset và cho std :: bitset biết chúng ta muốn lưu trữ bao nhiêu bit. Số lượng bit phải là một hằng số thời gian biên dịch. std :: bitset có thể được khởi tạo bằng giá trị tích phân không dấu (ở bất kỳ định dạng nào, bao gồm thập phân, bát phân, hex hoặc nhị phân).

#include <bitset> // for std::bitset
#include <iostream>
 
int main()
{
	// std::bitset<8> means we want to store 8 bits
	std::bitset<8> bin1{ 0b1100'0101 }; // binary literal for binary 1100 0101
	std::bitset<8> bin2{ 0xC5 }; // hexadecimal literal for binary 1100 0101
 
	std::cout << bin1 << ' ' << bin2 << '\n';
	std::cout << std::bitset<4>{ 0b1010 } << '\n'; // we can also print from std::bitset directly
 
	return 0;
}

Bản in này:

11000101 11000101

1010

Chúng ta cũng có thể tạo std :: bitset tạm thời (ẩn danh) để in một giá trị duy nhất. Trong đoạn code trên, dòng này:

std::cout << std::bitset<4>{ 0b1010 } << '\n'; // we can also print from std::bitset directly

tạo một đối tượng std :: bitset tạm thời với 4 bit, khởi tạo nó bằng 0b1010, in giá trị dưới dạng nhị phân, sau đó loại bỏ std :: bitset tạm thời.

5. Những con số ma thuật , và tại sao chúng tệ

Hãy xem xét đoạn code sau:

int maxStudents{ numClassrooms * 30 };

Một số chẳng hạn như 30 trong đoạn code trên được gọi là một số ma thuật. Số ma thuật là một chữ (thường là một số) ở giữa code không có bất kỳ ngữ cảnh nào. 30 có nghĩa là gì? Mặc dù bạn có thể đoán rằng trong trường hợp này đó là số học sinh tối đa mỗi lớp, nhưng điều này không hoàn toàn rõ ràng. Trong các chương trình phức tạp hơn, có thể rất khó để suy ra một số được mã hóa cứng đại diện cho điều gì, trừ khi có nhận xét để giải thích nó.

Sử dụng số ma thuật thường được coi là thực hành xấu vì ngoài việc không cung cấp ngữ cảnh về những gì chúng đang được sử dụng, chúng còn gây ra vấn đề nếu giá trị cần thay đổi. Giả sử rằng nhà trường mua bàn học mới cho phép họ tăng sĩ số lớp học từ 30 lên 35 và chương trình của chúng ta cần phản ánh điều đó. Hãy xem xét chương trình sau:

int maxStudents{ numClassrooms * 30 };
setMax(30);

Để cập nhật chương trình của chúng ta nhằm sử dụng quy mô lớp học mới, chúng ta phải cập nhật hằng số 30 thành 35. Nhưng còn lệnh gọi setMax () thì sao? 30 đó có cùng ý nghĩa với 30 kia không? Nếu vậy, nó nên được cập nhật. Nếu không, nó nên được để một mình, hoặc chúng ta có thể phá vỡ chương trình của chúng ta ở một nơi khác. Nếu bạn thực hiện tìm kiếm và thay thế toàn cục, bạn có thể vô tình cập nhật đối số của setMax () khi nó không được cho là thay đổi. Vì vậy, bạn phải xem qua tất cả mã cho mọi trường hợp của nghĩa đen 30, và sau đó xác định xem nó có cần thay đổi hay không. Điều đó có thể rất tốn thời gian (và dễ xảy ra lỗi).

Mặc dù chúng ta nói “số” ma thuật, điều này ảnh hưởng đến tất cả các loại giá trị. Hãy xem xét ví dụ này

std::cout << "Enter a number less than 100: ";
 
int input{};
std::cin >> input;
 
if (input >= 100)
{
  std::cout << "Invalid input! The number has to be less than 100.";
}

Chỉ có một số (100) trong ví dụ này, nhưng nó cũng được sử dụng trong chuỗi. Nếu chúng ta quyết định cập nhật mức tối đa, giả sử là 200, chúng ta phải cập nhật ba lần khác nhau là 100.

May mắn thay, các tùy chọn tốt hơn (hằng số tượng trưng) tồn tại. Chúng ta sẽ nói về những điều đó trong bài học tiếp theo.

Bạn nên – Không sử dụng số ảo trong mã của bạn.

Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.

Nguồn và Tài liệu tiếng anh tham khảo:

Tài liệu từ cafedev:

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

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