:quality(75)/fgets_0_b843c19278.jpg)
Hàm fgets() trong C là gì? Cách dùng fgets() hiệu quả và ví dụ chi tiết dễ hiểu
Trong quá trình học lập trình C, việc xử lý dữ liệu đầu vào là một kỹ năng rất quan trọng. Để đọc dữ liệu dạng chuỗi một cách hiệu quả và an toàn, lập trình viên thường sử dụng hàm fgets(). Vậy cụ thể fgets() là gì, cách hoạt động ra sao và sử dụng như thế nào cho đúng? Hãy cùng FPT Shop tìm hiểu chi tiết trong bài viết dưới đây.
Hàm fgets() trong C là gì?
Hàm fgets() là một hàm có sẵn (built-in) trong thư viện chuẩn <stdio.h> của ngôn ngữ C, được sử dụng để đọc một dòng văn bản từ luồng nhập (input). Luồng nhập này có thể là bàn phím hoặc tệp tin. Khi sử dụng, dữ liệu đọc được sẽ được lưu vào một mảng ký tự (char array) do lập trình viên khai báo trước.
Cụ thể, fgets() sẽ đọc dữ liệu và dừng lại khi gặp một trong các điều kiện sau:
- Đã đọc đủ số lượng ký tự tối đa cho phép (tối đa là n-1 ký tự).
- Gặp ký tự xuống dòng \n.
- Gặp ký hiệu kết thúc tệp (EOF - End Of File).
Sau khi đọc xong, hàm sẽ tự động thêm ký tự kết thúc chuỗi \0 vào cuối dữ liệu, giúp chuỗi trở thành chuỗi hợp lệ trong C. Đồng thời, con trỏ vị trí đọc trong file (nếu đọc từ file) cũng sẽ được di chuyển đến ký tự tiếp theo chưa được đọc.
Một điểm quan trọng khiến fgets() được sử dụng rộng rãi là khả năng kiểm soát kích thước dữ liệu đầu vào. Nhờ giới hạn số lượng ký tự cần đọc, hàm này giúp ngăn chặn tình trạng tràn bộ đệm (buffer overflow) - một lỗi nguy hiểm có thể gây crash chương trình hoặc tạo lỗ hổng bảo mật.
Ngoài ra, fgets() còn có thể đọc được cả một dòng văn bản bao gồm khoảng trắng, điều mà một số phương pháp nhập dữ liệu khác không làm được vì thường dừng ngay khi gặp dấu cách. Chính vì vậy, fgets() rất phù hợp khi cần xử lý chuỗi đầy đủ từ người dùng hoặc từ file.
Tóm lại, với tính an toàn cao, khả năng đọc linh hoạt và dễ sử dụng, fgets() là một trong những hàm quan trọng mà bất kỳ ai học lập trình C cũng nên nắm vững.

