📥📤 Nhập xuất dữ liệu trong C++
📖 Giới thiệu
Nhập xuất dữ liệu (Input/Output - I/O) là cách chương trình giao tiếp với người dùng và môi trường bên ngoài. Đây là một trong những kỹ năng cơ bản nhất trong lập trình - làm sao để chương trình có thể nhận thông tin từ người dùng và hiển thị kết quả.
C++ cung cấp nhiều cách để thực hiện I/O: từ các phương thức hiện đại như cin/cout đến các hàm truyền thống như printf/scanf từ C. Mỗi phương pháp có ưu nhược điểm riêng và phù hợp với những tình huống khác nhau.
Trong bài này, chúng ta sẽ học cách sử dụng cin/cout hiệu quả, xử lý các vấn đề thường gặp, và tìm hiểu về định dạng đầu ra đẹp mắt.
🔧 Cú pháp
Xuất dữ liệu với cout
#include <iostream>
using namespace std;
// Xuất cơ bản
cout << "Hello World!"; // Xuất chuỗi
cout << 42; // Xuất số
cout << variable; // Xuất biến
// Xuất nhiều giá trị
cout << "Tuổi: " << age << " năm" << endl;
// Điều khiển định dạng
cout << endl; // Xuống dòng
cout << "\n"; // Xuống dòng (escape sequence)
cout << "\t"; // Tab
cout << flush; // Xóa bufferNhập dữ liệu với cin
#include <iostream>
using namespace std;
int number;
string name;
double price;
// Nhập cơ bản
cin >> number; // Nhập số nguyên
cin >> name; // Nhập string (một từ)
cin >> price; // Nhập số thực
// Nhập nhiều giá trị
cin >> a >> b >> c; // Nhập 3 giá trị cùng lúc
// Nhập chuỗi có khoảng trắng
getline(cin, fullName); // Nhập cả dòngĐịnh dạng đầu ra với manipulators
#include <iostream>
#include <iomanip>
using namespace std;
double pi = 3.14159265;
cout << fixed; // Định dạng số thực cố định
cout << setprecision(2); // 2 chữ số thập phân
cout << pi; // Output: 3.14
cout << setw(10); // Độ rộng 10 ký tự
cout << left; // Căn trái
cout << "Hello"; // "Hello "Printf và scanf (C-style)
#include <cstdio>
int age;
double height;
char name[50];
// Printf - định dạng linh hoạt
printf("Tuổi: %d\n", age); // %d cho int
printf("Chiều cao: %.2f cm\n", height); // %.2f cho double với 2 số thập phân
printf("Tên: %s\n", name); // %s cho string
// Scanf - nhập có định dạng
scanf("%d", &age); // Nhập int
scanf("%lf", &height); // Nhập double
scanf("%s", name); // Nhập string🔬 Phân tích & Giải thích chi tiết
Cin vs Getline
Cin chỉ đọc đến khoảng trắng đầu tiên:
string firstName;
cin >> firstName; // Nhập "Nguyen Van" → chỉ lấy "Nguyen"Getline đọc cả dòng:
string fullName;
getline(cin, fullName); // Nhập "Nguyen Van A" → lấy toàn bộBuffer và vấn đề thường gặp
Vấn đề mixing cin và getline:
int age;
string name;
cin >> age; // Nhập 25 và nhấn Enter
getline(cin, name); // Lấy ký tự xuống dòng → name = ""
// Giải pháp:
cin >> age;
cin.ignore(); // Bỏ qua ký tự xuống dòng
getline(cin, name); // Bây giờ mới lấy tênKiểm tra lỗi nhập liệu
int number;
cout << "Nhập số: ";
if (cin >> number) {
cout << "Nhập thành công: " << number << endl;
} else {
cout << "Lỗi: Không phải số!" << endl;
cin.clear(); // Xóa flag lỗi
cin.ignore(1000, '\n'); // Bỏ qua input sai
}So sánh cin/cout vs printf/scanf
| Đặc điểm | cin/cout | printf/scanf |
|---|---|---|
| Type safety | An toàn kiểu | Không an toàn |
| Tốc độ | Chậm hơn | Nhanh hơn |
| Định dạng | Khó hơn | Dễ và linh hoạt |
| Đơn giản | Dễ sử dụng | Phức tạp hơn |
| C++ style | Modern | Legacy |
Tối ưu hóa I/O
// Tăng tốc độ I/O cho competitive programming
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);💻 Ví dụ minh họa
Chương trình nhập thông tin cá nhân
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main() {
string fullName, address;
int age;
double height, weight;
char gender;
cout << "=== ĐĂNG KÝ THÔNG TIN CÁ NHÂN ===" << endl;
// Nhập họ tên (có khoảng trắng)
cout << "Họ và tên: ";
getline(cin, fullName);
// Nhập tuổi
cout << "Tuổi: ";
cin >> age;
// Nhập giới tính
cout << "Giới tính (M/F): ";
cin >> gender;
// Nhập chiều cao và cân nặng
cout << "Chiều cao (cm): ";
cin >> height;
cout << "Cân nặng (kg): ";
cin >> weight;
// Xóa buffer trước khi dùng getline
cin.ignore();
// Nhập địa chỉ
cout << "Địa chỉ: ";
getline(cin, address);
// Tính BMI
double bmi = weight / ((height/100) * (height/100));
// Hiển thị thông tin với định dạng đẹp
cout << "\n" << string(40, '=') << endl;
cout << " THÔNG TIN CÁ NHÂN" << endl;
cout << string(40, '=') << endl;
cout << left; // Căn trái
cout << setw(15) << "Họ tên:" << fullName << endl;
cout << setw(15) << "Tuổi:" << age << " tuổi" << endl;
cout << setw(15) << "Giới tính:" << (gender == 'M' ? "Nam" : "Nữ") << endl;
cout << setw(15) << "Chiều cao:" << height << " cm" << endl;
cout << setw(15) << "Cân nặng:" << weight << " kg" << endl;
cout << setw(15) << "BMI:" << fixed << setprecision(1) << bmi << endl;
cout << setw(15) << "Địa chỉ:" << address << endl;
return 0;
}Kết quả chạy:
=== ĐĂNG KÝ THÔNG TIN CÁ NHÂN ===
Họ và tên: Nguyễn Văn A
Tuổi: 25
Giới tính (M/F): M
Chiều cao (cm): 175
Cân nặng (kg): 70
Địa chỉ: 123 Đường ABC, Quận 1, TP.HCM
========================================
THÔNG TIN CÁ NHÂN
========================================
Họ tên: Nguyễn Văn A
Tuổi: 25 tuổi
Giới tính: Nam
Chiều cao: 175 cm
Cân nặng: 70 kg
BMI: 22.9
Địa chỉ: 123 Đường ABC, Quận 1, TP.HCMChương trình in bảng nhân
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int number;
cout << "Nhập số để in bảng nhân: ";
cin >> number;
cout << "\n" << string(30, '=') << endl;
cout << " BẢNG NHÂN " << number << endl;
cout << string(30, '=') << endl;
for (int i = 1; i <= 10; i++) {
cout << setw(2) << number << " x "
<< setw(2) << i << " = "
<< setw(3) << (number * i) << endl;
}
return 0;
}Chương trình xử lý lỗi nhập liệu
#include <iostream>
#include <limits>
using namespace std;
int main() {
int number;
cout << "=== DEMO XỬ LÝ LỖI NHẬP LIỆU ===" << endl;
while (true) {
cout << "Nhập một số nguyên (1-100): ";
if (cin >> number) {
// Nhập thành công, kiểm tra phạm vi
if (number >= 1 && number <= 100) {
cout << "Bạn đã nhập: " << number << endl;
break; // Thoát vòng lặp
} else {
cout << "Lỗi: Số phải trong khoảng 1-100!" << endl;
}
} else {
// Nhập thất bại (không phải số)
cout << "Lỗi: Vui lòng nhập số nguyên!" << endl;
// Xóa cờ lỗi và buffer
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
cout << "Cảm ơn bạn đã nhập đúng!" << endl;
return 0;
}So sánh cin/cout vs printf/scanf
#include <iostream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main() {
int age = 25;
double height = 175.5;
string name = "Nguyen Van A";
cout << "=== DEMO CIN/COUT VS PRINTF/SCANF ===" << endl;
// Cách 1: cout với manipulators
cout << "\n1. Sử dụng cout:" << endl;
cout << "Tên: " << name << endl;
cout << "Tuổi: " << age << " tuổi" << endl;
cout << "Chiều cao: " << fixed << setprecision(1) << height << " cm" << endl;
// Cách 2: printf
cout << "\n2. Sử dụng printf:" << endl;
printf("Tên: %s\n", name.c_str());
printf("Tuổi: %d tuổi\n", age);
printf("Chiều cao: %.1f cm\n", height);
// Demo định dạng phức tạp với printf
cout << "\n3. Định dạng phức tạp với printf:" << endl;
printf("%-15s %3d tuổi %6.1f cm\n", name.c_str(), age, height);
printf("|%-10s|%5d|%8.2f|\n", "Tên", age, height);
// Demo định dạng với cout
cout << "\n4. Định dạng với cout:" << endl;
cout << left << setw(15) << name
<< right << setw(3) << age << " tuổi "
<< setw(6) << fixed << setprecision(1) << height << " cm" << endl;
return 0;
}🏋️ Thực hành
Bài tập 1: Máy tính tiền điện
Viết chương trình tính tiền điện:
- Nhập số kWh tiêu thụ
- Bậc 1 (0-50 kWh): 1,678 VNĐ/kWh
- Bậc 2 (51-100 kWh): 1,734 VNĐ/kWh
- Bậc 3 (101-200 kWh): 2,014 VNĐ/kWh
- Bậc 4 (201+ kWh): 2,536 VNĐ/kWh
Bài tập 2: Formatter numbers
Viết chương trình nhập một số thực và hiển thị theo nhiều định dạng:
- Số gốc
- 2 chữ số thập phân
- Dạng khoa học (scientific notation)
- Căn phải trong 15 ký tự
Bài tập 3: Input validation
Viết hàm nhập tuổi với validation:
- Phải là số nguyên
- Trong khoảng 1-120
- Cho phép nhập lại nếu sai
Bài tập 4: File simulation
Viết chương trình "giả lập" đọc file:
- Nhập nhiều dòng text (kết thúc bằng "END")
- Đếm số dòng, số từ, số ký tự
- Hiển thị thống kê
Lời giải chi tiết
Bài tập 1:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double kwh;
cout << "Nhập số kWh tiêu thụ: ";
cin >> kwh;
double total = 0;
if (kwh <= 50) {
total = kwh * 1678;
} else if (kwh <= 100) {
total = 50 * 1678 + (kwh - 50) * 1734;
} else if (kwh <= 200) {
total = 50 * 1678 + 50 * 1734 + (kwh - 100) * 2014;
} else {
total = 50 * 1678 + 50 * 1734 + 100 * 2014 + (kwh - 200) * 2536;
}
cout << "Tiền điện: " << fixed << setprecision(0) << total << " VNĐ" << endl;
return 0;
}Bài tập 2:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double number;
cout << "Nhập số thực: ";
cin >> number;
cout << "\nCác định dạng khác nhau:" << endl;
cout << "Số gốc: " << number << endl;
cout << "2 chữ số TP: " << fixed << setprecision(2) << number << endl;
cout << "Khoa học: " << scientific << number << endl;
cout << "Căn phải 15: " << fixed << setw(15) << number << endl;
return 0;
}Bài tập 3:
#include <iostream>
#include <limits>
using namespace std;
int inputAge() {
int age;
while (true) {
cout << "Nhập tuổi (1-120): ";
if (cin >> age && age >= 1 && age <= 120) {
return age;
} else {
cout << "Lỗi! Vui lòng nhập số từ 1-120." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
}
int main() {
int age = inputAge();
cout << "Tuổi hợp lệ: " << age << endl;
return 0;
}📋 Tóm tắt
🎯 Những gì đã học
- cout: Xuất dữ liệu với toán tử
<< - cin: Nhập dữ liệu với toán tử
>> - getline(): Nhập chuỗi có khoảng trắng
- Manipulators: setw(), setprecision(), fixed, left, right
- Error handling: Kiểm tra và xử lý lỗi nhập liệu
🔧 Best Practices
- Dùng
getline()cho chuỗi có khoảng trắng - Luôn kiểm tra tính hợp lệ của input
- Sử dụng
cin.ignore()khi mix cin và getline - Định dạng output cho dễ đọc
- Xử lý lỗi nhập liệu một cách graceful
🚀 Chuẩn bị cho bước tiếp theo
Bài học tiếp theo sẽ tìm hiểu về cấu trúc điều khiển (if, switch). Đảm bảo bạn đã:
- [x] Thành thạo cin/cout cơ bản
- [x] Biết cách nhập chuỗi có khoảng trắng
- [x] Sử dụng được manipulators để định dạng
- [x] Xử lý được lỗi nhập liệu
💡 Lời khuyên
"Input validation là rất quan trọng! Luôn giả định rằng người dùng sẽ nhập sai để viết code robust hơn."
Chuyển sang: Cấu trúc điều khiển để học về if, else, switch-case!