2014-10-28 56 views
7

Nếu mã làSự khác biệt giữa nhận và scanf là gì?

scanf("%s\n",message) 

vs

gets(message) 

có gì khác biệt? Có vẻ như rằng cả hai trong số họ có được đầu vào tin nhắn.

+1

'scanf()' là Chuẩn C và 'được()' không phải là (nữa). – alk

+5

Có phải mọi người bỏ qua đề cập đến việc 'bị' không được dùng nữa? Ngay cả những câu trả lời được 4 tuổi nói để tránh 'bị' như bệnh dịch hạch. –

+1

@remyabel và họ cũng không đề cập đến rằng 'scanf()' là không an toàn bằng nhau ... và mọi người đều bỏ qua 'fgets()' nghèo nàn nên là Phương thức nhận đầu vào của người dùng. –

Trả lời

16

Sự khác biệt cơ bản [ám chỉ đến kịch bản cụ thể của bạn],

  • scanf() kết thúc lấy đầu vào khi gặp phải một whitespace, newline hoặc EOF

  • gets() xem xét khoảng trắng là một phần của chuỗi đầu vào và kết thúc dữ liệu nhập pon gặp phải newline hoặc EOF.

Tuy nhiên, để tránh tràn bộ đệm lỗi và để tránh rủi ro an ninh, nó an toàn hơn để sử dụng fgets().

+0

Lưu ý: 'scanf ("% s \ n ", tin nhắn)' hiện _not_ kết thúc lấy đầu vào khi gặp phải khoảng trắng, dòng mới. ''% s \ n "' làm cho 'scanf()' đến 1) quét tất cả các đầu vào khoảng trống trắng và loại bỏ chúng 2) quét trong tất cả các đầu vào không trắng và lưu chúng vào 'message', cuối cùng gắn thêm' ' \ 0'' 3) quét trong tất cả các đầu vào khoảng trống trắng và loại bỏ chúng cho đến khi gặp phải một 'char' không trắng, được đặt trở lại' stdin' cho cuộc gọi IO tiếp theo. – chux

+0

@chux Cảm ơn bạn đã làm rõ. Trong câu trả lời của tôi, bằng cách nói "lấy input' tôi có nghĩa là lưu trữ không-whitespaces vào bộ đệm được cung cấp' tin nhắn'. Tuy nhiên, nhận xét của bạn làm cho câu trả lời này hoàn tất. –

+0

Kính gửi Downvoter, thay vì chính sách downvote-and-run, nếu bạn quan tâm để lại một bình luận, nó sẽ giúp tôi cải thiện câu trả lời này (và những câu tiếp theo). Cảm ơn bạn. –

4

gets - Đọc ký tự từ stdin và lưu trữ chúng dưới dạng chuỗi.

scanf - Đọc dữ liệu từ thiết bị nhập chuẩn và lưu giữ chúng theo định dạng cụ thể int tuyên bố scanf như %d, %f, %s vv

4

Có một số. Một là get() sẽ chỉ nhận được dữ liệu chuỗi ký tự. Khác là được() sẽ chỉ nhận được một biến tại một thời điểm. scanf() mặt khác là một công cụ linh hoạt hơn nhiều. Nó có thể đọc nhiều mục của các kiểu dữ liệu khác nhau.

Trong ví dụ cụ thể mà bạn đã chọn, không có nhiều sự khác biệt.

3

được: ->

gets() reads a line from stdin into the buffer pointed to by s until 
either a terminating newline or EOF, which it replaces with a null byte ('\0'). 

LỖI: ->

Never use gets(). Because it is impossible to tell without knowing the 
    data in advance how many characters gets() will read, and because 
    gets() will continue to store characters past the end of the buffer, it 
    is extremely dangerous to use. It has been used to break computer 
    security. Use fgets() instead. 

scanf: ->

The scanf() function reads input from the standard input stream stdin; 

BUG

Some times scanf makes boundary problems when deals with array and 
string concepts. 
+2

Vui lòng nêu rõ nguồn nếu bạn trích dẫn nội dung nào đó và sử dụng định dạng trích dẫn. – Lundin

6

Định hướng: Trong ngữ cảnh sau, tôi sẽ xem xét "an toàn" nếu không dẫn đến sự cố khi sử dụng chính xác. Và "không an toàn" nếu "mất an toàn" không thể được điều động xung quanh.

scanf("%s\n",message) 

vs

gets(message) 

sự khác biệt là gì?

Về mặt an toàn không có sự khác biệt, cả hai đọc từ Standard Input và might rất tốt tràn message, nếu người dùng nhập dữ liệu nhiều hơn thì message cung cấp bộ nhớ cho.

