Đọc và ghi file trong C++ với các cuộc thi lập trình

Học lập trình

Trong các cuộc thi lập trình, việc đọc và ghi file là một phần quan trọng khi xử lý dữ liệu đầu vào và xuất kết quả. Dưới đây là 2 cách thực hiện việc đọc và ghi file trong C++ một cách hiệu quả, phù hợp với yêu cầu của các cuộc thi lập trình.

Đọc và Ghi File Cơ Bản

C++ cung cấp thư viện <fstream> để làm việc với file. Các lớp chính được sử dụng là:

  • ifstream (input file stream): Dùng để đọc dữ liệu từ file.
  • ofstream (output file stream): Dùng để ghi dữ liệu vào file.
  • fstream: Kết hợp cả đọc và ghi.

Ví dụ:

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    // Mở file input
    ifstream inputFile("input.txt");
    if (!inputFile.is_open()) {
        cerr << "Không thể mở file input!" << endl;
        return 1;
    }

    // Mở file output
    ofstream outputFile("output.txt");
    if (!outputFile.is_open()) {
        cerr << "Không thể mở file output!" << endl;
        return 1;
    }

    int a, b;
    inputFile >> a >> b; // Đọc dữ liệu từ file input
    int sum = a + b;

    outputFile << sum << endl; // Ghi kết quả vào file output

    // Đóng file
    inputFile.close();
    outputFile.close();

    return 0;
}

Sử Dụng freopen Để Chuyển Hướng I/O

Trong các cuộc thi lập trình, thường có yêu cầu đọc dữ liệu từ file input.txt và ghi kết quả vào file output.txt. Thay vì sử dụng ifstreamofstream, bạn có thể sử dụng hàm freopen để chuyển hướng luồng nhập/xuất chuẩn (cincout) sang file.

Ví dụ:

#include <iostream>
using namespace std;

int main() {
    // Chuyển hướng cin từ file input.txt
    freopen("input.txt", "r", stdin);
    // Chuyển hướng cout sang file output.txt
    freopen("output.txt", "w", stdout);

    int a, b;
    cin >> a >> b; // Đọc từ file input.txt
    int sum = a + b;

    cout << sum << endl; // Ghi vào file output.txt

    return 0;
}

Ưu điểm của freopen:

  • Không cần quản lý việc mở/đóng file thủ công.
  • Code ngắn gọn và dễ đọc hơn.

Lưu ý:

  • Sau khi sử dụng freopen, tất cả các lệnh cincout sẽ tự động đọc/ghi từ/vào file thay vì bàn phím/màn hình.

Xử Lý Đầu Vào/Kết Quả Nhanh

Trong các cuộc thi lập trình, tốc độ xử lý là yếu tố quan trọng. Việc sử dụng cincout mặc định có thể chậm hơn so với scanfprintf. Để tối ưu hóa tốc độ, bạn có thể sử dụng các kỹ thuật sau:

Tắt đồng bộ giữa cin/coutstdio

std::ios::sync_with_stdio(false);
cin.tie(NULL);
  • sync_with_stdio(false): Tắt đồng bộ giữa cin/coutstdio.
  • cin.tie(NULL): Ngắt liên kết giữa cincout để tránh việc tự động flush buffer.

Ví dụ tối ưu hóa:

#include <iostream>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);

    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        cout << x * 2 << "\n";
    }

    return 0;
}

Lưu Ý Khi Làm Việc Với File

  • Kiểm tra file tồn tại: Luôn kiểm tra xem file có mở thành công hay không trước khi đọc/ghi.
  • Đóng file: Nếu sử dụng ifstream hoặc ofstream, hãy đảm bảo đóng file sau khi hoàn thành.
  • Định dạng dữ liệu: Đảm bảo rằng định dạng dữ liệu trong file đầu vào phù hợp với cách đọc trong chương trình.
  • Xử lý lỗi: Nếu có lỗi xảy ra (ví dụ: file không tồn tại, định dạng sai), hãy thông báo rõ ràng để dễ debug.

Tổng Kết

  • Sử dụng freopen để chuyển hướng cin/cout là cách phổ biến và tiện lợi trong các cuộc thi lập trình.
  • Để tối ưu hóa tốc độ, tắt đồng bộ giữa cin/coutstdio bằng ios::sync_with_stdio(false) cin.tie(NULL).
  • Luôn kiểm tra tính hợp lệ của file và đảm bảo đóng file sau khi sử dụng.

Hy vọng những thông tin trên sẽ giúp bạn tự tin hơn khi làm việc với file trong các cuộc thi lập trình!