2010-09-21 14 views
9

Problema: devo essere in grado di identificare quando si verificano due spazi bianchi consecutivi.Come si legge lo spazio bianco usando scanf in c?

Ho letto le seguenti domande:

how to read a string from a \n delimited file

how to read scanf with spaces

e sono consapevole dei problemi scanf: http://c-faq.com/stdio/scanfprobs.html

ingresso sarà nel seguente formato:

1 5 3 2 4 6 2 1 9 0 

Due spazi bianchi indicano che il prossimo set di dati deve essere gestito e confrontato a se stesso. La lunghezza della linea è sconosciuta e il numero o gli interi in ogni gruppo sono sconosciuti. Due spazi bianchi sono i più che separeranno il prossimo set di dati.

Mentre posso utilizzare fget e varie funzioni integrate per risolvere questo problema, sono al punto in cui risolvere il problema con scanf a questo punto sarà probabilmente più semplice. Tuttavia, se questo non è il caso, usando fgets, strtok e atoi faranno la maggior parte del lavoro, ma ho ancora bisogno di identificare due spazi bianchi di fila.

Quanto segue avrà numeri interi fino a quando non viene immesso un numero intero.

 
while (scanf ("%d", &x) == 1) 

Quello che ho bisogno fare è leggere gli spazi bianchi come bene e se ci sono due spazi bianchi consecutivi io il programma per fare qualcosa di diverso con la prossima serie di dati.

E una volta che faccio ottenere uno spazio bianco non so come dire:

 
if ((input == "whitespace") && (previousInput == "whitespace")) 
    ya da ya da 
else (input == "whitespace") 
    ya da ya da 
else 
    ya da ya da 

Apprezzo il vostro tempo e grazie per il vostro aiuto.

Lezione imparata: Mentre una soluzione per scanf è pubblicato qui di seguito da Jonathan Leffler, la soluzione è stata un po 'più semplice, con getc (a titolo di richiedere la conoscenza meno intima della scanf interno, le espressioni regolari e char). Con una migliore conoscenza retrospettiva delle espressioni regolari, scanf e char renderebbero il problema più facile e, naturalmente, sapendo quali funzioni sono disponibili e quale sarebbe stato il migliore da utilizzare sin dall'inizio.

+2

Questo è un formato di input piuttosto orribile. Se sei responsabile, ridisegnalo. Se, come sospetto, ti è stato assegnato un compito a casa, sfortuna, sono un gruppo sadico, i tuoi insegnanti. –

+3

Si noti che lo "spazio bianco" è diverso da "due spazi"; 'spazio bianco' indica convenzionalmente una varietà di possibili caratteri, tra cui tabulazione e spazio (o spazio), e talvolta forma feed, tabulazione verticale o nuova riga; e occasionalmente anche backspace. –

+0

@Jonathan Leffler: almeno non sta cercando di analizzare lo spazio bianco (http://compsoc.dur.ac.uk/whitespace/) – ninjalj

risposta

6

getc e ungetc sono i tuoi amici

#include <stdio.h> 

int main(void) { 
    int ch, spaces, x; 
    while (1) { 
    spaces = 0; 
    while (((ch = getc(stdin)) != EOF) && (ch == ' ')) spaces++; 
    if (ch == EOF) break; 
    ungetc(ch, stdin); 
    if (scanf("%d", &x) != 1) break; 
    printf("%d was preceded by %d spaces\n", x, spaces); 
    } 
    return 0; 
} 

Demo a http://ideone.com/xipm1

Modifica Rahhhhhhhhh ...L'ho caricato come C++. Ecco la stessa identica cosa, ma ora C99 strict (http://ideone.com/mGeVk)

+0

scanf, sscanf, fscanf, fgets, gets, getc ... lol tante opzioni. Dovrò leggere su getc e ungetc. Grazie per la risposta. – MykC

+0

+1 perché 'getc()' e 'ungetc()' sono un modo migliore per farlo che provare a usare solo 'scanf()' - ma elude la domanda un po '. –

+4

@MykC: ** No, NON si ottiene! NON SEMPRE L'USO, MAI MAI ** – pmg

1
while (scanf ("%c", &x) == 1) 

Usando %c si può leggere caratteri di spaziatura, è necessario leggere solo tutti i dati e memorizzare in array. Quindi allocare cptr per iniziare la matrice, quindi si analizza la matrice e se si desidera leggere i numeri decimali, è possibile utilizzare semplicemente sscanf su cptr mentre si desidera decimale lettura, ma è necessario disporre di puntatore in buona posizione su matrice (in numero di quello che Wäny leggere)

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' ')) 
    ya da ya da 
else ((*cptr)== ' ')) 
    ya da ya da 
    sscanf(++cptr, "%d", &x); 
else 
    ya da ya da 
+0

Sembra buono. Evito di usare puntatori e matrici se posso. Nota: userò puntatori e array quando invece ha senso. – MykC

+0

Ho ricordato in alcuni commenti di altri che sembra che se ci fosse uno o più spazi bianchi verrebbero tutti memorizzati in un singolo carattere, in modo da impedire il funzionamento del metodo precedente. – MykC

