2009-06-16 51 views
7

Tôi đã bắt đầu đọc "The C Programming Language" (K & R) và tôi có nghi ngờ về chức năng getchar().`getchar()` lưu trữ đầu vào của người dùng ở đâu?

Ví dụ mã này:

#include <stdio.h> 

main() 
{ 
    int c; 

    c = getchar(); 
    putchar(c); 
    printf("\n"); 
} 

toomanychars + CTRL +D (EOF) in ra chỉ t. Tôi nghĩ rằng đó là dự kiến ​​vì nó là nhân vật đầu tiên được giới thiệu.

Nhưng sau đó mảnh này khác mã:

#include <stdio.h> 

main() 
{ 
    int c; 

    while((c = getchar()) != EOF) 
    putchar(c); 
} 

toomanychars + CTRL +D (EOF) in toomanychars.

Câu hỏi của tôi là, tại sao điều này xảy ra nếu tôi chỉ có một biến char đơn? các ký tự còn lại được lưu ở đâu?

EDIT:

Nhờ mọi người cho câu trả lời, tôi bắt đầu để có được nó bây giờ ... chỉ có một nhược điểm:

Các lối ra chương trình đầu tiên khi đưa CTRL +D khi các bản in thứ hai toàn bộ chuỗi và sau đó chờ đợi cho đầu vào người dùng hơn. Tại sao nó đợi một chuỗi khác và không thoát ra khỏi chuỗi đầu tiên?

+1

Cách tiếp cận thứ hai của bạn chỉ lặp lại cho đến EOF. CTRL + D (trên các hệ thống unix điển hình) sẽ không dẫn đến EOF trừ khi bạn nhấn nó trên một dòng riêng của nó. Nhấn CTRL + D sau khi bạn đã viết một ký tự không dẫn đến EOF – nos

Trả lời

4

Nó xử lý luồng đầu vào như một tệp. Nó giống như khi bạn mở một tệp chứa văn bản "toomanychars" và đọc hoặc xuất ra một ký tự cùng một lúc.

Trong ví dụ đầu tiên, trong trường hợp không có vòng lặp while, nó giống như bạn đã mở một tệp và đọc ký tự đầu tiên, sau đó xuất nó ra. Tuy nhiên ví dụ thứ hai sẽ tiếp tục đọc ký tự cho đến khi nó kết thúc tín hiệu tệp (ctrl+D trong trường hợp của bạn) giống như khi nó đang đọc từ một tệp trên đĩa.


Trả lời câu hỏi cập nhật của bạn, bạn đang sử dụng hệ điều hành nào? Tôi chạy nó trên máy tính xách tay Windows XP của tôi và nó hoạt động tốt. Nếu tôi nhấn enter, nó sẽ in ra những gì tôi đã có cho đến nay, tạo ra một dòng mới, và sau đó tiếp tục. (Chức năng getchar() không trở lại cho đến khi bạn nhấn enter, đó là khi không có gì trong bộ đệm đầu vào khi nó được gọi). Khi tôi bấm CTRL+Z (EOF trong Windows), chương trình sẽ chấm dứt. Lưu ý rằng trong Windows, EOF phải nằm trên một dòng riêng của nó để được tính là một EOF trong dấu nhắc lệnh. Tôi không biết liệu hành vi này được bắt chước trong Linux hay bất kỳ hệ thống nào bạn có thể đang chạy.

+0

@Carson, chính xác! EOF phải nằm trong dòng riêng của nó. CẢM ƠN RẤT NHIỀU! –

+0

bạn được chào đón. Tôi đã vật lộn với điều này cũng nhưng đã giải quyết nó nhờ SO :) –

9

getchar lấy một ký tự đơn từ đầu vào chuẩn, trong trường hợp này là bộ đệm bàn phím.

Trong ví dụ thứ hai, getchar chức năng là trong một vòng lặp while mà tiếp tục cho đến khi nó gặp một EOF, vì vậy nó sẽ tiếp tục vòng lặp và lấy một nhân vật (và in các nhân vật vào màn hình) cho đến khi đầu vào trở nên trống rỗng.

Cuộc gọi liên tiếp đến getchar sẽ nhận được các ký tự liên tiếp đến từ đầu vào.

Ồ, và không cảm thấy xấu khi hỏi câu hỏi này - Tôi đã bối rối khi lần đầu tiên tôi gặp sự cố này.

+0

