2012-10-15 28 views
20

Từ cplusplus.comĐiều gì sẽ được() tương đương trong C11?

Các phiên bản gần đây nhất của tiêu chuẩn C (2011) đã dứt khoát loại bỏ chức năng này từ đặc điểm kỹ thuật

Chức năng bị phản đối trong C++ (của nó như là tiêu chuẩn năm 2011, mà sau C99 + TC3).

Tôi chỉ muốn biết phương án thay thế cho gets() trong tiêu chuẩn C11 là gì?

+2

fgets (..., ..., stdin) –

Trả lời

15

Trong C11 gets đã được thay thế bằng gets_s có khai báo như sau:

char *gets_s(char *str, rsize_t n); 

Chức năng này sẽ đọc nhiều nhất n-1 chars từ stdin vào *str. Điều này là để tránh lỗ hổng tràn bộ đệm vốn có là gets. Chức năng fgets cũng là một lựa chọn. Từ http://en.cppreference.com/w/c/io/gets:

Các được() chức năng không thực hiện kiểm tra giới hạn, do đó chức năng này là cực kỳ lỗ hổng bị tràn tấn công. Nó không thể được sử dụng một cách an toàn (trừ khi chương trình chạy trong môi trường hạn chế những gì có thể xuất hiện trên stdin). Vì lý do này, chức năng này đã không được chấp nhận trong bản sửa đổi thứ ba đối với tiêu chuẩn C99 và được loại bỏ hoàn toàn theo tiêu chuẩn C11. fgets()gets_s() là các thay thế được đề xuất.

Không bao giờ sử dụng được().

Được xác định trong phần mở rộng cho tiêu chuẩn, chỉ được triển khai tùy chọn, bạn có thể viết chương trình của mình bằng cách sử dụng fgets thay thế. Nếu bạn sử dụng fgets trên stdin, chương trình của bạn cũng sẽ biên dịch trong các phiên bản trước của C. Nhưng hãy ghi nhớ sự khác biệt trong hành vi: khi gets_s đọc n-1 ký tự nó tiếp tục đọc cho đến khi dòng mới hoặc cuối tập tin được truy cập , loại bỏ đầu vào. Vì vậy, với gets_s bạn luôn đọc toàn bộ dòng, ngay cả khi chỉ một phần của nó có thể được trả lại trong bộ đệm đầu vào.

+6

Cần lưu ý rằng 'get_s' là tùy chọn, không cần phải hiện diện nếu việc triển khai không xác định' __STDC_LIB_EXT1__', và nếu có, cần '__STDC_WANT_LIB_EXT1__' được định nghĩa là 1 (nếu không được xác định ở tất cả, đó là triển khai- xác định xem các hàm trong phụ lục K có được bao gồm trong các tiêu đề tương ứng) hay không. –

+6

'fgets' nên được sử dụng. 'gets_s' là một giao diện tùy chọn chỉ tồn tại trên Windows và được đề cập trong tiêu chuẩn chỉ vì lý do chính trị.Khá nhiều người bên ngoài MS thấy các giao diện _s sai lầm và có hại. Được biết, hành vi chuẩn hóa của một số hoặc tất cả các giao diện _s thậm chí khác với các triển khai hiện có duy nhất (các MS), làm cho việc sử dụng chúng thậm chí còn có hại hơn. –

+0

Tôi nghi ngờ rằng bạn đã hiểu sai hành vi của gets_s. Cũng giống như fgets, nó đọc nhiều nhất n-1 ký tự. Sự khác biệt là get_s dừng nếu nó gặp một ký tự dòng mới. Không có gì trong tiêu chuẩn chỉ ra rằng nó tiếp tục đọc sau n-1. Đừng nhầm lẫn giữa phiên bản tiêu chuẩn với các triển khai không chuẩn khác nhau đã tồn tại trước C11. – Lundin

4

Theo man 3 gets, fgets.

+0

Tương đương với tiêu chuẩn C11 là get_s, mặc dù về mặt kỹ thuật, nó cũng giống như fgets (..., stdin); – Lundin

+1

"Trong một phụ lục tùy chọn được thêm vào vì lý do chính trị" là khó "trong tiêu chuẩn C11". Bạn sẽ không tìm thấy phiên bản tuân thủ C11 của các hàm _s ở bất kỳ đâu, bởi vì không ai có kế hoạch triển khai chúng. –

+2

@R .. Phụ lục K của C11 là tiêu chuẩn, mặc dù không bắt buộc phải thực hiện. Điều này có nghĩa là trong thực tế, là việc triển khai C có thể không còn chứa hàm get_s lạ, phi tiêu chuẩn có hành vi va chạm với tiêu chuẩn. Tôi cũng đặt cược rằng GCC sẽ thực hiện các chức năng này: trình biên dịch đó chỉ yêu các tính năng tùy chọn, dư thừa, vô nghĩa. Tuy nhiên tôi sẽ khuyên bạn nên fgets(), vì lý do tương thích. – Lundin

8

Những người khác đã trả lời câu hỏi. Vì mục đích hoàn chỉnh, đây là khuyến nghị của tiêu chuẩn C:

ISO9899: 2011 K.3.5.4.1/6

Đề xuất thực hành

Chức năng fgets phép các chương trình đúng như các văn bản để xử lý một cách an toàn đường dây đầu vào quá dài để lưu trữ trong các kết quả mảng. Nói chung điều này đòi hỏi người gọi của fgets chú ý đến sự hiện diện hoặc vắng mặt của một ký tự dòng mới trong mảng kết quả. Cân nhắc sử dụng các fgets (cùng với bất kỳ xử lý cần thiết nào dựa trên ký tự dòng mới) thay vì get_s.

Vì vậy, bạn nên sử dụng fgets bất cứ khi nào có thể.

EDIT

gets_s hành vi được quy định là:

ISO9899: 2011 K.3.5.4.1/4

Mô tả

Chức năng gets_s đọc nhiều nhất một nhỏ hơn số ký tự được chỉ định bởi n từ luồng được chỉ định bởi stdin, vào mảng được trỏ tới bởi s. Không có thêm ký tự nào được đọc sau ký tự dòng mới (được bỏ đi) hoặc sau khi kết thúc tệp. Ký tự dòng mới bị hủy không được tính vào số ký tự đã đọc. Ký tự null được viết ngay sau ký tự cuối cùng được đọc vào mảng.

Nếu kết thúc tệp và không có ký tự nào được đọc vào mảng hoặc nếu lỗi đọc xảy ra trong quá trình hoạt động, thì s [0] được đặt thành ký tự rỗng và các yếu tố khác trong số các giá trị không xác định.

+3

Lưu ý rằng 'gets_s()' báo cáo một sự vi phạm ràng buộc nếu không có một dòng mới hay EOF trong các ký tự 'n-1'; đó là một lỗi để có được một dòng quá dài. –

Các vấn đề liên quan