Skip to content

📥 Input/Output với iostream

C++ sử dụng streams (luồng) để xử lý I/O. Stream là abstraction mạnh mẽ cho phép đọc/ghi từ console, files, và strings với cùng syntax.

Basic Output: std::cout

cpp
#include <iostream>

int main() {
    // Basic output
    std::cout << "Hello, PENALGO!" << std::endl;
    
    // Chaining << operator
    int age = 25;
    std::string name = "HPN";
    std::cout << "Name: " << name << ", Age: " << age << std::endl;
    
    // endl vs '\n'
    std::cout << "Line 1" << std::endl;  // Flush buffer
    std::cout << "Line 2\n";              // No flush, faster
    std::cout << "Line 3" << '\n';        // Same as above
    
    return 0;
}

💡 std::endl vs '\n'

  • std::endl = '\n' + flush buffer → chậm hơn
  • '\n' = chỉ newline → nhanh hơn cho output nhiều dòng
  • Dùng std::endl khi cần đảm bảo output xuất hiện ngay (debugging)

Basic Input: std::cin

cpp
#include <iostream>
#include <string>

int main() {
    // Input số
    int number;
    std::cout << "Nhập một số: ";
    std::cin >> number;
    std::cout << "Bạn nhập: " << number << std::endl;
    
    // Input nhiều giá trị
    int a, b;
    std::cout << "Nhập 2 số (cách nhau bởi space): ";
    std::cin >> a >> b;
    std::cout << "Tổng: " << (a + b) << std::endl;
    
    // ⚠️ Input string với std::cin chỉ đọc đến space
    std::string word;
    std::cout << "Nhập một từ: ";
    std::cin >> word;  // Chỉ nhận từ đầu tiên!
    std::cout << "Từ: " << word << std::endl;
    
    return 0;
}

std::getline() — Đọc cả dòng

cpp
#include <iostream>
#include <string>

int main() {
    std::string fullName;
    
    std::cout << "Nhập họ tên đầy đủ: ";
    std::getline(std::cin, fullName);  // Đọc cả dòng, bao gồm spaces
    
    std::cout << "Xin chào, " << fullName << "!" << std::endl;
    
    return 0;
}

⚠️ Mixing std::cin >> và std::getline

cpp
#include <iostream>
#include <string>

int main() {
    int age;
    std::string name;
    
    std::cout << "Nhập tuổi: ";
    std::cin >> age;
    
    // ❌ Bug! getline sẽ đọc newline còn sót lại từ cin >>
    std::cout << "Nhập tên: ";
    std::getline(std::cin, name);  // name sẽ rỗng!
    
    std::cout << "Name: '" << name << "'" << std::endl;  // ''
    
    return 0;
}

Fix:

cpp
std::cin >> age;
std::cin.ignore();  // Bỏ qua newline còn sót
std::getline(std::cin, name);

// Hoặc:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Output Formatting với <iomanip>

cpp
#include <iostream>
#include <iomanip>  // Cho setw, setprecision, etc.

int main() {
    // === setw: Set width ===
    std::cout << "=== setw demo ===" << std::endl;
    std::cout << std::setw(10) << 42 << std::endl;           // "        42"
    std::cout << std::setw(10) << std::left << 42 << std::endl;  // "42        "
    std::cout << std::setw(10) << std::right << 42 << std::endl; // "        42"
    
    // === setfill: Fill character ===
    std::cout << "\n=== setfill demo ===" << std::endl;
    std::cout << std::setfill('0') << std::setw(5) << 42 << std::endl;  // "00042"
    std::cout << std::setfill('-') << std::setw(10) << "Hi" << std::endl;  // "--------Hi"
    std::cout << std::setfill(' ');  // Reset
    
    // === Floating-point precision ===
    double pi = 3.141592653589793;
    
    std::cout << "\n=== precision demo ===" << std::endl;
    std::cout << "Default: " << pi << std::endl;                         // 3.14159
    std::cout << "setprecision(3): " << std::setprecision(3) << pi << std::endl;  // 3.14
    std::cout << "setprecision(10): " << std::setprecision(10) << pi << std::endl; // 3.141592654
    
    // === fixed vs scientific ===
    double bigNum = 1234567.89;
    
    std::cout << "\n=== fixed/scientific demo ===" << std::endl;
    std::cout << std::setprecision(2);
    std::cout << "Default: " << bigNum << std::endl;        // 1.2e+06
    std::cout << "Fixed: " << std::fixed << bigNum << std::endl;      // 1234567.89
    std::cout << "Scientific: " << std::scientific << bigNum << std::endl; // 1.23e+06
    
    return 0;
}

