Domanda

Ho avuto molti problemi cercando di capire come usare scanf () . Sembra funzionare bene con i numeri interi, essendo abbastanza semplice scanf ("% d " ;, & amp; i) .

Dove sto incontrando problemi sta usando scanf () nei loop cercando di leggere l'input. Ad esempio:

do {
  printf("counter: %d: ", counter);
  scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
  1. Quando entro in un input validamente strutturato come c P101 , sembra ripetere nuovamente il ciclo prima di avvisarmi. Questo sembra accadere anche con un singolo:

    scanf("%c", &c) 
    

    in un ciclo while. Farà il ciclo due volte prima di chiedermi di nuovo. Che cosa lo rende loop due volte e come posso interromperlo?

  2. Quando inserisco una quantità inferiore di input che a livello di codice non avrebbe un altro carattere o numero come q , premendo Invio mi viene richiesto di inserire altro. Come posso ottenere scanf () per elaborare sia voci a carattere singolo che doppio?

È stato utile?

Soluzione

Quando inserisci " c P101 " il programma effettivamente riceve " c P101 \ n " ;. La maggior parte degli identificatori di conversione salta i principali spazi bianchi, compresi i newline, ma % c no. La prima volta in tutto fino al " \ n " viene letto, la seconda volta attorno a " \ n " viene letto in comando , " c " viene letto in prefisso e " P " viene lasciato un numero diverso, pertanto la conversione non riesce e " P101 \ n " viene lasciato sul flusso. La prossima volta " P " è memorizzato nel comando, " 1 " è memorizzato nel prefisso e 1 (dal restante " 01 ") è memorizzato nell'input con " \ n " ancora in streaming per la prossima volta. Puoi risolvere questo problema inserendo uno spazio all'inizio della stringa di formato che salterà qualsiasi spazio bianco iniziale, comprese le nuove righe.

Sta succedendo una cosa simile per il secondo caso, quando inserisci " q " ;, " q \ n " viene immesso nello stream, la prima volta attorno a " q " viene letto, la seconda volta che " \ n " viene letto, solo alla terza chiamata è il secondo " q " leggi, puoi evitare di nuovo il problema aggiungendo un carattere spazio all'inizio della stringa di formato.

Un modo migliore per farlo sarebbe usare qualcosa come fgets () per elaborare una riga alla volta e quindi usare sscanf () per eseguire l'analisi.

Altri suggerimenti

È davvero rotto! Non lo sapevo

#include <stdio.h>

int main(void)
{
    int counter = 1;
    char command, prefix;
    int input;

    do 
    {
        printf("counter: %d: ", counter);
        scanf("%c %c%d", &command, &prefix, &input);
        printf("---%c %c%d---\n", command, prefix, input);
        counter++;
    } while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
 c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
 g3---

L'output sembra adattarsi alla risposta di Robert.

Una volta che hai la stringa che contiene la linea. vale a dire " C P101 " ;, puoi usare le abilità di analisi di sscanf.

Vedi: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf. html

Per la domanda 1, sospetto che tu abbia un problema con il tuo printf () , dal momento che non è presente alcuna terminazione " \ n " ;.

Il comportamento predefinito di printf è di bufferizzare l'output fino a quando non ha una riga completa. Questo a meno che tu non modifichi esplicitamente il buffering su stdout .

Per la domanda 2, hai appena riscontrato uno dei maggiori problemi con scanf () . A meno che il tuo input non corrisponda esattamente alla stringa di scansione che hai specificato, i tuoi risultati non saranno affatto come quelli che ti aspetti.

Se hai un'opzione otterrai risultati migliori (e meno problemi di sicurezza) ignorando scanf () e facendo il tuo analisi. Ad esempio, utilizzare fgets () per leggere un'intera riga in una stringa, quindi elaborare i singoli campi della stringa, magari utilizzando anche sscanf () .

Forse sarà utile usare un ciclo while, non un do ... while. In questo modo la condizione viene verificata prima dell'esecuzione del codice. Prova il seguente frammento di codice:

 while(command != 'q')
    {
        //statements
    }

Inoltre, se si conosce la lunghezza della stringa in anticipo, i cicli 'for' possono essere molto più facili da lavorare rispetto ai cicli 'while'. Ci sono anche alcuni modi più complicati per determinare dinamicamente anche la lunghezza.

Come ultimo rant: scanf () non " suck. " Fa quello che fa e questo è tutto. fgets () è molto pericoloso (anche se conveniente per le applicazioni senza rischi), poiché non esegue in modo nativo alcun controllo dell'input. È MOLTO comunemente noto come punto di exploit, in particolare attacchi buffer overflow, sovrascrivendo lo spazio nei registri non allocati per quella variabile. Pertanto, se si sceglie di utilizzarlo, dedicare un po 'di tempo a inserire un solido controllo / correzione degli errori.

Spero che questo aiuti qualcuno in futuro dal momento che presumo che tu l'abbia gestito ormai! ;)

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