Trong khi scanf() cho phép bạn được sử dụng một cách an toàn bằng cách xác định số tiền tối đa của dữ liệu được quét trong:

char message[42]; 

... 

scanf("%41s", message); /* Only read in one few then the buffer (messega here) 
          provides as one byte is necessary to store the 
          C-"string"'s 0-terminator. */ 

Với gets() nó là không thể xác định số ký tự tối đa được đọc, đó là lý do tại sao sau này sẽ không được sử dụng!

+0

scanf() kém an toàn hơn so với khi sử dụng, vì sự an toàn loại giảm. – Lundin

+0

Vâng, nhưng để bắt đầu tranh luận về điều này, người ta có thể xác định tốt hơn "* an toàn *" trước đây. @Lundin – alk

+0

An toàn như trong "được biết là gây ra lỗi, hành vi kém và chương trình bị treo"? Tôi không thể nghĩ ra nhiều chức năng kém an toàn hơn trong ngôn ngữ C. – Lundin

2

Trong trường hợp scanf bạn cần định dạng đó được đề cập, không giống như khi tải. Vì vậy, trong gets bạn nhập charecters, strings, numbers và spaces.

Trong trường hợp scanf, bạn nhập sẽ kết thúc ngay khi gặp phải không gian trắng.

Nhưng sau đó trong ví dụ bạn đang sử dụng '% s', không, gets() cũng không phải scanf() là các chuỗi là các con trỏ hợp lệ cho các mảng đủ độ dài để giữ các ký tự bạn đang gửi cho chúng. Do đó có thể dễ dàng gây ra tràn bộ đệm.

Mẹo: sử dụng fgets(), nhưng tất cả phụ thuộc vào trường hợp sử dụng

4

Sự khác biệt chính là gets lần đọc cho đến EOF hoặc \n, trong khi scanf("%s") đọc cho đến khi gặp bất kỳ khoảng trống nào. scanf cũng cung cấp nhiều tùy chọn định dạng hơn, nhưng đồng thời nó có độ an toàn loại kém hơn gets.

Một khác biệt lớn là scanf là hàm C tiêu chuẩn, trong khi gets đã bị xóa khỏi ngôn ngữ, vì nó vừa là thừa và nguy hiểm: không có sự bảo vệ chống tràn bộ đệm. Các lỗ hổng bảo mật rất giống nhau tồn tại với scanf tuy nhiên, do đó, không nên sử dụng hai hàm nào trong mã sản xuất.

Bạn nên luôn luôn sử dụng fgets, tiêu chuẩn C bản thân thậm chí khuyến cáo này, xem C11 K.3.5.4.1

Đề xuất thực hành

6 Chức năng fgets phép đúng cách viết chương trình xử lý an toàn các dòng nhập liệu quá lâu để lưu trữ trong mảng kết quả . 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 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ì be_s.

(tôi nhấn mạnh)

+2

Lưu ý: 'scanf ("% s ")' đọc và loại bỏ bất kỳ khoảng trống trắng và _then_ quét và tiết kiệm không gian trắng cho đến khi một khoảng trắng tiếp theo hoặc 'EOF'. – chux

0

Khái niệm rằng scanf không mất không gian trắng là hoàn toàn sai. Nếu bạn sử dụng phần mã này, nó cũng sẽ có khoảng trắng trắng:

#include<stdio.h> 
int main() 
{ 
char name[25]; 
printf("Enter your name :\n"); 
scanf("%[^\n]s",name); 
printf("%s",name); 
return 0; 
} 

Trường hợp sử dụng dòng mới sẽ chỉ dừng đầu vào. Điều đó có nghĩa là nếu bạn nhấn enter chỉ sau đó nó sẽ ngừng tham gia đầu vào.

Vì vậy, về cơ bản không có sự khác biệt giữa chức năng quét và nhận. Nó chỉ là một cách thực hiện phức tạp.

0

được() không an toàn, ví dụ: char str [1]; được (str) nếu bạn nhập nhiều hơn thì độ dài, nó sẽ kết thúc bằng SIGSEGV. nếu chỉ có thể sử dụng được, sử dụng malloc làm biến cơ sở.

0

scanf() là công cụ linh hoạt hơn nhiều trong khi gets() chỉ nhận được một biến tại một thời điểm.

+0

Điều này không cung cấp câu trả lời cho câu hỏi. Khi bạn có đủ [danh tiếng] (https://stackoverflow.com/help/whats-reputation), bạn sẽ có thể [nhận xét về bất kỳ bài đăng nào] (https://stackoverflow.com/help/privileges/comment); thay vào đó, [cung cấp câu trả lời không yêu cầu làm rõ từ người hỏi] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do-thay thế). - [Từ đánh giá] (/ đánh giá/bài đăng chất lượng thấp/17482315) – Mayur

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