2012-03-17 13 views
18

Devo verificare se una stringa C è un numero intero valido.Determinare se una stringa C è un valore int valido in C

Ho provato entrambi

int num=atoi(str); 

e

int res=sscanf(str, "%d", &num); 

Ma l'invio della stringa "8 -9 10" in entrambe le linee tornato semplicemente 8, senza indicare l'invalidità di questa stringa.

Qualcuno può suggerire un'alternativa?

+0

'atoi' non verifica errori; il suo comportamento se 'str' non contiene una rappresentazione di un valore' int' non è definito. (Tipiche implementazioni restituiscono '0'.)' Sscanf' è migliore, ma il suo comportamento non è definito se il valore nella stringa non è rappresentabile come 'int'. Inoltre, il tuo titolo dice che vuoi controllare un int valido, ma il corpo della tua domanda dice "numero intero valido"; non sono la stessa cosa 'int' è uno dei numerosi * tipi interi *. –

risposta

29

Dai un'occhiata a strtol(), può dirti delle parti non valide della stringa tramite il ritorno del puntatore.

E fare attenzione al codice di esempio entusiasta .. consultare la pagina man per la gestione completa degli errori.

+0

strtol() imposta semplicemente il puntatore sul prossimo "oggetto" nella stringa. Non convalida nulla. –

+1

@ g24l Se quel puntatore finisce per puntare su NULL, allora sai che l'intera stringa era valida. Se no, no. Tadaa! – blueshift

+0

Se è una stringa terminata da null. –

8

Forse avrò in malo modo perché non usare strtol o simili libc funzioni, ma ragionando su questo problema non è così difficile:

#include <stdbool.h> // if using C99... for C++ leave this out. 
#include <ctype.h> 

bool is_valid_int(const char *str) 
{ 
    // Handle negative numbers. 
    // 
    if (*str == '-') 
     ++str; 

    // Handle empty string or just "-". 
    // 
    if (!*str) 
     return false; 

    // Check for non-digit chars in the rest of the stirng. 
    // 
    while (*str) 
    { 
     if (!isdigit(*str)) 
     return false; 
     else 
     ++str; 
    } 

    return true; 
} 

[NB: avrei potuto altrimenti fatto isdigit(*str++) al posto del else a tenerlo più breve ma ricordo che gli standard dicono che è possibile che isdigit sia una macro.]

Suppongo che una limitazione sia che questo non restituisce false se il numero nella stringa non si adatta a un numero intero. Questo potrebbe non avere importanza per te.

+1

"non così difficile", ma è necessario tornare e modificarlo;) – blueshift

+1

@blueshift Punto preso, ma 1 modifica in 5 minuti quando digitare il codice in un modulo Web non è poi così male per me. :-) – asveikau

+0

In questo caso non so se è più soggetto a errori di rollare il proprio o per cercare di ottenere la gestione degli errori per strtol() giusto .. Probabilmente mi raccomando ancora strtol. – blueshift

2

Un modo semplice per farlo robusto sarebbe leggere l'int e assicurarsi che sia rappresentazione stringa è identica alla stringa di input, ad esempio una combinazione atoi e itoa:

int is_int(char const* p) 
{ 
    return strcmp(itoa(atoi(p)), p) == 0; 
} 
+0

Bella idea :). Tuttavia, ciò richiederà anche il taglio degli spazi iniziali e finali, al fine di farlo funzionare. – sara

+3

Si noti che questa soluzione non è conforme ANSI. –

0

Per verificare se stringa contiene un numero valido puoi usare un'espressione regolare. Ad esempio per gli interi utilizzare:

[- +] [0-9] +

e un caso generale per i numeri in virgola mobile:??

[+ -] [0-9] + [ .] [0-9] * ([ee] [- +] [0-9] +?)?

Nel caso di C++ 11 le funzioni di espressione regolare sono disponibili in libreria, ad es. "std :: regex_match (.....)" indica la corrispondenza esatta. Il codice dovrebbe essere così:

#include <regex> 
..... 
std::string strnumber("-1.234e+01"); 
float number; 
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?")) 
number=std::stof(strnumber); 
else 
std::cout<<"error, string is not a valid number"; 
0

Ci scusiamo per scavare il tema, ma per amore di completezza e perché questa discussione è la prima partita quando si fa una ricerca su Google ...

E 'possibile usare qualcosa come:

ret = sscanf(string, "%d%n", &number, &idx); 
if (ret == 0 || string[idx] != '\0') 
    /* handle the error */ 

direttiva %n, che sembra essere standard C secondo la pagina man, conta il numero di caratteri trasformati.

[Edit] sscanf non sembra fornire un modo per rilevare overflow, così la famiglia funzioni strtoX dovrebbe essere preferito IMHO.

Problemi correlati