2008-12-05 33 views
7

Bất kỳ ý tưởng nào tại sao mã sau không in số lượng ký tự trong đầu vào? Tôi đã lấy trực tiếp từ cuốn sách R & R. Học C tại thời điểm này và điều này thực sự khó hiểu, nhìn tôi như tôi chưa bao giờ đạt đến EOF. Nếu đó là trường hợp thì tại sao điều này sẽ được sử dụng làm ví dụ?Bài tập Lập trình C từ Sách K & R

#include <stdio.h> 

main() 
{ 
    double nc; 

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

Trả lời

12

Chương trình có vẻ chính xác, vấn đề của bạn là bạn phải gửi EOF (cuối tệp) vào dòng lệnh sau khi nhập của bạn vì đầu vào chuẩn được coi là tệp. Tôi nghĩ rằng trong một thiết bị đầu cuối Linux, bạn có thể nhấn Ctrl + D để gửi EOF ... Tôi không chắc chắn làm thế nào để làm điều đó trong hệ điều hành khác. Để kiểm tra chương trình này, bạn có thể muốn thay đổi EOF thành '\n' sẽ làm cho nó dừng lại khi bạn nhấn enter.

+1

CTRL Z trong vùng đất số – EvilTeach

+0

Tại sao tôi nhận được hai phiếu giảm giá? –

+1

FWIW, tôi không downvote bạn. Tuy nhiên, không có những thứ như một nhân vật EOF, vì vậy đó có thể là lý do tại sao. Khi người dùng nhấn^D (hoặc bất kỳ điều gì) trên một thiết bị đầu cuối, nó gây ra một điều kiện EOF trên quá trình 'stdin (nó được đóng bởi shell), không có nhân vật nào liên quan. – Chris

1

Mã này đọc ký tự từ đầu vào chuẩn. Khi bạn chạy chương trình này bình thường, đầu vào tiêu chuẩn đến từ người dùng. Trong trường hợp này, không có cách nào để gửi EOF cho chương trình.

Mã này sẽ hoạt động nếu bạn chuyển hướng tệp đến tiêu chuẩn trong (./myprogram < tempfile.txt).

+0

Tại sao nó được sử dụng làm ví dụ ane trong biểu mẫu hiện tại của nó khi không có cách nào (ở dạng dự định hiện tại) để truy cập chức năng printf? –

+0

Bạn có chắc chắn họ không muốn bạn sử dụng chuyển hướng? Ngoài ra nếu bạn gõ nó chính xác như ví dụ xuất hiện, thì có vẻ như cuốn sách này khá cũ, có thể nó được sử dụng để làm việc, hoặc làm việc trên một nền tảng cụ thể (có thể không còn xung quanh nữa, như DOS). – SoapBox

+0

Đặc biệt định nghĩa của hàm main(), trong đó không có kiểu trả về, và việc sử dụng double cho vòng lặp làm cho tôi đặt câu hỏi về độ tuổi và tính hữu ích của cuốn sách này. – SoapBox

7

Chương trình giữ đọc dữ liệu từ stdin cho đến khi EOF nhận được, điều này được thực hiện bằng cách nhấn Ctrl-D vào đầu của một dòng trên một giao diện điều khiển Unix hoặc Ctrl-Z vào đầu của một dòng trong một cửa sổ giao diện điều khiển. Sau khi bạn báo hiệu EOF theo cách này, chức năng printf sẽ được thực hiện hiển thị số lượng ký tự đã đọc.

6

nc của bạn là sử dụng hai lần printf("%lf", nc) để in tăng gấp đôi.

Hãy thử này thay vì

#include <stdio.h> 

int main(void) 
{ 
    int nc; 

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

    return 0; 
} 
+0

Ooh, xe bán tải tốt. –

+0

Mặc dù hơi sai,% f là để tăng gấp đôi. Nó cũng có thể được sử dụng cho phao do quảng cáo trên các hàm đối số biến. – Chris

+0

Cảm ơn nhưng tôi sẽ gắn bó với% lf, như sách hay nói #include int main (void) { long float x = 3.14159265358979; float y = 3.14159265358979f; printf ("% 15.10f \ n", y);/* 3.1415927410 */ printf ("% 15.10lf \ n", x);/* 3.1415926536 */ trả lại 0; } – EvilTeach

5

Tôi muốn làm rõ câu trả lời cho đến nay vì họ dường như sử dụng cụm từ như "gửi EOF", "nhận EOF", "nhân vật EOF", vv Theo nhận xét (cảm ơn) cho câu trả lời này, "gửi EOF" và "nhận EOF" là các điều khoản hợp pháp, nhưng xin đừng nghĩ rằng đó là một nhân vật.

EOF không phải là một ký tự nào cả. Đó là giá trị getchar() (hoặc fgetc/getc) trả về nếu luồng ở "cuối tập tin" hoặc lỗi đọc xảy ra. Nó chỉ đơn thuần là một giá trị đặc biệt nằm ngoài phạm vi giá trị ký tự mà getchar() sẽ trả về cho biết điều kiện lỗi hoặc cuối tệp.

Nó được xác định bởi tiêu chuẩn C là âm, trong khi getchar trả về các ký tự dưới dạng ký tự chưa được chuyển đổi thành int.

Chỉnh sửa: Khi thực hiện một số nghiên cứu mà tôi nên thực hiện trước đoạn tôi viết đã từng ở đây, tôi đã nhận ra một số giả định của tôi hoàn toàn sai. Cảm ơn người bình luận đã chỉ ra điều này.

Khi một luồng (như stdin) ở điều kiện cuối tệp, điều kiện này có thể được xóa lại với clearerr() và getchar() có thể đọc thêm dữ liệu từ stdin.

+0

Wow, có rất nhiều điều chỉnh ở đây: 1) không ai gọi EOF là ký tự, 2) "gửi/nhận EOF" là các cụm từ hoàn toàn hợp pháp, 3) thiết bị đầu cuối điều khiển không đóng các tệp của bạn, 4) stdin không bị đóng khi EOF được trả về từ getchar, bạn có thể tiếp tục đọc từ stdin sau khi nhận EOF ... –

+0

1) Trên thực tế Jeremy Ruten đã làm, và tôi sửa chữa anh ta và ông đã chỉnh sửa câu trả lời của mình; xem lịch sử sửa đổi. 2) Được rồi 3) Tôi nên nói vỏ 4) Chắc chắn, bạn có thể tiếp tục đọc từ stdin nhưng bạn sẽ chỉ tiếp tục nhận được EOF. Nếu bạn không đồng ý, vui lòng cung cấp minh họa. – Chris

+0

Xin lỗi, khi thực hiện nghiên cứu của riêng tôi, có vẻ như bạn cũng đúng về 4 người. Cảm ơn. – Chris

0

Đầu tiên, như đã đề cập trước đó bạn cần% lf thay vì% d để hiển thị gấp đôi, nếu không nó sẽ chỉ hiển thị bằng không mọi lúc (d là số nguyên đã ký). Sau đó, nếu bạn muốn kiểm tra điều này bằng tay trên một cửa sổ dựa trên loại hệ điều hành trong một số ký tự nhấn Enter và sau đó nhấn CtrlZ trên dòng kế tiếp tất cả bởi chính nó (điều này sẽ mô phỏng EOF).Kết quả in sẽ nhiều hơn số ký tự (bao gồm CtrlZ). Cũng như SoapBox chỉ ra khi tìm kiếm một EOF điển hình thì suy nghĩ trở lại sau đó là Unix, nơi bạn đặt một tập tin vào chương trình thông qua đầu vào tiêu chuẩn, điều này cũng sẽ hoạt động.

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