Nó có bắt đầu lặp lại ngay sau khi nó gặp câu lệnh 'while (c = getchar())' hay nó đợi nhập để được nhấn và sau đó lặp lại? Từ những gì tôi có thể thấy, nó thực thi thân của vòng lặp 'while()' chỉ sau khi chúng ta nhấn enter. Câu hỏi của tôi là: Liệu 'getchar()' làm cho vòng lặp 'while()' đợi cho đến khi 'enter' hoặc' CTRL + D' (trên hệ thống của tôi) được nhấn và chỉ sau khi trở về 'while() 'vòng lặp và sau đó thực hiện phần còn lại của cơ thể. – dud3

3

Chương trình đầu tiên của bạn chỉ đọc một ký tự, in ra và thoát. Chương trình thứ hai của bạn có một vòng lặp. Nó tiếp tục đọc từng ký tự một và in chúng ra cho đến khi nó đọc một ký tự EOF. Chỉ một ký tự được lưu trữ tại bất kỳ thời điểm nào.

2

Bạn chỉ sử dụng biến số c để chứa từng ký tự cùng một lúc.

Khi bạn đã hiển thị char đầu tiên (t) sử dụng putchar(c), bạn quên đi những giá trị của c bằng cách gán các ký tự tiếp theo (o) vào biến c, thay thế giá trị trước đó (t).

1

mã có chức năng tương đương với

main(){ 
    int c; 
    c = getchar(); 
    while(c != EOF) { 
    putchar(c); 
    c = getchar(); 
    } 
} 

bạn có thể tìm thấy phiên bản này dễ hiểu hơn. lý do duy nhất để đặt nhiệm vụ trong điều kiện là tránh phải gõ 'c = getchar()' hai lần.

4

Nội dung nào đó ở đây được lưu vào bộ đệm. ví dụ. stdout FILE * mà putchar ghi vào có thể là line.buffered. Khi chương trình kết thúc (hoặc gặp một dòng mới) như một FILE * sẽ được fflush() 'ed và bạn sẽ thấy đầu ra.

Trong một số trường hợp thiết bị đầu cuối thực tế bạn đang xem có thể đệm đầu ra cho đến khi một dòng mới, hoặc cho đến khi chính thiết bị đầu cuối được hướng dẫn xóa bộ đệm, có thể là trường hợp khi chương trình nền trước hiện tại thoát khỏi vì nó muốn hiển thị lời nhắc mới.

Bây giờ, có thể là trường hợp thực tế ở đây, đó là đầu vào được đệm (ngoài đầu ra :-)) Khi bạn nhấn phím nó sẽ xuất hiện trên cửa sổ đầu cuối của bạn. Tuy nhiên, thiết bị đầu cuối sẽ không gửi các ký tự đó đến ứng dụng của bạn, nó sẽ đệm nó cho đến khi bạn hướng dẫn nó là đầu vào cuối cùng với Ctrl + D và có thể là một dòng mới. Đây là một phiên bản khác để phát xung quanh và suy ngẫm về:

int main() { 
    int c; 
    while((c = getchar()) != EOF) { 
    if(c != '\n') 
     putchar(c); 
    } 
    return 0; 
} 

Hãy thử cho chương trình của bạn một câu và nhấn Enter. Và làm tương tự nếu bạn nhận xét ra nếu (c! = '\ N') Có thể bạn có thể xác định xem đầu vào, đầu ra của bạn hoặc cả hai được đệm theo một cách nào đó. Điều này sẽ trở nên thú vị hơn nếu bạn chạy ở trên như: ./mytest | ./mytest

(Như bên lề, lưu ý rằng CTRD + D không phải là ký tự, cũng không phải là EOF. Nhưng trên một số hệ thống, kết quả sẽ đóng luồng đầu vào, điều này sẽ tăng EOF cho bất kỳ ai cố gắng đọc từ luồng.)

0

Đối với câu hỏi được cập nhật của bạn, trong ví dụ đầu tiên, chỉ đọc một ký tự. Nó không bao giờ đạt đến EOF. Chương trình chấm dứt vì không có gì để làm sau khi hoàn thành lệnh printf. Nó chỉ đọc một nhân vật. In nó. Đặt trong một dòng mới. Và sau đó chấm dứt vì nó không có gì để làm. Nó không đọc nhiều hơn một ký tự.

Trong khi đó, trong mã thứ hai, hàm getchar và putchar có mặt trong vòng lặp while.Trong chương trình này, chương trình tiếp tục đọc từng ký tự một (do nó được tạo ra để thực hiện điều đó bởi vòng lặp) cho đến khi đạt đến ký tự EOF (^ D). Tại thời điểm đó, nó khớp với c! = EOF và vì các điều kiện không thỏa mãn, nó xuất hiện từ vòng lặp. Bây giờ không có thêm câu lệnh nào để thực hiện. Vì vậy, chương trình chấm dứt vào thời điểm này.

Hy vọng điều này sẽ hữu ích.

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