Unix / Linux - Standard I/O Streams

Xin chào các pháp sư Linux tương lai! Hôm nay, chúng ta sẽ khám phá thế giới kỳ diệu của các luồng vào/ra tiêu chuẩn trong Unix và Linux. Đừng lo lắng nếu bạn là người mới bắt đầu lập trình - tôi sẽ là người hướng dẫn thân thiện của bạn trong cuộc phiêu lưu này, giống như tôi đã làm cho hàng trăm sinh viên trong những năm dạy học của mình. Vậy, hãy lấy cặp sách ảo của bạn và cùng khám phá nào!

Unix / Linux - Standard I/O Streams

什么是标准I/O Streams?

Trước khi chúng ta đi vào chi tiết, hãy hiểu Standard I/O Streams là gì. Hãy nghĩ về chúng như những kênh đặc biệt qua đó chương trình của bạn có thể giao tiếp với thế giới bên ngoài. Giống như con người chúng ta có những cách khác nhau để tương tác - nói, nghe và đôi khi la hét khi mọi thứ đi sai hướng - chương trình của chúng ta có những luồng này.

Có ba luồng chính:

  1. Standard Input (stdin)
  2. Standard Output (stdout)
  3. Standard Error (stderr)

Hãy phân tích chúng một bằng một.

Standard Input (stdin)

Standard Input, thường được viết tắt là stdin, giống như đôi tai của chương trình. Đây là cách chương trình lắng nghe thông tin từ người dùng hoặc các nguồn khác.

Ví dụ 1: Đọc từ stdin

#include <stdio.h>

int main() {
char name[50];
printf("What's your name? ");
scanf("%s", name);
printf("Hello, %s!\n", name);
return 0;
}

Trong ví dụ này, scanf đang đọc từ stdin. Khi bạn chạy chương trình này, nó chờ bạn gõ gì đó và nhấn Enter. Đó là stdin trong hành động!

Standard Output (stdout)

Standard Output, hoặc stdout, giống như miệng của chương trình. Đây là cách chương trình nói với chúng ta, hiển thị kết quả hoặc thông điệp.

Ví dụ 2: Ghi vào stdout

#include <stdio.h>

int main() {
printf("Hello, World!\n");
fprintf(stdout, "This also goes to stdout.\n");
return 0;
}

Cả printffprintf(stdout, ...) đều ghi vào stdout. Khi bạn chạy chương trình này, bạn sẽ thấy cả hai thông điệp được in ra trên terminal.

Standard Error (stderr)

Standard Error, hoặc stderr, giống như cách chương trình la hét khi có điều gì đó đi sai. Nó được sử dụng cho các thông báo lỗi và chẩn đoán.

Ví dụ 3: Sử dụng stderr

#include <stdio.h>

int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
fprintf(stderr, "Error: Could not open file!\n");
return 1;
}
// Rest of the code...
return 0;
}

Ở đây, nếu tệp không tồn tại, chúng ta sử dụng fprintf(stderr, ...) để in thông báo lỗi.

Điều hướng Streams

Bây giờ, hãy đi vào phần thực sự thú vị! Trong Unix/Linux, chúng ta có thể điều hướng các luồng này. Điều này giống như cho chương trình của chúng ta những đôi tai hoặc miệng khác nhau. Hãy để tôi chỉ cho bạn cách:

Điều hướng stdin

$ ./program < input.txt

Điều này lấy đầu vào từ input.txt thay vì từ bàn phím.

Điều hướng stdout

$ ./program > output.txt

Điều này gửi đầu ra vào output.txt thay vì màn hình.

Điều hướng stderr

$ ./program 2> error.txt

Điều này gửi các thông báo lỗi vào error.txt.

Pipes: Kết nối các Chương trình

Đây là một tuyệt chiêu: chúng ta có thể kết nối đầu ra của một chương trình vào đầu vào của một chương trình khác bằng cách sử dụng pipes (|). Điều này giống như các chương trình đang chơi một trò chơi điện thoại!

$ echo "Hello, World!" | wc -w

Điều này đếm số từ trong "Hello, World!". Đầu ra của echo trở thành đầu vào của wc.

Các Chức năng Standard I/O

Hãy xem xét một số chức năng phổ biến được sử dụng với các luồng này:

Function Description Stream
scanf Đọc đầu vào đã định dạng stdin
printf Ghi đầu ra đã định dạng stdout
fprintf Ghi đầu ra đã định dạng vào một luồng Bất kỳ
fgets Đọc một chuỗi Bất kỳ
fputs Ghi một chuỗi Bất kỳ
fread Đọc dữ liệu nhị phân Bất kỳ
fwrite Ghi dữ liệu nhị phân Bất kỳ

Một Câu Chuyện Cá Nhân

Tôi nhớ khi tôi dạy khái niệm này lần đầu tiên, một sinh viên đã hỏi, "Nhưng giáo sư, tại sao chúng ta cần các luồng khác nhau? Không thể chỉ sử dụng một cho mọi thứ được không?" Tôi mỉm cười và nói, "Hãy tưởng tượng bạn đang ở trong một nhà hàng ồn ào. Bạn nói để đặt thức ăn, nghe khi thức ăn của bạn sẵn sàng, và bạn có thể la hét nếu có vấn đề với订单 của bạn. Đó là lý do chúng ta có các luồng khác nhau - mỗi luồng có mục đích riêng!"

Kết luận

Hiểu về các luồng vào/ra tiêu chuẩn giống như học ABC của giao tiếp chương trình. Đây là nền tảng cho các khái niệm nâng cao hơn mà bạn sẽ gặp trong hành trình lập trình của mình. Nhớ rằng, mỗi nhà lập trình vĩ đại đều bắt đầu từ nơi bạn đang đứng bây giờ. Hãy tiếp tục luyện tập, 保持好奇心, và sớm bạn sẽstreaming dữ liệu như một chuyên gia!

Chúc mừng coding, các ngôi sao công nghệ tương lai! ?

Credits: Image by storyset