×

Đọc một chuỗi ký tự từ đầu vào chuẩn với hàm gets() trong C

Nhập một chuỗi ký tự từ đầu vào chuẩn là một thao tác thường gặp khi lập trình trong ngôn ngữ C. Để thực hiện điều này, lập trình viên có thể sử dụng hàm gets() - một hàm được cung cấp bởi thư viện chuẩn của ngôn ngữ C.

Đầu tiên, chúng ta cần hiểu gets() là gì và cách thức hoạt động của nó. Hàm gets() đọc toàn bộ một dòng từ stdin (đầu vào chuẩn) và lưu trữ nó vào bộ đệm ký tự được chỉ định. Ký tự dòng mới ('\n') tại cuối dòng nhập sẽ được thay thế bởi ký tự null ('\0'), đánh dấu kết thúc của chuỗi ký tự.

Tuy nhiên, hàm gets() đã được loại bỏ kể từ phiên bản C11 của chuẩn C do các vấn đề về bảo mật. Cụ thể, gets() không kiểm tra kích thước của bộ đệm nhận chuỗi ký tự đầu vào, dẫn đến nguy cơ tràn bộ đệm (buffer overflow) nếu đầu vào dài hơn kích thước bộ đệm.

Dưới đây là một ví dụ minh họa về việc sử dụng gets() nhưng lưu ý rằng hàm này không an toàn và việc sử dụng nó không được khuyến khích:

#include <stdio.h>

int main() {
    char buffer[100];
    
    printf("Nhập một chuỗi ký tự: ");
    gets(buffer);  // không an toàn, có thể dẫn đến tràn bộ đệm
    
    printf("Chuỗi bạn đã nhập: %s\n", buffer);
    
    return 0;
}

Để cải tiến và tránh nguy cơ bảo mật, lập trình viên nên sử dụng fgets() thay vì gets(). Hàm fgets() cho phép chỉ định kích thước của bộ đệm, đồng thời đảm bảo không đọc vượt quá giới hạn này, giúp ngăn chặn tràn bộ đệm:

#include <stdio.h>

int main() {
    char buffer[100];
    
    printf("Nhập một chuỗi ký tự: ");
    if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
        // Xóa ký tự dòng mới nếu có
        char *newline = strchr(buffer, '\n');
        if (newline) {
            *newline = '\0';
        }
        
        printf("Chuỗi bạn đã nhập: %s\n", buffer);
    } else {
        printf("Lỗi khi đọc chuỗi ký tự.\n");
    }
    
    return 0;
}

Trong ví dụ trên, hàm fgets() đọc tối đa sizeof(buffer) - 1 ký tự từ stdin và đảm bảo chuỗi ký tự được kết thúc bằng ký tự null ('\0'). Điều này giúp chương trình an toàn hơn và tránh các lỗi bảo mật liên quan đến tràn bộ đệm.

Tóm lại, mặc dù gets() là một công cụ tiện lợi để đọc chuỗi ký tự từ đầu vào chuẩn, nhưng các nhà phát triển nên chuyển sang sử dụng fgets() hoặc các hàm an toàn hơn để bảo vệ chương trình khỏi các lỗ hổng bảo mật.

Comments