Domanda

Sto scrivendo un programma che dovrebbe leggere due stringhe che possono contenere interruzioni di riga e vari altri caratteri. Pertanto, sto usando EOF (Ctrl-Z o Ctrl-D) per terminare la stringa.

Funziona bene con la prima variabile, ma con la seconda variabile, tuttavia, questo sembra essere problematico poiché apparentemente qualcosa è bloccato nel buffer di input e l'utente non riesce a digitare nulla.

Ho provato a pulire il buffer con while (getchar ()! = '\ n'); e diverse varianti simili, ma nulla sembra aiutare. Tutti i tentativi di pulizia hanno portato a un ciclo infinito e senza pulizia è impossibile aggiungere la seconda variabile.

I caratteri per entrambe le variabili vengono letti in un ciclo come questo: while ((c = getchar ())! = EOF) , il che suggerisce che è EOF quello in cui mi sono bloccato il mio buffer. O influenza il comportamento del programma in qualche altro modo? C'è qualcosa di sbagliato nella logica che sto usando?

Sto iniziando a diventare un po 'disperato dopo aver lottato con questo per ore.

[modifica: codice aggiunto sotto]

[modifica 2: clearerr () sembra far funzionare questa soluzione EOF dopo tutto.

Sembra funzionare nella sua forma originale come intendevo sotto Linux, ieri l'ho provato con Windows.]

codice:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int x = 0;
    int c;
    char a[100];
    char b[100];

    printf("Enter a: ");
    while((c = getchar()) != EOF)
    {
        a[x] = c;
        x++;
    }
    a[x] = '\0';
    x = 0;

    /*while (getchar() != '\n'); - the non-working loop*/

    printf("\nEnter b: ");
    while((c = getchar()) != EOF)
    {
        b[x] = c;
        x++;
    }
    b[x] = '\0';

    printf("\n\nResults:\na: %s\n", a);
    printf("b: %s\n", b);

    return(0);
}

[modifica 3:]

Problema di memoria dinamica:

Il mio programma dovrebbe anche gestire stringhe più lunghe di 100 caratteri. Inizialmente intendevo risolverlo tramite l'allocazione dinamica della memoria, ma quando ho avuto problemi con il loop infinito sopra descritto e gli arresti anomali relativi alla memoria l'ho lasciato fuori e sono passato a char [100].

Penso che quello che ho provato fosse generalmente qualcosa del genere:

while((c = getchar()) != EOF)
{
  a = malloc(sizeof(char));
  a[x] = c;
  x++;
}

È un modo possibile (o ragionevole) per farlo? Sto cercando di allocare più memoria per ogni personaggio che viene gestito lì. Individualmente. Con un codice del genere (questo esempio contiene probabilmente errori di sintassi) ho riscontrato arresti anomali, quindi mi sembra che malloc potrebbe non essere la funzione giusta qui, o sto provando a sbagliare. Supponendo che sia persino possibile.

È stato utile?

Soluzione

Dopo aver ricevuto un EOF dal terminale, non riceverai alcun dato aggiuntivo . Non c'è modo di annullare l'input EOF: la fine del file è, beh, la fine.

Quindi dovresti definire che ogni variabile è inserita su una riga separata e che gli utenti premano invio invece di EOF. Devi ancora verificare se hai ricevuto eof, perché ciò significa che l'utente ha effettivamente digitato EOF e non vedrai nient'altro - in questo caso, devi uscire dal ciclo e stampare un messaggio di errore.

Altri suggerimenti

EOF non è un carattere - è un valore speciale che le funzioni di input restituiscono per indicare una condizione , che il " end del file " su quel flusso di input è stato raggiunto. Come dice Martin v. L & # 246; una volta quella "fine del file" si verifica la condizione, significa che non sarà più disponibile alcun input su quel flusso.

La confusione sorge perché:

  • Molti tipi di terminali riconoscono una combinazione di tasti speciale per segnalare "fine del file" quando il " file " è un terminale interattivo (es. Ctrl-Z o Ctrl-D); e
  • Il valore EOF è uno dei valori che possono essere restituiti dalla famiglia di funzioni getchar () .

Dovrai utilizzare un valore di carattere effettivo per separare gli input: il carattere nullo ASCII '\ 0' potrebbe essere una buona scelta, se non può apparire come un valore valido all'interno del input stessi.

Eseguo il codice sul mio Linux box, ecco il risultato:

Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>

Results:
a: qwer
asdf
b: 123
456

Erano necessari due Ctrl-D perché il buffer di input del terminale non era vuoto.

È possibile utilizzare il carattere null ( '\ 0' ) per separare le variabili. Vari strumenti UNIX (ad esempio find ) sono in grado di separare i loro elementi di output in questo modo, il che suggerisce che si tratta di un metodo abbastanza standard.

Un altro vantaggio di questo è che puoi leggere lo stream in un singolo buffer e quindi creare un array di char * per puntare alle singole stringhe e ciascuna stringa sarà correttamente '\ 0' -terminato senza che tu debba modificare manualmente nulla nel buffer. Ciò significa un minore sovraccarico di allocazione della memoria, che può rendere il programma notevolmente più veloce a seconda di quante variabili stai leggendo. Ovviamente, questo è necessario solo se devi tenere tutte le variabili in memoria contemporaneamente - se le hai a che fare una alla volta, non ottieni questo particolare vantaggio.

Quello che stai provando è fondamentalmente impossibile con EOF.

Sebbene in qualche modo si comporti come tale, EOF non è un carattere nello stream ma una macro definita dall'ambiente che rappresenta la fine dello stream. Non ho visto il tuo codice, ma credo che tu stia facendo qualcosa del genere:

while ((c=getchar()) != EOF) {
    // do something
}
while ((c=getchar()) != EOF) {
    // do something else
}

Quando si digita il carattere EOF per la prima volta, per terminare la prima stringa, il flusso viene chiuso irrevocabilmente. Cioè, lo stato del flusso è che è chiuso.

Pertanto, i contenuti del secondo ciclo while non vengono mai eseguiti.

Invece di interrompere la lettura dell'input su EOF - che non è un personaggio - fermati a ENTER.

while((c = getchar()) != '\n')
{
    if (c == EOF) /* oops, something wrong, input terminated too soon! */;
    a[x] = c;
    x++;
}

EOF è un segnale che l'ingresso è terminato. Sei quasi sicuro che tutti gli input dell'utente finiscono con '\ n': questa è l'ultima chiave che l'utente digita !!!


Modifica: puoi ancora usare Ctrl-D e clearerr () per ripristinare il flusso di input.

#include <stdio.h>

int main(void) {
  char a[100], b[100];
  int c, k;

  printf("Enter a: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    a[k++] = c;
  }
  a[k] = 0;

  clearerr(stdin);

  printf("Enter b: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    b[k++] = c;
  }
  b[k] = 0;

  printf("a is [%s]; b is [%s]\n", a, b);
  return 0;
}
$ ./a.out
Enter a: two
lines (Ctrl+D right after the next ENTER)
Enter b: three
lines
now (ENTER + Ctrl+D)
a is [two
lines (Ctrl+D right after the next ENTER)
]; b is [three
lines
now (ENTER + Ctrl+D)
]
$
  

Come si inserisce null nel programma?

Puoi implementare la funzione -print0 usando:

putchar(0);

Questo stamperà un carattere nullo ASCII '\ 0' su sdtout.

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