Bài 5. Nhập / Xuất Cơ Bản Trong C++

Basic input / output in C++

Trong bài này mình sẽ trình bày những thao tác nhập/ xuất cơ bản(basic input/output) để các bạn có thể viết ngay được chương trình với C++. Học C++ cũng giống như học một ngoại ngữ như tiếng Ý hay Italia . Để học được và học tốt ngôn ngữ việc trước tiên không phải là lao ngay vào “ngâm cứu” ngữ pháp hay văn phạm hoặc các luật lệ của ngôn ngữ, mà là phải biết một số từ mới, một số câu xã giao đơn giản kiểu như : Hey, Girl! You’re so beautiful …  Dần dần khi vốn từ vựng đã đủ dùng và ta ta đã quen dần với ngôn ngữ thì lúc đó mới ngâm cứu những vấn đề sâu hơn, mới tìm hiểu được bản chất của vấn đề. Vì vậy bài này giúp các bạn mới học C++ làm quen với những thao nhập xuất tác cơ bản trong C++ như học các từ vựng đầu tiên của ngôn ngữ, còn muốn hiểu rõ bản chấtnguyên tắc hoạt động của chúng ra sao thì cần phải cần có những kiến thức sâu hơn một chút, mình sẽ trình bày trong bài nói về input/ output streamfile.

1. Xuất dữ liệu ra màn hình

Để in dữ liệu của một biểu thức nào đó ra màn hình (standard output device) ta dùng cú pháp sau:

cout << exp ;  // output content of expression

Hoặc cho một dãy các biểu thức:

cout << exp_1 << exp_2 << … << exp_n ; // output content of expressions 1, 2, … , n

Ta cũng có thể viết câu lệnh trên trên nhiều dòng ví dụ như:

cout << exp_1 << exp_2 << exp_3 … << exp_n;

Kết quả thu được là hoàn toàn tương tự. cout cùng với toán tử << có thể xuất được nhiều kiểu dữ liệu khác nhau mà không cần sự can thiệp của lập trình viên. C++ tự động nhận biết và xuất ra dưới định dạng phù hợp. Xét đoạn chương trình sau:

#include <iostream> #include <string> using namespace std; int main(){ int n=3; float x=12.08; string str="Be aware ! I have a gun"; cout << n << endl; cout << x << endl; cout << str << endl; return 0; }

Kết quả thu được trên màn hình sẽ như sau:

3 12.08 Be aware ! I have a gun

2. Nhập dữ liệu vào từ bàn phím

Bàn phím là thiết bị nhập chuẩn (standard input device). Để vào dữ liệu từ bàn phím cho các biến ta có thể dùng cin vùng toán tử >>. Cú pháp sẽ như sau:

cin >> var; // read data into variable

Hoặc cho nhiều biến:

cin >> var_1 >> var_2 >> … >> var_n; // read data into variables 1, 2, ... , n

Khi gặp những câu lệnh như thế này chương trình sẽ “pause” lại để chờ chúng ta nhập dữ liệu vào từ bàn phím. Câu lệnh cin >> var_1 >> var_2 >> … >> var_n; coi các ký tự trắng là ký tự phân cách các lần nhập dữ liệu. Các ký tự trắng (white space characters) bao gồm: dấu cách, dấu tab, và ký tự xuống dòng (new line). Ví dụ a, b là hai biến kiểu int, thì câu lệnh:

cin >> a >> b;

sẽ đợi người dùng nhập dữ liệu hai lần, cách nhau bởi ít nhất một ký tự trắng. Ví dụ ta nhập vào bàn phím như sau : 1989 2011 ↵ thì biến a sẽ nhận giá trị 1989, còn biến b sẽ nhận giá trị 2011. Chúng ta cũng không cần quan tâm đến kiểu của các biến, C++ tự động nhận biết điều này. Xem xét đoạn chương trình sau:

int num; cin >> num;

Nếu ta nhập vào giá trị 12.08 thì biến num chỉ nhận được giá trị 12. Còn phần thập phân sẽ không được ghi nhận, do num là một biến kiểu int nên C++ tự động nhận biết và “chặt cụt” đi phần này.

3. Những lưu ý trong nhập/ xuất xâu ký tự.

