Kiểu dữ liệu tự định nghĩa là gì

Mọi chương trình đều cần đến dữ liệu. Ví dụ chương trình sau:

int main() { cout<<"LAP TRINH C/C++"; system("pause"); }

Một chương trình xuất ra màn hình đơn giản cũng cần dữ liệu

Chương trình trên cần lưu trữ dữ liệu “LAP TRINH C/C++” để xuất ra màn hình. Hay một chương trình giải phương trình bậc 2 cần lưu trữ dữ liệu các hệ số a, b,c, giá trị Delta, các nghiệm của phương trình.

Một chương trình quản lý nhân sự cần dữ liệu mã số nhân sự, họ tên, hệ số lương,…

Dữ liệu mà chương trình lưu trữ có thể thuộc nhiều dạng khác nhau, gọi là kiểu dữ liệu (data type):

    • Ký tự (character), một chuỗi như “LAP TRINH C/C++”
    • Trạng thái: có hay không, đúng hay sai
    • Các con số nguyên, số thực,…
    • Một dãy các giá trị, một tổ hợp các giá trị (struct, class)

Ngoài tính chất lưu trữ khác nhau, chương trình cũng cần thiết phân biệt các kiểu dữ liệu nói trên. Vì mỗi kiểu quy định thông tin đi kèm khác nhau, cách tổ chức lưu trữ khác nhau.

Vậy ngôn ngữ lập trình phân biệt các kiểu dữ liệu như thế nào?

Ngôn ngữ C/C++ (các ngôn ngữ khác cũng vậy) quy ước ngữ nghĩa với một loạt các tên kiểu dữ liệu mà nó cung cấp sẵn. Tên các kiểu có sẵn này đã được gắn sẵn ngữ nghĩa nên nó là từ khoá. Ngoài ra, các ngôn ngữ lập trình cũng cung cấp cơ chế để lập trình viên tự định nghĩa các kiểu dữ liệu cho riêng mình.

Kiểu dữ liệu cơ bản (Fundamental Data Type): Tên kiểu là từ khoá, ngữa nghĩa của tên này được quy định bởi ngôn ngữ lập trình.

Kiểu dữ liệu do lập trình viên định nghĩa (User-defined Data Type): Tên kiểu do người lập trình đặt ra. Các kiểu dữ liệu dạng này trong C++ như struct, class,…

Kiểu dữ liệu dẫn xuất (Derived Data Type): C++ cung cấp các ký hiệu để tạo ra kiểu mới từ các kiểu khác. Ví dụ: Mảng (array) các ký tự, các số nguyên, các số thực hay con trỏ (pointer).

Kiểu dữ liệu Enum (Enum Data Type): tham khảo bài Kiểu dữ liệu enum trong C++.

Phải nhớ từ khóa và phạm vi giá trị của các kiểu dữ liệu để sử dụng chính xác.

Kiểu dữ liệuTừ khóaKích thước (bytes)Phạm vi giá trị
Số nguyênint4–2.147.483.648 đến +2.147.483.647
Số thựcfloat4+/- 3.4E +/- 38
Số thựcdouble8+/- 1.7E +/- 308
Ký tựchar1-128 đến 127 hoặc 0 đến 255
Ký tựwchar_t20 đến 65.535
Luận lý (Boolean)bool1true hoặc false (1 hoặc 0)
Không kiểu (Valueless)void  

Ngôn ngữ C++ cho phép các modifiers đứng trước các kiểu dữ liệu cơ bản. Mục đích là thay đổi ý nghĩa của các kiểu dữ liệu cơ bản.

Kiểu dữ liệu tự định nghĩa là gì
Modifiers trong C++

Các modifiers được hỗ trợ trong C++ là signed (có dấu), unsigned (không dấu), short, long.

Từ khóaKích thước (bytes)Phạm vi giá trị
Modifier của kiểu int
short int2-32.768 đến 32.767
unsigned short int20 đến 65.535
unsigned int40 đến 4.294.967.295
long int4-2.147.483.648 đến 2.147.483.647
unsigned long int40 đến 4.294.967.295
long long int8-(2^63) đến (2^63)-1
unsigned long long int80 đến 18.446.744.073.709.551.615
Modifier của kiểu char
signed char1-128 đến 127
unsigned char10 đến 255
Modifier của kiểu double
long double8+/- 1.7E +/- 308

Sử dụng hàm sizeof để in ra số bytes của các kiểu dữ liệu.

#include <iostream> using namespace std; int main() { cout << "Kich thuoc cua char la: " << sizeof(char) <<" byte"<< endl; cout << "Kich thuoc cua int la: " << sizeof(int) <<" byte"<< endl; cout << "Kich thuoc cua short int la: " << sizeof(short int) <<" byte"<< endl; cout << "Kich thuoc cua long int la: " << sizeof(long int) <<" byte"<< endl; cout << "Kich thuoc cua float la: " << sizeof(float) <<" byte"<< endl; cout << "Kich thuoc cua double la: " << sizeof(double) <<" byte"<< endl; cout << "Kich thuoc cua wchar_t la: " << sizeof(wchar_t) <<" byte"<< endl; system("pause"); }

Kết quả:

