Perché esiste la funzione Cddio 'ungetc'?

5

Nel linguaggio di programmazione C (e in molte lingue successive che sono direttamente interfacciate con o costruito un fac-simile delle funzioni IO standard di C), esiste una funzione chiamata ungetc : int ungetc(int char, FILE *stream); . Rimette un carattere nella parte anteriore dello stream che viene letto. Questa restituzione è solo virtuale: il flusso di input originale non viene alterato, solo il risultato delle successive chiamate 'getc' leggerà prima i valori 'ungetc' prima di continuare con i reali valori successivi nel flusso.

Perché esiste questa funzione? Quali sono esempi di casi d'uso che possono essere gestiti solo utilizzando 'ungetc'?

    
posta Qqwy 04.09.2016 - 23:34
fonte

1 risposta

15

La risposta breve è che ungetc ti permette di sbirciare al prossimo personaggio senza consumarlo.

Diciamo che stai leggendo un formato di dati a pacchetti. Contiene, tra le altre cose, un modello di sincronizzazione dei frame. I pattern di sincronizzazione dei frame consentono di allineare i dati contrassegnando l'inizio di un frame di dati in un flusso di dati altrimenti non sincronizzato.

Per facilitare la discussione, ecco una definizione dei dati:

[sync pattern] [packet length] [--------------data--------------] [checksum]

|---0xEB25---| |-- 16 bits --| |-- packet length minus 64 bits--| |32 bits |

Il pattern di sincronizzazione EB25 viene scelto per una serie di motivi. Il suo schema di bit è resistente ai falsi positivi, ed è abbastanza unico da servire come un tipo di file "numero magico".

Il checksum è lì per rilevare gli errori di trasmissione e per convalidare il pattern di sincronizzazione (dal momento che EB25 ha una piccola possibilità di essere effettivamente dati validi). Se combinato con una lunghezza del pacchetto accurata, la combinazione di pattern di sincronizzazione, lunghezza del pacchetto e somma di controllo garantisce virtualmente di aver identificato un pacchetto di dati valido.

Ora immagina di passare attraverso questo esercizio senza la possibilità di eseguire il backup su un punto precedente nel flusso di dati. Per trovare il pacchetto successivo, è necessario eseguire la scansione dei byte finché non si identifica un pattern di sincronizzazione di EB25, tenendo conto che i byte sono invertiti perché la specifica è basata su Little Endian. Una volta identificato il pattern di sincronizzazione, è necessario leggere la lunghezza del pacchetto, quindi il resto del pacchetto e calcolare un checksum. Se la verifica del checksum fallisce, è necessario ricominciare dal byte che segue il pattern di sincronizzazione fallito. Per fare ciò, è necessario eseguire il backup all'inizio del pattern di sincronizzazione + 4 byte, e ricominciare la scansione .

Finora, non ho descritto nulla che non possa essere ottenuto anche da buffering del flusso di input. Ma se il pattern di sincronizzazione non è garantito per l'allineamento su un limite di byte ? In questa situazione, il primo bit del pattern di sincronizzazione potrebbe verificarsi nel mezzo di un byte. Quindi per ottenere i primi 8 bit, dovresti leggere due byte, non solo uno. In queste condizioni, non sarebbe utile sfogliare di un byte se nessun 8 bit consecutivi fosse un E (senza stare in piedi su un lettore bufferizzato?)

Questo non è solo un ipotetico ozioso. Le specifiche dell'IRIG 106 Capitolo 10 funzionano esattamente in questo modo, anche se ho semplificato la storia in qualche modo per questa dimostrazione.

    
risposta data 05.09.2016 - 01:01
fonte

Leggi altre domande sui tag