2010-09-04 108 views
10

Tôi bối rối bởi một đoạn mã được tìm thấy trong một hàm Tôi đang học:C getchar vs scanf

char GetCommand(void) 
{ 
    char command; 

    do { 
     printf("Enter command (q=quit, n=new, l=list): "); 
     scanf("%c", &command); 
     Flush(); 
    } 
    while ((command != 'q') && (command != 'n') 
      && (command != 'l')); 

    printf("\n----------\n"); 
    return(command); 
} 

void Flush(void) { 
    while (getchar() != '\n') 
     ; 
} 

Những gì tôi không hoàn toàn hiểu đây là việc sử dụng các chức năng Flush(). Ý tôi là, cuốn sách tôi đọc giải thích nó bằng cách nói rằng nó ngăn cản người dùng nhập nhiều hơn một ký tự đơn và sau đó có nhân vật đó đọc khi họ được nhắc nhập vào lần thứ hai.

Điều tôi không hiểu là cách Flush() đang ngăn điều này xảy ra. Nó không làm bất cứ điều gì. Tất cả nó là một lệnh while. (Trong khi điều này là đúng ...... những gì ?????) Không có ý nghĩa.

Trả lời

8

getchar() có tác dụng phụ của việc xóa ký tự tiếp theo khỏi bộ đệm đầu vào. Vòng lặp trong số Flush đọc và loại bỏ các ký tự cho đến - và bao gồm - dòng mới \n kết thúc dòng.

Vì số scanf được yêu cầu đọc một và chỉ một ký tự (%c) điều này có tác dụng bỏ qua mọi thứ khác trên dòng nhập đó.

Nó có lẽ sẽ rõ ràng hơn nếu scanf là thay thế với

command = getchar(); 

nhưng nó thực sự là một ví dụ thường xấu vì nó không xử lý End Of File tốt.

Nói chung, scanf là tốt nhất bị lãng quên; fgetssscanf hoạt động tốt hơn nhiều khi một người chịu trách nhiệm nhận dữ liệu nhập và phương thức khác để phân tích cú pháp. scanf (và fscanf) cố gắng thực hiện quá nhiều công việc cùng một lúc.

+0

OHHHH, tôi không biết rằng getchar đã loại bỏ ký tự tiếp theo trong bộ đệm đầu vào - điều đó giải thích sự nhầm lẫn của tôi. Cảm ơn bạn. – startuprob

2

getchar đọc một ký tự từ đầu vào chuẩn. Nếu bạn đặt nó trong một vòng lặp while, nó sẽ tiếp tục đọc một ký tự cùng một lúc cho đến khi điều kiện là sai.

Chức năng Flush đang thực hiện là đọc cho đến khi nó gặp một dòng mới (\n). Đây là ký tự được tạo khi người dùng nhấn phím enter. Vì vậy, mã bạn đưa ra sẽ đọc một ký tự (tôi không rõ tại sao nó sử dụng scanf cho điều này thay vì chỉ đơn giản là getchar, sẽ nhanh hơn) và sau đó loại bỏ phần còn lại của đầu vào cho đến khi người dùng truy cập vào .

Nếu bạn đã nạp chương trình này foobar, nó sẽ mất f và loại bỏ oobar trong chức năng Flush. Nếu không gọi số flush, số f có thể chuyển đến một số scanf và số scanf thứ hai sẽ nhận được o đầu tiên.

+0

Tôi vẫn không hiểu. Chính xác thì Flush đang làm gì? Nó có vẻ tương đương với một điều kiện if statement nhưng không phải lệnh. Tôi hiểu rằng scanf sẽ giữ tất cả các đầu vào của người dùng và sau đó chạy lại nó, nhưng làm thế nào để Flush ngăn không cho nó chạy 'o' trên ví dụ của bạn? – startuprob

-1

sau Các mã ví dụ có thể giúp bạn tìm hiểu logic đằng sau sử dụng Flush():

std::cerr << "Save this data (y for yes/Enter for no)? "; 
int chr = getchar(); 
if(chr != '\n') while(getchar() != '\n'); // Flush() 
if(chr == 'y') 
    std::cerr << "The current data was saved\n"; 
Các vấn đề liên quan