Kich thuoc cua char la: 1 byte Kich thuoc cua int la: 4 byte Kich thuoc cua short int la: 2 byte Kich thuoc cua long int la: 4 byte Kich thuoc cua float la: 4 byte Kich thuoc cua double la: 8 byte Kich thuoc cua wchar_t la: 2 byte Bài trước và bài sau trong môn học

Trong nhiều trường hợp, chúng ta cần lưu trữ một nhóm các biến dữ liệu khác nhau (int, float, char, string,…). Ngôn ngữ C++ có hỗ trợ lập trình viên tạo ra kiểu dữ liệu cấu trúc (struct) để thực hiện lưu trữ như thế. Bài này sẽ giới thiệu định nghĩa và cách khai báo biến cấu trúc.

Cần viết chương trình lưu thông tin 1 sinh viên gồm các thông tin:

    • MSSV: kiểu chuỗi
    • Tên SV: kiểu chuỗi
    • Ngày sinh: kiểu chuỗi
    • Phái: kiểu luận lý
    • Điểm Toán, Lý, Hóa: kiểu số thực

Khai báo các biến lưu thông tin 1 sinh viên

    • string mssv; // “0306201123”
    • string hoten; // “Nguyễn Văn Minh”
    • string ngaysinh; // “16/08/2002”
    • bool phai; // true: Nữ, false: Nam
    • float Toan, Ly, Hoa; //8.5, 9, 7.5

Nếu cần lưu thông tin của 10 sinh viên hoặc hơn thì phải làm thế nào? Một sinh viên tạo 7 biến, không lẻ phải tạo 7×10 = 70 biến để lưu 10 sinh viên?

Giải pháp: Gom những thông tin của cùng một sinh viên thành một kiểu dữ liệu mới. Đó là kiểu dữ liệu cấu trúc (struct).

Kiểu dữ liệu cấu trúc (struct) là một nhóm các thành phần dữ liệu, được gom lại với nhau và đặt trong một tên. Trong đó:

– Mỗi thành phần dữ liệu gọi là trường dữ liệu hoặc thành viên.

– Các trường dữ liệu có thể có kiểu dữ liệu khác nhau.

– Lập trình viên tự định nghĩa kiểu dữ liệu cấu trúc gồm những thành phần dữ liệu.

Cú pháp định nghĩa một kiểu dữ liệu cấu trúc mới

struct <tên kiểu cấu trúc>

{

            <kiểu dữ liệu> <tên thành phần 1>;

            …

            <kiểu dữ liệu> <tên thành phần n>;

};//lưu ý phải có dấu ;

Ví dụ:

struct DIEM { int x; int y; }; struct SINHVIEN { string mssv; string hoten; string ngaysinh; bool phai; float Toan, Ly, Hoa; };

Muốn sử dụng các kiểu cấu trúc đã định nghĩa để lưu trữ dữ liệu thì cần tạo ra các biến của kiểu cấu trúc đó. Cú pháp khai báo biến của kiểu cấu trúc là:

<tên kiểu cấu trúc> <tên biến cấu trúc>;

Ví dụ:

DIEM d1, d2; SINHVIEN sv1, sv2;

Định nghĩa kiểu cấu trúc và khai báo biến cấu trúc cùng lúc

Việc khai báo biến cấu trúc có thể được thực hiện đồng thời với việc định nghĩa cấu trúc. Muốn vậy, cần đặt danh sách tên biến cấu trúc cần khai báo sau dấu } theo cú pháp sau:

struct <tên kiểu cấu trúc>

{

            <kiểu dữ liệu> <tên thành phần 1>;

            …

            <kiểu dữ liệu> <tên thành phần n>;

} <tên biến 1>, <tên biến 2>,…, <tên biến m>;

Ví dụ:

struct DIEM { int x; int y; } d1, d2; struct SINHVIEN { string mssv; string hoten; string ngaysinh; bool phai; float Toan, Ly, Hoa; } sv1, sv2;

Khởi tạo giá trị cho biến cấu trúc

Cú pháp khởi tạo giá trị cho biến cấu trúc

<tên biến cấu trúc> = {<giá trị 1>,…,<giá trị n>};

– Khởi tạo biến cấu trúc khi định nghĩa cấu trúc
struct DIEM { int x; int y; } d1 = {5, 9}, d2 = {1, 1};
– Khởi tạo biến cấu trúc khi khai báo biến cấu trúc
struct DIEM { int x; int y; }; DIEM d1 = {5, 9}; DIEM d2 = {1, 1};

Lưu ý: Có thể chỉ khởi tạo giá trị cho một số thành phần dữ liệu đầu tiên trong cấu trúc

DIEM d1 = {99};//chỉ khởi tạo giá trị cho x = 99, y không được khởi tạo. y sẽ nhận giá trị mặc định hoặc giá trị rác.

Thiếu dấu ; khi định nghĩa kiểu cấu trúc

struct DIEM { int x; int y; }//lỗi thiếu dấu ;

Khởi tạo biến cấu trúc sau khi khai báo sẽ gây lỗi

struct DIEM { int x; int y; }d1, d2; d1 = {1, 5};//lỗi DIEM d3; d3 = {1, 9};//lỗi

Không thể khởi tạo các thành phần cấu trúc trong khi định nghĩa cấu trúc

struct HINH_TRON { float x = 5.5; //Không hợp lệ float y = 3.2; //Không hợp lệ float BanKinh = 6; //Không hợp lệ }; Bài trước và bài sau trong môn học