Biến và các kiểu dữ liệu trong C++

####Chúng ta tiếp tục đồng hành trong khóa học lập trình C++ hướng thực hành.

Trong bài học hôm nay, chúng ta sẽ tìm hiểu cơ bản về việc lưu trữ và sử dụng dữ liệu.

Như thường lệ, việc đầu tiên chúng ta làm là tạo một project C++ mới (Mình đặt tên project là Bai1.4 để tiện theo dõi, còn các bạn thích đặt tên project là gì cũng được).

Sau khi Visual studio thiết lập cấu hình cho project, ta tạo file main.cpp và viết một số dòng lệnh tạo nên cấu trúc cơ bản của chương trình C++.

Sau đó nhấn tổ hợp phím Ctrl + Shift + B để thực hiện quá trình biên dịch file main.cpp thành file main.obj, và tạo thành file execute. Việc build chương trình trong giai đoạn đầu này nhằm đảm bảo mọi thứ hoạt động ổn định, và tiết kiệm thời gian cho những lần build sau.

Mình xin phép dành thêm một ít thời gian để nói về cấu hình build ứng dụng của Visual studio 2015.

Khi thực hiện build project, Visual studio cung cấp cho chúng ta hai lựa chọn: DebugRelease.

Để chọn cấu hình build ứng dụng, các bạn vào BUILD trên thanh Menu Bar, chọn Configuration Manager.

Cửa sổ chọn cấu hình xuất hiện như bên dưới:

Hai lựa chọn này khác nhau như thế nào? Có thể hiểu build chương trình dưới cấu hình Debug thì sản phẩm của chúng chưa được hoàn thiện, cần thời gian để tìm lỗi, sửa lỗi… Và một khi bạn cho rằng sản phẩm của mình đã được viết hoàn tất, bạn chuyển sang cấu hình Release để build sản phẩm. Sản phẩm sau khi Release thường sẽ có dung lượng nhẹ hơn khi Debug, vì khi trong chế độ Debug, Visual studio sẽ tích hợp một số thư viện nhằm phục vụ cho quá trình tìm kiếm và sửa lỗi. Đây chỉ là phần ngoài lề của bài học, bây giờ chúng ta quay lại với nội dung chính.

##Biến (Variable)

Khái niệm biến (variable) ra đời đã giải quyết được rất nhiều mặt hạn chế trong các chương trình mà các bạn đã viết trong các bài học trước. Ví dụ với chương trình tính kết quả biểu thức chứa 2 số nguyên, các bạn phải viết một vài dòng lệnh, biên dịch chương trình, chạy chương trình để in ra kết quả. Sau đó thì sao? Khi bạn muốn tính kết quả của phép tính trên với 2 giá trị khác, các bạn lại phải viết lại một vài dòng lệnh, và thực hiện quá trình trên lặp đi lặp lại.

Đây không phải là lập trình! Người viết chương trình phải đảm bảo chương trình sau khi viết ra phải có tính tổng quát, nghĩa là chương trình đó phải giải được một bài toán nào đó với nhiều giá trị đầu vào khác nhau mà không phải thay đổi bất kỳ đoạn code nào bên trong.

Để tiết kiệm thời gian cho việc này, chúng ta sẽ sử dụng biến (variable) để lưu trữ giá trị cần xử lý.

Ví dụ:

int var1 = 3;
int var2 = 5;
cout << "var1 + var2 = " << var1 + var2 << endl;

Trong đoạn code trên, var1 là một biến và var2 cũng là một biến. Hai biến này hiện đang lưu trữ hai giá trị khác nhau (cũng có thể sẽ trùng nhau). Và dòng lệnh cout bên dưới sẽ in ra kết quả phép cộng của hai biến này.

Và khi chúng ta muốn thay đổi giá trị của hai số cần tính, chúng ta đơn giản truyền vào cho hai biến này hai giá trị khác.

var1 = 10;
var2 = 20;
cout << "The new result: " << var1 * var2 << endl;

Như đoạn code trên, chúng ta sử dụng lại hai biến var1 và var2 mà không cần biên dịch lại chương trình hay viết lại bất kỳ đoạn code nào. Việc tái sử dụng tiết kiệm thời gian và công sức cho chúng ta rất nhiều.

Đến đây sẽ có nhiều bạn vẫn chưa hình dung được biến là cái gì. Các bạn có thể hiểu như thế này:

Biến là một ô nhớ đơn lẻ hoặc một vùng nhớ được hệ điều hành cấp phát cho chương trình C++ nhằm để lưu trữ giá trị vào bên trong vùng nhớ đó. Chúng ta sẽ hỏi xin hệ điều hành những vùng nhớ thông qua các câu lệnh khai báo biến như bên dưới:

int valueInteger = 12; // (1) Chúng ta có một vùng nhớ để chứa 1 số nguyên

float valueFloat = 5.394; // (2) Xin hệ điều hành thêm một vùng nhớ để chứa 1 số thực

string myName = "Minh Vu"; // (3) Biến này chứa được một dãy các kí tự

Với 3 cách khai báo trên, chúng ta sẽ có 3 vùng nhớ nằm ở 3 vị trí khác nhau trên RAM của bạn.

Với cách khai báo 1:

Hình 1.4.4

Với cách khai báo 2:

Hình 1.4.5

Với cách khai báo 3:

Hình 1.4.6

Sau đây là cú pháp cơ bản để chúng ta khai báo 1 biến:

<Kiểu dữ liệu> <Tên biến> = [Giá trị khởi tạo của biến];

Trong đó, tên biến giúp ngôn ngữ C++ xác định vùng nhớ mà chúng ta đã cấp phát, mỗi lần sử dụng biến, compiler sẽ tìm đến vùng nhớ mà chúng ta đã đặt tên cho nó và lấy giá trị ra để sử dụng. Kiểu dữ liệu sẽ phân loại giá trị của biến (kí tự, số nguyên, số thực, …), chúng ta sẽ làm rõ hơn ở phần dưới của bài học này.

Khi khai báo biến, chúng ta có thể gắn 1 giá trị ban đầu cho biến hoặc không, nhưng chúng bản chất là một câu lệnh, nên chúng ta phải kết thúc bằng dấu chấm phẩy.

Lý thuyết nhiều rồi, bây giờ chúng ta sẽ tận dụng sức mạnh lưu trữ dữ liệu của biến để giải một bài toán cơ bản.

Bài toán: Nhà mình có nuôi 1 đàn bò, mình đã biết số lượng bò ở thời điểm hiện tại. Nhưng vì mình tính toán chậm nên gặp khó khăn trong việc tính số chân bò của đàn bò đang nuôi. Mình muốn đưa máy tính tính giúp mình, các bạn có thể giúp mình viết chương trình tính tổng số chân bò của cả đàn được không? (Các bạn có thể nghĩ ra một con số đại diện cho số bò mà mình đang nuôi, sao cho nó là số nguyên dương là được)

Sau khi viết xong đề của bài toán thì mình đã nghĩ ra giải pháp giải quyết bài toán này rồi. Chúng ta biết 1 con bò thì có 4 chân, vậy là mình chỉ cần 1 biến để chứa số bò hiện tại, và lấy giá trị của biến đó nhân với 4 là ra kết quả.

Đây là chương trình do mình viết, mình khuyên các bạn nên tự nghĩ cách viết trước khi tham khảo chương trình của mình.

Hi vọng chương trình của bạn các viết cũng cho kết quả đúng như mong đợi.

Bây giờ có một vấn đề phát sinh, đàn bò của mình sau một năm đã sinh thêm 10 con bò con. Bây giờ làm sao để mình tính tổng số chân của đàn bò mới?

Hướng giải quyết: Lấy số lượng bò cũ cộng thêm 10 con bò mới sinh, và lấy số lượng bò mới này nhân 4.

Chương trình của mình sẽ được viết lại như sau:

Ở đoạn code trên, dòng number_of_cows = number_of_cows + 10; có nghĩa là:

Chúng ta dùng toán tử “=” để đưa một giá trị vào trong biến number_of_cows, giá trị mà chúng ta đưa vào sẽ bằng giá trị của biến number_of_cows hiện tại (đang là 30) cộng thêm 10. Sau khi thực hiện dòng lệnh này, giá trị mới trong biến number_of_cows sẽ là 40.

Chúng ta đã sử dụng lại biến number_of_cows để tính tiếp số chân bò sau 1 năm mà không cần phải viết lại chương trình tính số chân bò nữa.

##Kiểu dữ liệu

Kiểu dữ liệu là một thành phần bắt buộc phải có khi muốn khai báo biến, nó giúp chương trình xác định kích cỡ của vùng nhớ mà bạn muốn xin hệ điều hành cấp phát trên RAM, đồng thời giúp chương trình xác định giới hạn giá trị mà biến đó có thể lưu trữ.

Dưới đây là bảng mô tả một số kiểu dữ liệu cơ bản:

Hình 1.4.10

(Nguồn: www.learncpp.com)

Trong cột Category, người ta chia các kiểu dữ liệu cơ bản thành 4 loại:

  • Kiểu logic (boolean): bool.
  • Kiểu kí tự (character): char, wchar_t, char16_t, char32_t. Hiện tại chúng ta chỉ cần quan tâm đến kiểu char.
  • Kiểu số nguyên (integer): short, int, long, long long. Thường dùng nhất là kiểu int.
  • Kiểu số thực (floating): float, double, long double. Tùy vào độ chính xác mà chúng ta đòi hỏi ở phần thập phân mà chúng ta chọn kiểu dữ liệu float hoặc double. Kiểu double có kích thước vùng nhớ lớn hơn, nên sẽ lưu giá trị có độ chính xác cao hơn float.

