2012-01-12 11 views
5

Spiacente per la semplice domanda, ma sto cercando di trovare un modo elegante per evitare il mio programma di vedere ingresso come "14asdf" e accettare semplicemente come 14.Ignorando interi che sono accanto a personaggi utilizzando sscanf()

if (sscanf(sInput, "%d", &iAssignmentMarks[0]) != 0) 

C'è un modo semplice per impedire a sscanf di estrarre numeri interi da stringhe storpiate del genere?

+0

Vuol dire che c'è un modo per avere sscanf solo per raccogliere i caratteri numerici in una stringa del genere? Potresti anche voler chiarire se vuoi "53sd2" per restituire 53 o 532. – Ian

+0

Scusa se dovrei essere più chiaro, voglio "14asdf" per essere riconosciuto come input non valido, come farebbe "53sd2". Voglio solo riconoscere interi che si trovano da soli (almeno delimitati da spazi) senza caratteri non numerici che li toccano. – ARW

+0

Questo sarebbe facile in C++.Forse il tag 'C++' dovrebbe essere rimosso da questa domanda? @ AdamWathan, vuoi solo le risposte che funzionano in C? –

risposta

3

Non si può fermare direttamente sscanf() di fare quello che è stato progettato e specificato a che fare. Tuttavia, è possibile utilizzare una funzione poco conosciuta e raramente usati di sscanf() per rendere più facile per scoprire che c'era un problema:

int i; 

if (sscanf(sInput, "%d%n", &iAssignmentMarks[0], &i) != 1) 
    ...failed to recognize an integer... 
else if (!isspace(sInput[i]) && sInput[i] != '\0') 
    ...character after integer was not a space character (including newline) or EOS... 

Le %n rapporti direttiva relativa al numero di caratteri consumato fino a quel momento e non conta come una conversione (quindi c'è una sola conversione in quel formato). Lo %n è standard in sscanf() da C89.

Per l'estrazione di un singolo intero, si potrebbe anche usare strtol() - attenzione (rilevazione condizioni di errore con esso è sorprendentemente difficile, ma è meglio di sscanf() che non riferirà o rilevare overflow). Tuttavia, questa tecnica può essere utilizzata più volte in un unico formato, che è spesso più conveniente.

2

Si desidera leggere numeri interi da stringhe. È più semplice farlo con strtol anziché sscanf. strtol restituirà, indirettamente tramite endptr, l'indirizzo subito dopo l'ultimo carattere che è stato letto correttamente nel numero. Se, e solo se, la stringa era un numero, quindi endptr punta alla fine della stringa numerica, ad esempio *endptr == \0.

char *endptr = NULL; 
long n = strtol(sInput, &endptr, 10); 
bool isNumber = endptr!=NULL && *endptr==0 && errno==0; 

(spazio bianco iniziale è ignorato. Consulta l'strtol man page per i dettagli.

+0

Ho aggiunto del testo alla risposta per spiegare il codice. Spero non ti dispiaccia @ Serge-appTranslator. Sentiti libero di modificarlo ulteriormente o di rimuoverlo. –

+1

Cosa? testo? Perché non commentare il codice mentre ci sei! :-) Grazie Aaron –

0

scanf non è così intelligente. Dovrete leggere l'input come testo e utilizzare strtol per convertirlo. Uno dei argomenti strtol è una char * che punterà al primo carattere che non convertito, se quel carattere non è uno spazio o 0, allora la stringa di input non è un numero intero valido:

char input[SIZE]; // where SIZE is large enough for the expected values plus 
        // a sign, newline character, and 0 terminator 
... 
if (fgets(input, sizeof input, stdin)) 
{ 
    char *chk; 
    long val = strtol(input, &chk, 10); 
    if (*chk == NULL || !isspace(*chk) && *chk != 0) 
    { 
    // input wasn't an integer string 
    } 
} 
+0

La domanda riguarda 'sscanf', non' scanf', e quindi i dati sono già in una stringa. Vedi @ risposta di Serge. –

+0

Questo non è corretto: puoi usare '[fs] scanf()' per questo OK: devi solo provare a leggere qualcosa dopo il numero e controllare il numero di elementi letti. –

2

Questo è facile. Non è richiesto C++ di fantasia! Basta fare:

char unusedChar; 
if (sscanf(sInput, "%d%c", &iAssignmentMarks[0], &unusedChar) == 1) 
Problemi correlati