Cú pháp của hàm fgets()
Để sử dụng hiệu quả hàm fgets(), trước tiên bạn cần nắm rõ cú pháp chuẩn của hàm trong ngôn ngữ C. Việc hiểu đúng cú pháp sẽ giúp bạn tránh được các lỗi phổ biến khi xử lý dữ liệu đầu vào.
Dưới đây là phần khai báo cho hàm fgets() trong C:
char *fgets(char *str, int n, FILE *stream);
Trong đó:
- str: Đây là con trỏ tới một mảng các ký tự (char array), nơi mà chuỗi dữ liệu được đọc từ luồng input sẽ được lưu trữ. Bạn cần đảm bảo mảng này đã được cấp phát bộ nhớ với kích thước phù hợp trước khi gọi hàm fgets(). Sau khi đọc xong, dữ liệu sẽ được ghi trực tiếp vào mảng và kết thúc bằng ký tự null \0 để tạo thành chuỗi hợp lệ trong C.
- n: Đây là số ký tự tối đa mà hàm fgets() có thể đọc, bao gồm cả ký tự null kết thúc chuỗi. Điều này có nghĩa là hàm chỉ đọc tối đa n-1 ký tự thực tế từ luồng dữ liệu. Thông thường, giá trị của n sẽ được đặt bằng kích thước của mảng str để đảm bảo không xảy ra tình trạng tràn bộ đệm. Việc giới hạn số ký tự đọc là một trong những yếu tố giúp fgets() an toàn hơn khi xử lý chuỗi.
- stream: Đây là con trỏ tới một đối tượng kiểu FILE, đại diện cho luồng dữ liệu mà từ đó các ký tự sẽ được đọc. Luồng này có thể là stdin (nhập từ bàn phím) hoặc một file đã được mở bằng hàm fopen (hàm dùng để mở tệp và thiết lập kết nối với file để đọc hoặc ghi dữ liệu). Nhờ tham số này, fgets() có thể linh hoạt làm việc với nhiều nguồn dữ liệu khác nhau, không chỉ giới hạn ở input từ người dùng.
Nhìn chung, với cấu trúc trên, hàm fgets() sẽ đọc dữ liệu từ luồng stream, lưu vào mảng str với giới hạn tối đa là n-1 ký tự, sau đó tự động thêm ký tự kết thúc chuỗi \0. Nếu gặp ký tự xuống dòng \n hoặc đạt giới hạn trước đó, quá trình đọc sẽ dừng lại, giúp đảm bảo dữ liệu được xử lý chính xác và an toàn.
Để dễ hình dung, bạn có thể theo dõi ví dụ sau đây:
#include <stdio.h>
int main() {
FILE *fptr = fopen("in.txt", "r");
char str[30];
fgets(str, sizeof(str), fptr);
printf("%s", str);
fclose(fptr);
return 0;
}
Trong ví dụ trên, hàm fgets() sẽ đọc dữ liệu từ file in.txt và lưu vào mảng str với kích thước tối đa là 29 ký tự thực tế. Nếu nội dung trong file dài hơn, hàm chỉ lấy một phần tương ứng với kích thước đã khai báo, phần còn lại vẫn nằm trong luồng và có thể tiếp tục được đọc ở những lần gọi fgets() sau. Điều này giúp chương trình hoạt động ổn định và tránh được các lỗi liên quan đến tràn bộ nhớ.

So sánh fgets() với các hàm tương tự khác
So sánh fgets() và gets()
Để hiểu rõ hơn về ưu điểm của fgets(), việc đặt nó cạnh các hàm cũ là rất cần thiết. Một trong những hàm thường được đem ra so sánh là gets(), dù hiện nay đã không còn được khuyến nghị sử dụng.
| Tiêu chí | gets() | fgets() |
| Giới hạn số ký tự nhập | Không có giới hạn | Có giới hạn rõ ràng |
| Nguy cơ lỗi tràn bộ nhớ | Dễ gặp | Ít gặp hơn |
| Xử lý ký tự xuống dòng | Không giữ lại | Giữ lại |
| Nguồn dữ liệu | Chỉ nhập từ bàn phím | Nhập từ bàn phím và file |
| Tình trạng sử dụng | Không còn được dùng từ phiên bản C11 trở lên | Được khuyến nghị dùng |
Từ bảng trên, có thể thấy fgets() có khả năng kiểm soát dữ liệu tốt hơn và giảm thiểu rủi ro khi nhập chuỗi. Chính vì vậy, trong lập trình C hiện đại, fgets() gần như đã thay thế hoàn toàn gets().

