2012-08-14 14 views
7

Ecco il mio codice. Lo eseguo in Ubuntu con terminale. quando digito (a CtrlD) nel terminale, il programma non si è fermato ma ha continuato ad attendere il mio input.ctrl-d non ha interrotto il ciclo while (getchar()! = EOF)

Non è CtrlD pari a EOF in UNIX?

Grazie.

#include<stdio.h> 

main() { 
    int d; 
    while(d=getchar()!=EOF) { 
     printf("\"getchar()!=EOF\" result is %d\n", d); 
     printf("EOF:%d\n", EOF); 
    } 
     printf("\"getchar()!=EOF\" result is %d\n", d); 
} 
+1

Questa non è una ricorsione. È solo un ciclo infinito fino a quando EOL l'input. Ricorsione = funzione che si chiama direttamente o dopo un altro numero intermedio di passaggi. –

+0

Compilato che con gcc, premendo '^ D' ho interrotto il ciclo per me. –

+0

@JonLin Semplicemente inserisci^D. Funziona anche per me. Tuttavia, quando l'input è (a^D), il ciclo non si è fermato. – Sam

risposta

11

EOF non è un carattere. Lo EOF è una macro che restituisce getchar() quando raggiunge la fine dell'input o incontra un qualche tipo di errore. ^D non è "un carattere EOF". Ciò che accade in Linux quando si preme^D su una riga di per sé è che chiude lo stream e la chiamata getchar() raggiunge la fine dell'input e restituisce la macro EOF. Se si digita ^D da qualche parte nel mezzo di una riga, lo stream non viene chiuso, quindi getchar() restituisce i valori letti e il ciclo non viene chiuso.

Vedere stdio section of the C faq per una descrizione migliore.

Inoltre:

Nei sistemi moderni, non riflette alcun vero carattere di fine file memorizzato in un file; è un segnale che non ci sono più personaggi disponibili.

+0

Ho letto attentamente il sito. A mio avviso, se digito '^ D' da qualche parte nel mezzo di una riga, bash affronterà'^D'. Di conseguenza, il programma C non ha ricevuto un comando per chiudere il flusso. Se digito '^ D' su una singola riga, il programma C otterrà il comando corretto. Ho ragione? – Sam

+1

@qingfeng C'è un po 'di più su '^ D' qui: http://www.c-faq.com/stdio/eofval.html Ma sì, lo stream non verrà chiuso a meno che non si trovi su una linea da solo. Breve spiegazione qui: http://stackoverflow.com/a/1516177/851273 –

+6

Quando il terminale è in modalità canonica, le linee non vengono trasmesse sul dispositivo tty finché non si preme Invio. Premendo il tasto EOF configurato (^ D per impostazione predefinita) i dati vengono immediatamente trasmessi e qualsiasi 'lettura' in attesa su di esso restituisce il numero di caratteri disponibili. Se la linea contiene già dei dati, questa sarà una lettura normale, non a lunghezza zero. Se la riga è vuota, ciò comporterà una lettura di lunghezza zero, che è la * definizione * dello stato di fine file su un descrittore di file. Quindi il livello stdio lo interpreterà come stato EOF. –

6

In aggiunta alla risposta di Jon Lin su EOF, non sono sicuro che il codice che hai scritto sia ciò che intendevi. Se volete vedere il valore restituito dal getchar nella variabile d, è necessario modificare la sua dichiarazione while a:

while((d=getchar())!=EOF) { 

Questo perché l'operatore di disuguaglianza ha la precedenza maggiore di assegnazione. Pertanto, nel codice, d sarà sempre 0 o 1.

+0

È molto gentile da parte tua essere così meticoloso. Ma voglio solo verificare che l'espressione 'd = getchar()! = EOF' sia 0 o 1. – Sam

+0

@Sam: puoi chiarire che stai assegnando il risultato del confronto scrivendo:' while ((d = (getchar()! = EOF))! = 0) 'o come' while ((d = (getchar()! = EOF))) 'in modo che il compilatore non ti lanci degli avvertimenti. L'alternativa più comune è 'while ((d = getchar())! = EOF)' che assegna il risultato di 'getchar()' a 'd' e poi lo confronta con EOF. Questo per evitare gli avvertimenti del compilatore. Molti compilatori moderni genereranno un avvertimento per ciò che hai scritto. –