0

Qual è la tua definizione di "spazio bianco"?

Francamente, non credo che vorrei provare a utilizzare scanf() per identificare i doppi spazi bianchi; quasi ogni altro metodo sarebbe molto più facile.

Tuttavia, se ti ostini a fare il non disperatamente sensibile, allora si potrebbe desiderare di utilizzare codice derivato dalla seguente:

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

int main(void) 
{ 
    int d; 
    char sp[3] = ""; 
    int n; 

    while ((n = scanf("%d%2[ \t]", &d, sp)) > 0) 
    { 
     printf("n = %d; d = %d; sp = <<%s>>", n, d, sp); 
     if (n == 2 && strlen(sp) == 2) 
      printf(" end of group"); 
     putchar('\n'); 
    } 
    return 0; 
} 

Le parentesi quadre racchiudono una classe di caratteri e il 2 prima che insiste su a la maggior parte di 2 personaggi della classe. Potresti doverlo preoccupare leggendo la nuova riga e cercando di ottenere più dati per soddisfare la classe di caratteri, che potrebbe essere risolta rimuovendo la nuova riga dalla classe di caratteri. Ma poi dipende dalla definizione di spazio bianco, e se i gruppi vengono automaticamente terminati da una nuova riga o meno. Non farebbe male resettare sp[0] = '\0'; alla fine del ciclo.

Potrebbe, forse, essere meglio invertire i campi, per rilevare due spazi prima di un numero. Ma questo fallirebbe nel caso ordinario, quindi ricorrerebbe a un semplice formato "%d" per leggere il numero (e se fallisce, sai che non hai né spazi né numeri - errore). Notare che %d mastica lo spazio bianco iniziale (come definito dallo standard) - tutti.

Più guardo a questo, meno mi piace solo 'scanf(). Ricordami di non frequentare un corso alla tua università, per favore.

+1

Credo di dovermi preoccupare solo con uno spazio bianco che è un singolo spazio vuoto o "". Non sono collegato a scanf, sono solo attaccato a farlo nel modo più semplice presumendo che dovessi farlo di nuovo e non solo fare il lavoro. Volevo solo vedere se c'era un'espressione regolare o un trucco con scanf che potevo ignorare che avrebbe risolto il problema in modo estremamente semplice dal momento che l'input è stato formattato. – MykC

+0

Ho visto la tua risposta e sembra che scanf nel tuo esempio restituisca sempre 2. Sto attualmente esaminando quale intervallo di valori può restituire scanf e perché. – MykC

+0

Sono corretto, non sempre restituisce 2. – MykC

0

Se si vuole veramente scanf funzionalità di tipo, è possibile utilizzare fgets e sscanf, e utilizzare il %n specificatore per arrivare scanf per dare il vostro programma gli offset per l'inizio e la fine di ogni campata spazi al tempo stesso lo fa il resto del suo lavoro.

In caso contrario, abbandonare l'intera famiglia scanf. È probabilmente la parte più inutile della libreria standard, secondo me.

+0

È utile, ma in generale cattivo. Se vuoi aggiungere l'input equivalente a una dichiarazione di stampa di debug su un programma, allora è grandioso. Se vuoi aggiungere semplici input per un test o un programma dimostrativo (dove le buone pratiche di input non sono ciò che stai dimostrando), allora è abbastanza buono. Se vuoi fare input per il codice di produzione è davvero pessimo. – nategoose

+0

In realtà c'è un uso per 'scanf': una versione portatile di' getline' (o 'getdelim'), inclusa la gestione pulita dei caratteri NUL incorporati, può essere ottenuta con qualcosa come' scanf ("% 99 [^ \ n] % n ", buf, &cnt);' (dove 99 viene sostituito con la dimensione del buffer) –

+0

'scanf ("% 99 [^ \ n]% n ", buf, &cnt);' ha il problema che non salva nulla in 'buf' e 'cnt' se l'input inizia con' '\ n'' e lascia '' \ n'' in stdin.Questo non è come 'getline()'. – chux

0

Ecco una soluzione che utilizza solo la funzione scanf(). Ho usato sscanf() in questo esempio per circa la stessa funzionalità.

#include <stdio.h> 


int p_1_cnt = 0, p_2_cnt = 0; 

void process_1(int x) 
{ 
    p_1_cnt++; 
} 


void process_2(int x) 
{ 
    p_2_cnt++; 
} 


char * input_line = "1 5 3 2 4 6 2 1 9 0"; 

int main(void) 
{ 
    char * ip = input_line; 

    int x = 0, ws_0 = 0, ws_1 = 0, preceding_spaces = 1, fields = -2; 

    while (sscanf (ip, "%d%n %n", &x, &ws_0, &ws_1) > 0) 
    { 
     ip += ws_0; 

     if ((preceding_spaces) == 1) 
      process_1(x); 
     else 
      process_2(x); 

     preceding_spaces = ws_1 - ws_0; 
    } 

    printf("\np_1_cnt = %d, p_2_cnt = %d", p_1_cnt, p_2_cnt); 
    _fgetchar(); 

    return 0; 
} 
Problemi correlati