Kích thước vùng nhớ của các kiểu dữ liệu này được tính bằng đơn vị byte. Đối với các bạn mới học ngôn ngữ lập trình, chúng ta chưa cần quan tâm nhiều đến khái niệm này.

Để xem kích thước vùng nhớ sẽ được cấp phát cho biến trong chương trình. Chúng ta sử dụng toán tử sizeof(<kiểu dữ liệu>) như sau:

Theo kết quả của chương trình, kiểu dữ liệu số nguyên int có kích cỡ 4 bytes, đó là do IDE Visual studio 2015 định nghĩa kiểu int như vậy. Mỗi compiler sẽ có một chuẩn kiểu dữ liệu riêng, nên các bạn không cần lo lắng về sự khác biệt giữa kích bảng dữ liệu ở trên với kết quả thực tế.

Các bạn hiện tại chỉ cần hiểu với những kiểu dữ liệu có kích thước càng lớn thì phạm vi giá trị có thể lưu trữ cho biến càng lớn.

Dưới đây là bảng giới hạn giá trị cho từng kiểu dữ liệu mà chúng ta thường xuyên sử dụng trong Visual studio:

Hình 1.4.12

Các bạn không cần nhớ chính xác những giới hạn trên, chỉ cần ước chừng phạm vi của mỗi kiểu dữ liệu để chọn kiểu dữ liệu phù hợp cho biến là được.

##Tổng kết

Trong bài này, các bạn chỉ cần hiểu được một số khái niệm về biến và kiểu dữ liệu:

  • Biến (variable) là một đối tượng chiếm giữ một vùng nhớ xác định.

  • Biến (variable) dùng để lưu trữ giá trị (kí tự, số nguyên, số thực … hoặc cũng có thể là một dãy các con số).

  • Cú pháp khai báo biến:

    <kiểu dữ liệu> <tên biến> [= giá trị khởi tạo];
    
  • Kiểu dữ liệu đứng trước tên biến nhằm xác định giới hạn giá trị mà biến có thể lưu trữ được.

  • Đặt tên biến như thế nào cho phù hợp?

    • Tên biến không được bắt đầu bằng kí tự số.

    • Trong một khối lệnh { } không được có hai biến cùng tên.

    • Tên biến trong C++ phân biệt chữ hoa và chữ thường. Ví dụ: int var1;int Var1; là hai biến phân biệt.

    • Các bạn có thể sử dụng kí tự gạch chân khi đặt tên biến.

    • Nên đặt tên biến sao cho thể hiện được ý nghĩa của biến. Ví dụ:

      int myAge;

      string myName; // các bạn sẽ được học về kiểu string trong các bài học sau

      bool isRunning = true;

      int current_score;

  • Khi sử dụng biến trong các biểu thức toán học, các bạn nên dùng biến có cùng kiểu dữ liệu với nhau. (Tùy trường hợp mà có thể dùng kết hợp nhiều kiểu dữ liệu khác nhau)

###Bài tập cơ bản

Hình 1.4.13

  1. Chạy thử đoạn chương trình trên và xem kết quả.
    Giải thích tại sao chương trình cho kết quả như vậy!

  2. Tạo hai biến (variable) và gán giá trị mặc định cho nó tùy ý bạn, sau đó in ra kết quả của 4 phép toán cơ bản +, -, * và / của hai biến đó lên màn hình.

  3. Viết chương trình tính chu vi và diện tích hình chữ nhật khi biết trước độ dài hai cạnh kề nhau.


Hẹn gặp lại các bạn trong bài học tiếp theo trong khóa học lập trình C++ hướng thực hành.

Mọi ý kiến đóng góp hoặc thắc mắc có thể đặt câu hỏi trực tiếp tại diễn đàn

www.daynhauhoc.com


Link Videos khóa học

https://www.udemy.com/c-co-ban-danh-cho-nguoi-moi-hoc-lap-trinh/learn/v4/overview

12 Likes

anh ơi cho em lời giải thích bài 1 dc ko ạ? em chưa hiểu tại sao vượt quá giá trị lưu của kiểu dữ liệu thì nó sẽ ra kết quả khác

Em lên learncpp thì thấy ng ta nói là biến là tên 1 vùng nhớ ở trong ram có thể dùng để lưu trữ dữ liệu, mà ở đây định nghĩa biến lại khác :frowning:

Vùng nhớ mà biến quản lý nằm trên RAM. Chúng ta hỏi xin hệ điều hành cấp phát bộ nhớ bằng câu lệnh khai báo biến.