Trong tất cả các kiểu dữ liệu, theo mình thì nhập xuất với xâu (string) là thể loại củ chuối và rắc rối nhất (:=(|) Trước hết mình nói qua một chút về thư viện chuẩn <string> của C++. Nếu bạn nào đã học qua ngôn ngữ C rồi thì đều biết xâu ký tự là một mảng chứa các ký tự (kiểu char) và phần tử cuối cùng của mảng là NULL (hay ” ) để đánh dấu sự kết thúc xâu. Tuy nhiên, sử dụng mảng để lưu trữ xâu có phần phức tạp vì mảng là một cấu trúc tĩnh phải biết rõ kích thước ngay khi khai báo. Điều này làm cho chương trình “cứng nhắc” và không “kinh tế”. Ví dụ nếu khai báo ít quá thì khi muốn chứa thêm nhiều ký tự hơn sẽ không được, mà nếu khai báo nhiều quá, không dùng hết sẽ lãng phí bộ nhớ. Để khắc phục người ta dùng biện pháp quản lý mảng bằng con trỏcấp bộ nhớ phát động cho mảng (dynamic memory allocation). Tuy nhiên nếu việc này diễn ra thường xuyên thì chương trình sẽ rất rối rắm, gây mệt mỏi cho lập trình viên và dễ dẫn đến lỗi. C++ giải quyết tốt vấn đề này bằng cách xây dựng lớp string. Một đối tượng của lớp string có thể lưu trữ các ký tự “tốt hơn” mảng trong C rất nhiều. Muốn sử dụng nó ta phải include header file <string>. Trong các bài viết, nếu không có lý do gì đặc biệt, thì mình sẽ dùng string để lưu trữ xâu.

Bây giờ trở lại vấn đề của chúng ta, đó là nhập/ xuất xâu ký tự. Xuất thì ok, không có vấn đề gì phải bàn luận nhiều, nhưng nhập thì lại có nhiều điều để nói.

i. cin không cho phép nhập dấu trắng

Xét chương trình sau đây:

#include <iostream> #include <string> using namespace std; int main(){ string str; cin>> str; cout << str << endl; return 0; }

Nếu ta nhập vào đoạn văn bản sau: “Osama Binladen” thì xâu str chỉ ghi nhận đoạn đầu “Osama” vì dấu cách là một khoảng trắng mà cin coi các dấu trắng là ký tự báo hiệu kết thúc việc nhập dữ liệu. Để khắc phục điều này C++ cung cấp một số cách thức để nhập toàn bộ xâu ký tự. Nhưng trước hết ta phải xem xét một vấn đề về bộ đệm.

ii. Bộ đệm (buffer)

Khi ta nhập dữ liệu vào bàn phím thì dữ liệu không được đọc ngay vào biến mà được đẩy lên trên bộ đệm (buffer). Dữ liệu sẽ tồn tại trong bộ đệm cho tới khi một lệnh nào đó gửi yêu cầu đến bộ đệm “xin phép” được load dữ liệu về. Ví dụ khi chương trình gặp câu lệnh:

cin >> x; // với x là một biến kiểu int

thì nó sẽ mò lên buffer để load dữ liệu về, nếu như trên bộ đệm có số 100 thì nó sẽ đọc 100 vào biến x mà không đợi ta nhập gì cả, còn nếu bộ đệm trống hoặc có những dữ liệu không phải số nguyên (ví dụ mã phím Enter của lần nhập trước) thì nó mới dừng lại đợi ta nhập dữ liệu vào. Như vậy ta hoàn toàn không cần để ý nhiều việc sử dụng cin >> để nhập các dữ liệu số (nguyên hoặc dấu chấm động – floating point), nhưng để nhập dữ liệu ký tự thì lại hoàn phải hết sức chú ý. Trong đoạn chương trình test nhập xâu ký tự bên trên ta nhận thấy biến str chỉ lưu trữ phần “Osama”, phần còn lại thì vẫn nằm trên buffer để cho lần nhập sau. C++ cung cấp getline cho phép nhập toàn bộ xâu ký tự kể cả khoảng trắng. Cú pháp sử dụng hàm getline như sau.

getline(cin, str, delimiter);

Câu lệnh trên sẽ thực hiện đọc toàn bộ xâu nhập từ bàn phím vào biến str, cho tới khi bắt gặp ký tự kết thúc (delimiter) hoặc EOF (end-of-file). Nếu không viết delimiter thì mặc định là ký tự xuống dòng – ‘\n’. Xét chương trình sau:

#include <iostream> #include <string> using namespace std; int main(){ string str; getline(cin,str); cout << str << endl; return 0; }

Nếu ta nhập vào bàn phím xâu “Osama Binladen” rồi nhấn Enter thì kết quả thu được trên màn hình sẽ là trọn vẹn xâu “Osama Binladen”. Điều gì xảy ra với ký tự Enter, nó có nằm lại trên bộ đệm không? Câu trả lời là getline đã đọc mã của ký tự Enter nhưng không gắn nó vào trong xâu str và cũng không để lại nó trên bộ đệm mà hủy nó đi.

iii. Hiện tượng trôi lệnh

Xét chương trình sau:

#include <iostream> #include <string> using namespace std; int main(){ int num; string str; cout << "Input an integer a= "; cin >> num; cout << num << endl; cout << "Input a string str= "; getline(cin,str); cout << str << endl; cout << "End program" << endl; return 0; }

Bạn chạy thử chương trình trên sẽ thấy ngay. Sau khi nhập dữ liệu cho biến num, chương trình không dừng lại cho ta nhập dữ liệu cho str. Mà in ngay ra thông báo “End program”. Nguyên nhân là do sau khi nhập dữ liệu cho biến num ta gõ phím Enter. Mã của Enter được lưu trong bộ đệm (chính là ký tự xuống dòng ‘\n’) và do đó khi chương trình gặp câu lệnh:

getline(cin,str);

nó sẽ đọc ngay ký tự này và nhận thấy đây là ký tự kết thúc nên nó sẽ loại bỏ ký tự này ra khỏi bộ đệm mà không đọc vào xâu str. Sau đó nó sẽ chạy thẳng đến câu lệnh tiếp theo là:

cout << "End program" << endl;

Người ta thường gọi đó là hiện tượng “trôi lệnh”. Để khắc phục hiện tượng trôi lệnh này thì trước mỗi lệnh getline ta nên đặt câu lệnh:

fflush(stdin);

Câu lệnh này có tác dụng xóa bộ đệm và do đó ta có thể yên tâm là sẽ không bị trôi lệnh nữa.

Trên đây mình đã giới thiệu hai thao tác cơ bản và thông dụng nhất là nhập và xuất dữ liệu ra các thiết bị chuẩn. Đồng thời cũng đưa ra một số chú ý về nhập xuất với dữ liệu ký tự và xâu ký tự. Hy vọng có thể giúp các bạn tránh gặp phải những lỗi không mong muốn khi nhập xuất dữ liệu trong C++.

Chia sẻ:

  • Facebook
  • X
Thích Đang tải...

Có liên quan

Từ khóa » đâu Là Lệnh Xuống Dòng Trong Lập Trình C++