Table Formatting Example

cpp
#include <iostream>
#include <iomanip>
#include <string>

struct Product {
    std::string name;
    double price;
    int quantity;
};

int main() {
    Product products[] = {
        {"Laptop", 25000000, 5},
        {"Mouse", 500000, 20},
        {"Keyboard", 1500000, 15},
        {"Monitor", 8000000, 3}
    };
    
    // Print table header
    std::cout << std::left;
    std::cout << std::setw(15) << "Product"
              << std::setw(15) << "Price (VND)"
              << std::setw(10) << "Qty"
              << std::setw(18) << "Total" << std::endl;
    
    std::cout << std::setfill('-') << std::setw(58) << "" << std::endl;
    std::cout << std::setfill(' ');
    
    // Print rows
    double grandTotal = 0;
    for (const auto& p : products) {
        double total = p.price * p.quantity;
        grandTotal += total;
        
        std::cout << std::left << std::setw(15) << p.name
                  << std::right << std::setw(15) << std::fixed << std::setprecision(0) << p.price
                  << std::setw(10) << p.quantity
                  << std::setw(18) << total << std::endl;
    }
    
    std::cout << std::setfill('=') << std::setw(58) << "" << std::endl;
    std::cout << std::setfill(' ');
    std::cout << std::left << std::setw(40) << "Grand Total:"
              << std::right << std::setw(18) << grandTotal << std::endl;
    
    return 0;
}

Output:

Product        Price (VND)          Qty     Total
----------------------------------------------------------
Laptop              25000000         5        125000000
Mouse                 500000        20         10000000
Keyboard             1500000        15         22500000
Monitor              8000000         3         24000000
==========================================================
Grand Total:                                  181500000

std::cerr và std::clog

cpp
#include <iostream>

int main() {
    // std::cout — Standard output (buffered)
    std::cout << "Normal output" << std::endl;
    
    // std::cerr — Standard error (unbuffered, flushed immediately)
    std::cerr << "Error message!" << std::endl;
    
    // std::clog — Logging (buffered, goes to stderr)
    std::clog << "Log entry" << std::endl;
    
    // Trong terminal, bạn có thể redirect riêng:
    // ./program > output.txt 2> errors.txt
    
    return 0;
}

Input Validation

cpp
#include <iostream>
#include <limits>

int main() {
    int number;
    
    while (true) {
        std::cout << "Nhập một số nguyên: ";
        
        if (std::cin >> number) {
            break;  // Input hợp lệ
        } else {
            std::cout << "❌ Input không hợp lệ! Vui lòng nhập số." << std::endl;
            
            // Clear error flag
            std::cin.clear();
            
            // Discard invalid input
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }
    
    std::cout << "✅ Bạn nhập: " << number << std::endl;
    
    return 0;
}

📚 Tổng kết

ConceptUsage
std::coutOutput chuẩn (buffered)
std::cinInput chuẩn (đọc đến whitespace)
std::cerrError output (unbuffered)
std::getline()Đọc cả dòng bao gồm spaces
std::setw()Set column width
std::setprecision()Decimal precision
std::fixedFixed-point notation
cin.ignore()Skip characters in input buffer

➡️ Tiếp theo

Bạn đã nắm vững I/O! Tiếp theo: Exercises — 3 bài tập thực hành để củng cố kiến thức.