2017-02-14 26 views
7

Đây là câu hỏi C rất cơ bản, đến từ trang 18 của Kernighan và Ritchie.Tại sao không getchar() đọc các ký tự như backspace?

tôi đã biên soạn mã rất đơn giản này cho đếm ký tự đầu vào từ bàn phím:

#include <stdio.h> 

/* count characters in input; 1st version */ 
main() 
{ 
    long nc; 

    nc = 0; 
    while (getchar() != EOF) 
    ++nc; 
    printf("%1d\n", nc); 
} 

này biên dịch tốt, chạy tốt, và hoạt động khá nhiều như mong đợi tức là nếu tôi nhập "Hello World", nó trả về giá trị 11 khi tôi nhấn CTRLD để cung cấp ký tự EOF.

Điều gây nhầm lẫn là nếu tôi phạm sai lầm, tôi có thể sử dụng backspace để xóa ký tự và nhập lại chúng, và nó chỉ trả về số ký tự được hiển thị bởi terminal khi tôi gọi EOF.

Nếu mã đang đếm từng ký tự, bao gồm ký tự đặc biệt, nếu tôi nhập bốn ký tự, xóa hai ký tự và nhập hai ký tự khác, không được xuất với 8 ký tự (4 char + 2 del + 2 char) 4?

Tôi rõ ràng là sự hiểu lầm cách C xử lý backspace và cách/khi mã tăng biến nc?

+4

Việc chỉnh sửa được xử lý bởi ứng dụng đầu cuối, do đó, 'getchar' không bao giờ đọc xóa. –

+0

Lưu ý: Bạn nên sử dụng 'int main (void)' thay cho 'main()' như trước đây là giá trị hợp lệ theo tiêu chuẩn. –

+0

@CoolGuy: Trên thực tế, phiên bản thứ hai vẫn hợp lệ, nhưng là một di sản. Đó là một tính năng lỗi thời và có thể bị loại bỏ khỏi tiêu chuẩn. Nói rằng: có, phiên bản đầu tiên chắc chắn nên được sử dụng. Nói chung, các chữ ký kiểu mẫu nguyên mẫu nên được sử dụng cho các chức năng nói chung. – Olaf

Trả lời

5

Thông thường, phiên thiết bị đầu cuối của bạn đang chạy trong "chế độ dòng", nghĩa là, nó chỉ chuyển dữ liệu đến chương trình của bạn khi một dòng hoàn tất (ví dụ: bạn nhấn Quay lại, v.v.). Vì vậy, bạn chỉ nhìn thấy dòng như nó là hoàn thành (với bất kỳ chỉnh sửa đã được thực hiện trước khi chương trình của bạn bao giờ nhìn thấy bất cứ điều gì). Thông thường đây là một điều tốt, vì vậy mọi chương trình không cần phải xử lý xóa/etc.

Trên hầu hết các hệ thống (ví dụ như hệ thống dựa trên Unix, v.v.), có thể đặt thiết bị đầu cuối vào chế độ "thô" - nghĩa là mỗi ký tự được truyền như đã nhận cho chương trình. Ví dụ: trình chỉnh sửa văn bản hướng màn hình thường làm điều này.

5

Nó không phải là getchar() không tính "xóa" nhưng nó thậm chí không nhìn thấy đầu vào cho đến khi nó được chuyển đến chương trình của bạn bằng trình điều khiển thiết bị đầu cuối.

Khi bạn nhập nội dung nào đó, chương trình sẽ không tiếp cận chương trình C của bạn cho đến khi bạn nhấn \n hoặc gửi EOF (hoặc EOL). Đây là những gì POSIX định nghĩa là Canonical Mode Input Processing - thường là chế độ mặc định.

+0

Phải, tôi hiểu. Vì vậy, đây là nhiều hiểu lầm của tôi như thế nào các thiết bị đầu cuối hoạt động, chứ không phải là mã C chính nó. –

1

Ký tự backspace thường được sử dụng để chỉnh sửa đầu vào ở chế độ tty đã nấu (xem chế độ nhập chuẩn trong tty(4) trong BSD và termios(3) trong hệ thống Linux), vì vậy chúng được tiêu thụ tại trình điều khiển tty và không nhận được đầu vào quá trình sau đó. Điều tương tự cũng áp dụng cho Ctrl-D khi kết thúc tệp hoặc đến Ctrl-K làm ký tự nhập đầu vào. Có một số điều mà người lái xe làm đằng sau hậu trường mà quá trình của bạn không nhận được cuối cùng. Đây là hướng dẫn giúp người dùng và người lập trình dễ dàng hơn trong cuộc sống của bạn, vì bạn thường không muốn xóa đầu vào trong cuộc sống của mình (đó là lý do xóa nó) hoặc muốn kết thúc dòng là \n và không phải là \r. nhấn phím [RETURN]. Nhưng nếu bạn đọc từ một tệp xảy ra có khoảng trống, bạn sẽ nhận được chúng dưới dạng đầu vào bình thường, chỉ cần tạo tệp có không gian và cố đọc đầu vào chuyển hướng từ đó và bạn sẽ thấy các ký tự đó trong đầu vào của mình.

Bằng cách này, nếu bạn muốn tạo ra không gian ở đầu cuối, chỉ cần thêm một ký tự Ctrl-V trước mỗi (điều này cũng được quản lý ở trình điều khiển tty và sẽ không xảy ra khi đọc từ tệp) và bạn sẽ thấy backspace chars như đầu vào bình thường trong tập tin của bạn (để gửi một Ctrl-V chỉ cần gấp đôi nó)

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