Để xác định được 1 biến, chúng ta cần cung cấp kiểu dữ liệu và tên biến cho compiler (giá trị khởi tạo có thể có hoặc không). Khi nói đến biến, chúng ta hiểu nó bao gồm cả tên biến, địa chỉ của nó trên bộ nhớ, cả kích thước vùng nhớ mà biến đang giữ và giá trị bên trong vùng nhớ đó.

Qua bài địa chỉ của biến bạn sẽ biết cách đọc địa chỉ của biến trên bộ nhớ.

giải bài tập 1.4
Câu 1:
output 1 :khai báo giá trị biến vựot quá vùng nhớ cho phép của kiểu int, nên nó sẽ đưa về giá trị tối đa vùng nhớ là 21474836347

output 2: ra đúng theo giá trị khai báo vì giá trị của biến nằm trong vùng giá trị của kiểu int64

Câu 2:

#include iostream
using namespace std;

int var1 = 10;
int var2 = 15;
int main() {
    cout << " Cộng 2 số " << var1 + var2 << endl;
    cout << " Trừ 2 số " << var1 - var2 << endl;
    cout << " Nhân 2 số " << var1 * var2 << endl;
    cout << " Chia 2 số " << var1 / var2 << endl;
  return 0;
}

Câu 3 :slight_smile:
 #include iostream
using namespace std;

int chieudai = 10;
int chieurong = 15;
int main() {
    cout << " Chu vi hinh chu nhat la :  " << (chieudau + chieurong)*2 << endl;
    cout << " Dien tich hinh chu nhat la:  " << chieudai * chieurong << endl;
   system("pause");
  return 0;
}

P/s: mình không gõ được <> bao quanh thư viện iostream, gõ vào nó ko thấy chữ

1 Like

Thật ra để hiểu được câu 1 các bạn cần học qua về môn tin học đại cương, các hệ cơ số. Máy tính không thể hiểu được các giá trị hệ cơ số 10 mà chỉ hiểu được các giá trị 0 hoặc 1. Mỗi bit (đơn vị đo lường nhỏ nhất trong việc lưu trữ của máy tính) sẽ nhận giá trị 0 hoặc 1 này. Kiểu int có kích thước 32 bits (4 bytes).

Giá trị 999999999999 trong hệ cơ số 10 khi chuyển về nhị phân chúng ta sẽ được

‭|1110100011010100101001010000111111111111|‬ //999999999999

00000000|11010100101001010000111111111111|‬ //kiểu int chỉ chứa đc 32 chữ số

Như vậy, để lưu trữ được giá trị 999999999999, chúng ta cần ít nhất 40 bits để lưu trữ, trong khi đó, kích thước của kiểu int thông thường chỉ là 4 bytes (32 bits), do đó giá trị được in ra là 32 bits đếm từ phải sang trái: 11010100101001010000111111111111‬. Chuyển đổi chuỗi nhị phân này qua hệ cơ số 10, chúng ta sẽ được giá trị -727379969 (Vì đây là kiểu số nguyên có dấu, nên bit 1 đầu tiên sẽ chuyển giá trị về số âm).

Nếu các bạn mới học chưa biết gì về việc chuyển đổi giá trị giữa các hệ cơ số thì có thể bật cái Calculator lên, đặt mode dành cho Programmer.

Trong đó, DEC là decimal, BIN là binary.

5 Likes

thanks @nguyenchiemminhvu

Mình mới tìm hiểu C++, mình có đoạn code này

` #include
using namespace std;

int main() {
//
// Declare and defines variables
int a, b, e;

// Declare and initialized variable
int c = 3, d = 5;
cout << "a: " << a << ", b: " << b << ", c :" << c << ", d: " << d << ", e: " << e <<endl;

return 0;

}`

Mình không hiểu tại sao khi không gán giá trị cho các biến a, b thì giá trị của chúng lại khá lớn, còn e thì = 0. Mình nghĩ là cả a, b, e đều = 0 chứ nhỉ? Các bạn giải thích giúp, Cám ơn mọi người.

cái hộp ngoài đời thực chứa không khí còn trong lập trình nó chứa rác thôi anh ạ ! đối với code::blocks thì nó có giá trị lung tung còn Visual Studio nó mặc định (điều này rất tốt khi gặp lỗi) :slight_smile:

#include ;
#include
#include ;
using namespace std;
int main(){
srand(time(NULL));
int a = rand () % 100 + 1;

float b ;
	cout<< "be hon nhan 0, lon hon nhan 1 "; cin >> b;
	cout<<a<<endl;
	
if ( (a-50)*(b-1/2) >=0)
cout << "dung roi" <<endl;
else 
cout << "sai roi"<<endl;
 system("pause");
return 0;		

}

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?