Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Xóa bộ đệm đầu vào (Clear input buffer) trong C/C++

Vấn đề phổ biến: sau scanf(), ký tự newline \n còn lại trong buffer khiến fgets() hoặc getchar() tiếp theo đọc ngay dòng trống.

C - Các phương pháp

1. fflush(stdin) - KHÔNG CHUẨN (Chỉ MSVC hỗ trợ)

// CHỈ HOẠT ĐỘNG TRÊN MSVC (Windows)
fflush(stdin); // Undefined behavior theo chuẩn C!

2. Vòng lặp đọc hết ký tự (Portable, khuyến nghị)

void clearInputBuffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF) {
        // Bỏ qua ký tự
    }
}

3. scanf với format specifier (Đọc và bỏ qua whitespace)

// Dấu space trước %c bỏ qua mọi whitespace (kể cả \n)
scanf(" %c", &ch); // Space quan trọng!

// %*c đọc và hủy 1 ký tự
scanf("%d%*c", &num); // Đọc int, bỏ 1 ký tự (thường là \n)

4. fgets + sscanf (An toàn nhất)

char line[256];
if (fgets(line, sizeof(line), stdin)) {
    sscanf(line, "%d", &num);
    // Buffer đã sạch vì fgets đọc hết dòng
}

C++ - std::cin

1. cin.ignore() - Chuẩn C++

#include <iostream>
#include <limits>

int main() {
    int n;
    std::cin >> n;
    
    // Bỏ qua đến newline hoặc max stream size
    std::cin.ignore(std::numeric_limits::max(), '\n');
    
    // Bây giờ getline an toàn
    std::string line;
    std::getline(std::cin, line);
}

2. ws manipulator (Bỏ qua whitespace)

std::string line;
std::getline(std::cin >> std::ws, line); // Bỏ whitespace đầu, đọc dòng

Ví dụ hoàn chỉnh C++

#include <iostream>
#include <string>
#include <limits>

int main() {
    int age;
    std::string name;
    
    std::cout << "Tuổi: ";
    std::cin >> age;
    
    // XÓA BUFFER - QUAN TRỌNG
    std::cin.ignore(std::numeric_limits::max(), '\n');
    
    std::cout << "Tên: ";
    std::getline(std::cin, name);
    
    std::cout << "Tuổi: " << age << ", Tên: " << name << '\n';
    return 0;
}

So sánh phương pháp

Best Practice

  • C: Luôn dùng fgets() đọc dòng, sau đó sscanf() parse. Tránh scanf() trực tiếp.
  • C++: Dùng std::getline() cho string, std::cin >> var cho số + cin.ignore() sau đó.
  • Không bao giờ dùng gets() (removed C11) hoặc fflush(stdin).
Phương phápNgôn ngữPortableAn toànKhuyến nghị
fflush(stdin)CKhông (chỉ MSVC)UBKHÔNG DÙNG
while(getchar()!='\n')CCóCóOK
scanf(" %c")CCóCó (cho char)OK cho char
fgets + sscanfCCóRất an toànKHUYẾN NGHỊ
cin.ignore()C++CóCóKHUYẾN NGHỊ
cin >> wsC++CóCóOK cho string