×

Đẩy ký tự trở lại dòng đầu vào đã đọc với ungetc() trong C

Trong lập trình C, khi làm việc với đầu vào đầu ra, có lúc chúng ta cần đọc trước một ký tự từ tập tin hoặc đầu vào chuẩn, nhưng sau đó muốn đưa ký tự đó quay trở lại để lần sau có thể đọc lại một cách chính xác. Thực hiện điều này có thể sử dụng hàm ungetc(). Đây là một công cụ hữu ích khi bạn cần giải quyết các vấn đề xử lý đầu vào phức tạp hoặc phải dự đoán các ký tự tiếp theo trong dòng đọc.

Hàm ungetc() có chức năng đẩy một ký tự trở lại dòng đầu vào mà từ đó nó được đọc. Cụ thể, nó đặt ký tự chỉ định trở lại vào dòng đầu vào để lần đọc kế tiếp từ dòng này sẽ nhận được ký tự này đầu tiên.

Cú pháp của ungetc()

int ungetc(int ch, FILE *stream);
  • ch: Ký tự bạn muốn đẩy trở lại vào dòng đầu vào. Ký tự này sẽ được đọc trước trong lần gọi fgetc() hoặc một hàm đọc tương tự kế tiếp.
  • stream: Con trỏ đến đối tượng FILE tương ứng với dòng mà bạn muốn đẩy ký tự trở lại.

Giá trị trả về:

  • Nếu thành công, ch sẽ được trả về.
  • Nếu thất bại (ví dụ, nếu dòng đầu vào không hỗ trợ chức năng này), hàm trả về EOF và không thay đổi dòng đầu vào.

Ví dụ minh họa

Dưới đây là một ví dụ minh họa cách sử dụng ungetc():

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        perror("Failed to open file");
        return 1;
    }

    int ch = fgetc(fp);
    
    if (ch != EOF) {
        printf("Read character: %c\n", ch);
        
        // Đẩy ký tự trở lại dòng đầu vào
        if (ungetc(ch, fp) == EOF) {
            perror("Failed to push character back");
        } else {
            printf("Character pushed back to stream\n");
        }
        
        // Đọc lại ký tự đó
        ch = fgetc(fp);
        printf("Read character again: %c\n", ch);
    }

    fclose(fp);
    return 0;
}

Trong ví dụ trên, chương trình sẽ mở một tệp tin có tên example.txt và đọc một ký tự từ đó. Sau khi đọc, chương trình sẽ đẩy ký tự này trở lại dòng đầu vào và sau đó đọc lại chính ký tự đó.

Ứng dụng của ungetc()

Hàm này đặc biệt hữu ích trong các tình huống phân tích cú pháp (parsing) hoặc khi cần xử lý ngôn ngữ lập trình. Ví dụ, khi cần xác định xem dấu "-" trong một ngôn ngữ là dấu trừ hay kí tự gạch ngang (hyphen), bạn có thể đọc ký tự tiếp theo, xác định loại nó, và đưa ký tự đó trở lại dòng đầu vào nếu không phù hợp.

Một tình huống khác sẽ là khi bạn cần hiện thực một bộ giải mã hoặc bộ phân tích cú pháp mà cần phải dự đoán ký tự tiếp theo trước khi xác định cú pháp cụ thể.

Các giới hạn

  • Số lần sử dụng liên tiếp: Nhiều hệ thống chỉ cho phép một ký tự được đẩy trở lại mỗi lần. Nếu cố gắng đẩy nhiều ký tự liên tiếp, bạn có thể nhận được lỗi.
  • Dữ liệu nhị phân: Hành vi của ungetc() trên dữ liệu nhị phân có thể không được đảm bảo trên tất cả các hệ thống.

Kết luận

Việc sử dụng hàm ungetc() trong C giúp lập trình viên đạt lợi thế trong xử lý đầu vào phức tạp, đặc biệt là trong các ứng dụng cần phải kiểm tra trước ký tự kế tiếp mà không làm mất dữ liệu đầu vào. Tuy nhiên, nó cần được sử dụng cẩn thận do một vài giới hạn đã nêu. Thấu hiểu các đặc điểm này giúp bạn sử dụng một cách hợp lý và đạt được hiệu quả tối ưu trong các ứng dụng cụ thể của mình.

Comments