Domanda

Ho iniziato a leggere " Il linguaggio di programmazione C " (K & amp; R) e ho dei dubbi sulla funzione getchar () .

Ad esempio questo codice:

#include <stdio.h>

main()
{
  int c;

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

Digitando toomanychars + CTRL + D (EOF) si stampa solo t . Penso che ci si aspetta da quando è stato introdotto il primo personaggio.

Ma poi quest'altro pezzo di codice:

#include <stdio.h>

main()
{
  int c;

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

Digitando toomanychars + CTRL + D (EOF) stampa toomanychars .

La mia domanda è: perché succede se ho una sola variabile char? dove sono memorizzati gli altri personaggi?

Modifica

Grazie a tutti per le risposte, comincio a ottenerlo ora ... solo una cattura:

Il primo programma termina quando viene dato CTRL + D mentre il secondo stampa l'intera stringa e attende quindi ulteriori input da parte dell'utente. Perché aspetta un'altra stringa e non esce come la prima?

È stato utile?

Soluzione

Sta trattando il flusso di input come un file. È come se avessi aperto un file contenente il testo "toomanychars" e lo ha letto o emesso un personaggio alla volta.

Nel primo esempio, in assenza di un ciclo while, è come se tu aprissi un file e leggessi il primo carattere, quindi lo producessi. Tuttavia, il secondo esempio continuerà a leggere i caratteri fino a quando non arriva alla fine del segnale del file ( ctrl + D nel tuo caso) proprio come se stesse leggendo da un file su disco.


In risposta alla tua domanda aggiornata, quale sistema operativo stai usando? L'ho eseguito sul mio laptop Windows XP e ha funzionato bene. Se premessi invio, stampa ciò che avevo finora, tracciava una nuova riga e poi continuava. (La funzione getchar () non ritorna fino a quando non si preme invio, ovvero quando non c'è nulla nel buffer di input quando viene chiamato). Quando premo CTRL + Z (EOF in Windows), il programma termina. Si noti che in Windows, l'EOF deve trovarsi su una riga a sé stante per essere conteggiato come EOF nel prompt dei comandi. Non so se questo comportamento sia imitato in Linux, o qualunque sistema tu stia eseguendo.

Altri suggerimenti

getchar ottiene un singolo carattere dall'input standard, che in questo caso è il buffer della tastiera.

Nel secondo esempio, la funzione getchar è in un ciclo while che continua fino a quando non incontra un EOF , quindi continuerà ad essere ripetuto e recupera un personaggio (e stampa il personaggio sullo schermo) fino a quando l'input diventa vuoto.

Le chiamate successive a getchar riceveranno caratteri successivi che provengono dall'input.

Oh, e non sentirti male per aver posto questa domanda: ero perplesso anche quando ho riscontrato questo problema per la prima volta.

Qualcosa qui è bufferizzato. per esempio. lo stdout FILE * su cui scrive putchar potrebbe essere line.buffered. Quando il programma termina (o incontra una nuova riga) tale FILE * sarà fflush () 'ed vedrai l'output.

In alcuni casi il terminale reale che stai visualizzando potrebbe bufferizzare l'output fino a quando una nuova riga, o fino a quando il terminale stesso non viene istruito a svuotare il suo buffer, il che potrebbe essere il caso in cui l'attuale programma in primo piano esce dal momento che vuole presentare un nuovo prompt.

Ora, quello che è probabilmente il caso reale qui, è che è l'input che è bufferizzato (oltre all'output :-)) Quando si premono i tasti, apparirà sulla finestra del terminale. Tuttavia, il terminale non invierà questi caratteri all'applicazione, lo bufferizzerà fino a quando non gli viene indicato di essere la fine dell'input con Ctrl + D, e possibilmente anche una nuova riga. Ecco un'altra versione su cui giocare e riflettere:

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

Prova a dare una frase al tuo programma e premi Invio. E fai lo stesso se commenti if (c! = '\ n') Forse puoi determinare se il tuo input, output o entrambi sono bufferizzati in qualche modo. Questo diventa più interessante se esegui quanto sopra come: ./mytest | ./mytest

(Come sidecomment, nota che CTRD + D non è un personaggio, né EOF. Ma su alcuni sistemi risulterà la chiusura del flusso di input che aumenterà nuovamente EOF per chiunque tenti di leggere dal flusso.)

Il tuo primo programma legge solo un carattere, lo stampa ed esce. Il tuo secondo programma ha un ciclo. Continua a leggere i personaggi uno alla volta e li stampa fino a quando non legge un personaggio EOF. Viene memorizzato un solo personaggio alla volta.

Stai usando la variabile c solo per contenere ogni carattere uno alla volta.

Dopo aver visualizzato il primo carattere ( t ) utilizzando putchar (c) , si dimentica il valore di c assegnando il carattere successivo ( o ) alla variabile c , sostituendo il valore precedente ( t ).

il codice è funzionalmente equivalente a

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

potresti trovare questa versione più semplice da capire. l'unico motivo per mettere il compito nella condizione è evitare di digitare due volte "c = getchar ()".

Per la tua domanda aggiornata, nel primo esempio, viene letto solo un carattere. Non raggiunge mai l'EOF. Il programma termina perché non c'è nulla da fare dopo aver completato l'istruzione printf. Legge solo un personaggio. Lo stampa. Inserisce una nuova riga. E poi termina perché non ha altro da fare. Non legge più di un personaggio.

Considerando che, nel secondo codice, getchar e putchar sono presenti all'interno di un ciclo while. In questo, il programma continua a leggere i caratteri uno ad uno (come è fatto per farlo dal loop) fino a quando raggiunge i caratteri EOF (^ D). A quel punto, corrisponde a c! = EOF e poiché le condizioni non sono soddisfatte, esce dal ciclo. Ora non ci sono più dichiarazioni da eseguire. Quindi il programma termina a questo punto.

Spero che questo aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top