2009-12-23 24 views
5

Ho già ottenuto del codice per leggere un file di testo utilizzando fscanf() e ora ho bisogno che venga modificato in modo che i campi che prima erano bianchi non necessitassero di consentire spazi bianchi. Il file di testo è sostanzialmente in forma di:Can fscanf() può leggere lo spazio bianco?

titolo: DATI
titolo: DATI
ecc ...

quali è fondamentalmente analizzato utilizzando fgets(inputLine, 512, inputFile); sscanf(inputLine, "%*s %s", &data);, leggendo i campi di dati e ignorando i titoli, ma ora alcuni dei campi dati devono consentire gli spazi. Devo ancora ignorare il titolo e lo spazio immediatamente dopo, ma poi leggere il resto della riga incluso lo spazio bianco.

Esiste comunque lo scopo della funzione sscanf()?

In caso contrario, qual è il più piccolo cambiamento che posso apportare al codice per gestire correttamente lo spazio bianco?

AGGIORNAMENTO: Ho modificato la domanda per sostituire fscanf() con fgets() + sscanf(), che è ciò che il mio codice sta effettivamente utilizzando. Non ho davvero pensato che fosse rilevante quando ho scritto per la prima volta la domanda, motivo per cui l'ho semplificato in fscanf().

+0

Se si è utilizzato l'analisi con 'scanf', è anche possibile analizzare in precedenza qualcosa come' title: DATA title: DATA' (cioè tutto su una riga). Se vuoi consentire lo spazio bianco nei valori, allora quale sarà il terminatore? Se newline, sembra che il tuo codice originale fosse un po 'troppo lassista ... –

+0

Inoltre, come si decide sulla dimensione del buffer 'str' e come si fa a garantire che non esca? –

+0

sì, quando il DATI può avere spazi bianchi, la nuova riga verrà utilizzata come terminatore –

risposta

11

Se non è possibile utilizzare fgets() utilizzare l'identificatore %[ di conversione (con l'opzione "escludere"):

char buf[100]; 
fscanf(stdin, "%*s %99[^\n]", buf); 
printf("value read: [%s]\n", buf); 

Ma il fgets() è decisamente migliore.


Edit: versione con fgets() + sscanf()

char buf[100], title[100]; 
fgets(buf, sizeof buf, stdin); /* expect string like "title: TITLE WITH SPACES" */ 
sscanf(buf, "%*s %99[^\n]", title); 
+3

In questo caso particolare, in che modo 'fgets'" è migliore "? –

+1

Bene ... i requisiti continuano a cambiare (prima non c'era spazio nella stringa). Non è meglio per questo caso particolare, ma è meglio usare 'fgets()' ora, in antecipation per il prossimo cambio di requisiti :) – pmg

+0

Ho aggiornato la domanda per dimostrare che effettivamente uso fgets() per leggere la riga, quindi sscanf() per analizzarla, ma esiste un modo migliore per analizzare la riga dopo fgets()? –

3

Consiglio vivamente di smettere di usare fscanf() e iniziare a utilizzare fgets() (che legge un'intera riga) e quindi analizzare la riga che è stata letta.

Ciò consentirà una considerevolmente maggiore libertà per quanto riguarda l'analisi di input non formattati in modo esatto.

+0

Ho aggiornato la domanda per dimostrare che effettivamente utilizzo fgets(), ma non capisco che cosa esattamente aiuterà. Devo ancora analizzare la riga una volta che l'ho letta. –

+1

Una volta ottenuta l'intera stringa, esegui il comando da solo anziché utilizzare sscanf. –

+0

Sì, fallo con i puntatori o, ancora meglio, usa le espressioni regolari. Se avessi usato C++ avrei suggerito boost; Non conosco nessuna buona libreria di C, ma ce ne devono essere alcuni. Ho sentito che POSIX li supporta. –

2

La cosa più semplice sarebbe quella di emettere un

fscanf("%*s"); 

di scartare la prima parte e poi basta chiamare i fgets:

fgets(str, stringSize, filePtr); 
3

Se ti ostini a usare scanf, e supponendo che si desidera ritorno a capo come terminatore, si può fare questo:

scanf("%*s %[^\n]", str); 

Nota, tuttavia, che quanto sopra, usato esattamente come scritto, è una cattiva idea perché Non c'è nulla da proteggere contro lo str che viene sorvolato (come scanf non conosce le sue dimensioni). È possibile, ovviamente, impostare una dimensione massima predefinita e specificarla, ma in tal caso il programma potrebbe non funzionare correttamente su alcuni input validi.

Se la dimensione della linea, come definito dal formato di input, non si limita, quindi l'unica opzione pratica è quello di utilizzare fgetc per leggere char dati char, riallocando periodicamente il buffer, come si va. Se lo fai, modificalo per eliminare tutti i caratteri letti fino a quando il primo spazio non è abbastanza banale.

2

Un identificatore %s in fscanf salta qualsiasi spazio bianco sull'input, quindi legge una stringa di caratteri non di spaziatura fino ae non includendo il successivo carattere di spaziatura.

Se si desidera leggere fino a una nuova riga, è possibile utilizzare %[^\n] come identificatore. Inoltre, un '' nella stringa di formato salterà lo spazio bianco sull'input. Quindi, se si utilizza

fscanf("%*s %[^\n]", &str); 

si leggerà la prima cosa sulla linea fino al primo spazio bianco ("titolo:" nel tuo caso), e gettarlo via, poi leggerà i caratteri di spaziatura e buttarli via, poi leggerà tutti i caratteri fino a una nuova riga in str, che suona come quello che vuoi.

fare attenzione che non trabocchi str - si potrebbe desiderare di utilizzare

fscanf("%*s %100[^\n]", &str) 

per limitare la lunghezza massima della stringa potrai leggere (100 caratteri, senza contare un NUL di terminazione qui).

+0

So che questo è un breve esempio, ma devi usare l'indirizzo di str? Penserei che anche questo funzionerebbe. 'fscanf ("% * s% [^ \ n] ", str);' – cokedude

1

Ti stai avvicinando ai limiti di ciò che la famiglia *scanf è adatta a. Con modifiche alquanto minime è possibile provare a utilizzare i moduli di scansione delle stringhe di Dave Hanson C Interfaces and Implementations. Questa roba è un retrofit dal linguaggio di programmazione Icon, un linguaggio di elaborazione delle stringhe estremamente semplice e potente su cui Hanson e altri hanno lavorato in Arizona. La partenza da sscanf non sarà troppo severa, ed è più semplice, più facile da utilizzare e più potente delle espressioni regolari. L'unico lato negativo è che il codice è un po 'difficile da seguire senza il libro — ma se si fa molta programmazione in C, il libro merita di essere letto.

Problemi correlati