So sánh fgets() và scanf()
Bên cạnh gets(), scanf() cũng là một hàm quen thuộc khi xử lý dữ liệu đầu vào trong C. Tuy nhiên, cách mà scanf() và fgets() đọc chuỗi lại có sự khác biệt rõ rệt.
| Tiêu chí | scanf() | fgets() |
| Kiểu dữ liệu đọc | Đọc theo định dạng (số, chuỗi,...) | Đọc cả dòng dưới dạng chuỗi |
| Giới hạn số ký tự nhập | Không giới hạn nếu không khai báo thêm | Có giới hạn rõ ràng |
| Điểm dừng khi đọc | Dừng khi gặp khoảng trắng | Dừng khi gặp xuống dòng hoặc đủ ký tự |
| Xử lý khoảng trắng | Không đọc được khoảng trắng trong chuỗi | Đọc được cả khoảng trắng |
| Nguy cơ lỗi tràn bộ nhớ | Dễ gặp nếu không giới hạn | Ít gặp hơn |
| Nguồn dữ liệu | Chủ yếu từ bàn phím | Từ bàn phím và file |
Từ sự so sánh này, có thể thấy fgets() phù hợp hơn khi cần đọc dữ liệu đầy đủ và chính xác từ người dùng. Do đó, trong các bài toán xử lý chuỗi thực tế, fgets() thường được ưu tiên sử dụng hơn scanf().

Những lưu ý khi sử dụng fgets()
Khi sử dụng fgets(), ngoài việc nắm rõ cú pháp, bạn cũng cần chú ý đến một số đặc điểm quan trọng để tránh lỗi trong quá trình xử lý dữ liệu. Những lưu ý dưới đây sẽ giúp bạn sử dụng hàm này hiệu quả và hạn chế các vấn đề không mong muốn.
- fgets() giữ lại ký tự xuống dòng: Khi người dùng nhấn Enter, ký tự xuống dòng \n sẽ được lưu vào chuỗi kết quả. Điều này có thể khiến dữ liệu hiển thị bị lệch hoặc gây sai sót khi so sánh chuỗi nếu bạn không xử lý trước.
- Dữ liệu dư vẫn còn trong bộ đệm: Nếu dữ liệu nhập vào dài hơn giới hạn cho phép, hàm fgets() chỉ đọc một phần và phần còn lại vẫn nằm trong luồng nhập. Điều này có thể ảnh hưởng đến các lần đọc tiếp theo nếu không được xử lý đúng cách.
- Luôn kiểm tra kết quả trả về: Trong một số trường hợp như gặp lỗi hoặc kết thúc file, hàm fgets() có thể không đọc được dữ liệu. Vì vậy, việc kiểm tra kết quả trước khi sử dụng sẽ giúp chương trình tránh được lỗi ngoài ý muốn.
Nhìn chung, việc hiểu rõ những lưu ý trên sẽ giúp bạn sử dụng fgets() một cách chính xác và an toàn hơn trong các chương trình C. Điều này không chỉ giúp hạn chế lỗi mà còn nâng cao chất lượng và độ ổn định của code.

Tạm kết
Qua bài viết trên, FPT Shop đã giúp bạn hiểu rõ hàm fgets() trong C, từ khái niệm, cú pháp đến cách sử dụng trong thực tế. Nhờ đó, bạn có thể áp dụng fgets() một cách chính xác để xử lý dữ liệu chuỗi an toàn và hiệu quả hơn. Việc nắm vững hàm fgets() cũng sẽ giúp bạn hạn chế lỗi và nâng cao chất lượng chương trình khi học và làm việc với ngôn ngữ C.
Nếu bạn đang cần một thiết bị hỗ trợ lập trình mượt mà, đừng quên tham khảo các mẫu laptop MSI tại FPT Shop. Với thiết kế hiện đại cùng cấu hình mạnh mẽ, những chiếc laptop này sẽ giúp bạn học tập và làm việc hiệu quả hơn mỗi ngày. Hãy đến với FPT Shop để trải nghiệm thực tế và lựa chọn sản phẩm phù hợp với nhu cầu của mình.
Xem thêm:
:quality(75)/estore-v2/img/fptshop-logo.png)
:quality(75)/Boolean_la_gi_ava_2afe2ac566.png)
:quality(75)/clion_0_f040ea9c72.png)
:quality(75)/small/3_df4d6d6a06.jpg)
:quality(75)/while_cover_5faec5e902.png)
:quality(75)/claude_code_e57846278b.png)
:quality(75)/Apple_Developers_la_gi_cover_b9601c9bdf.png)