2009-11-05 5 views

Répondre

2

Vous voulez probablement un fragment de code plus comme ceci:

double number; 
do { 
    printf("Enter a double: "); 
    scanf("%*c"); // burn stdin so as not to buffer up responses 
} while (1 != scanf("%lf", &number)); 

Cependant, comme Jonathan l'a souligné, une meilleure analyse ligne par ligne peut être mieux. Scanner directement à partir de stdin de cette façon n'est pas intuitif pour l'utilisateur.

+0

Ok c'est quoi scanf ("% * c"); tout sur? –

+0

Il lit le caractère suivant - peut-être une nouvelle ligne, peut-être quelque chose d'autre - sans l'assigner à quelque chose. –

+0

Ok, merci ..... –

8

Vérifiez la valeur renvoyée par scanf(); il vous indique le nombre de conversions réussies.

Dans le contexte, si la conversion échoue, vous obtenez 0; Si elle réussit, vous obtenez 1.

La récupération d'erreur doit être envisagée. Je trouve généralement plus facile de lire une ligne de données en utilisant fgets() - et ne reçoit jamais()! - et ensuite le traiter avec sscanf(). Il est facile d'ignorer les données erronées si la conversion échoue.

+0

Comment vérifier la valeur de retour de scanf? –

+2

Vérifiez la valeur de retour de scanf avec, par exemple, 'if (scanf ("% lf ", & nombre)! = 1)/* erreur: le numéro est" invalide "* /;'. – pmg

3

Si vous voulez être sûr que la valeur attendue par l'utilisateur coïncide avec la valeur retournée en passant la chaîne à atof (str)- y compris la notation exposant - alors le code suivant fonctionne.

Vous pouvez obtenir l'entrée en utilisant fgets (str, size, stdin), et vous n'avez même pas à supprimer la nouvelle ligne de fin avant de passer la chaîne à l'analyseur.

En outre, s'il existe une erreur d'analyse, la fonction signale l'emplacement du caractère coupable à un pointeur passé en tant qu'argument supplémentaire.

Il existe une forme longue - plus facile à lire, et une forme courte - plus facile à taper.

Forme longue:


/* 
    Copyright (C) 2010 S. Randall Sawyer 

This code is in the public domain. It is intended to be usefully illustrative. 
It is not intended to be used for any particular application. If this code is 
used in any application - whether open source or proprietary, then please give 
credit to the author. 

*/ 

#include <ctype.h> 

#define FAILURE (0) 
#define SUCCESS (!FAILURE) 

enum { 
    END_EXPRESSION  = 0x00, 
    ALLOW_POINT   = 0x01, 
    ALLOW_NEGATIVE  = 0x02, 
    REQUIRE_DIGIT   = 0x04, 
    ALLOW_EXPONENT  = 0x08, 
    HAVE_EXPONENT   = 0x10, 
    EXPECT_EXPRESSION  = ALLOW_POINT | ALLOW_NEGATIVE | REQUIRE_DIGIT, 
    EXPECT_INTEGER  = ~ALLOW_POINT, 
    EXPECT_POS_EXPRESSION = ~ALLOW_NEGATIVE, 
    EXPECT_POS_INTEGER = EXPECT_INTEGER & EXPECT_POS_EXPRESSION, 
    EXPECT_EXPONENT  = EXPECT_INTEGER^HAVE_EXPONENT, 
    EXPONENT_FLAGS  = REQUIRE_DIGIT | ALLOW_EXPONENT | HAVE_EXPONENT 
} DoubleParseFlag; 

int double_parse_long (const char * str, const char ** err_ptr) 
{ 
    int ret_val, flags; 
    const char * ptr; 

    flags = EXPECT_EXPRESSION; 
    ptr = str; 

    do { 

    if (isdigit (*ptr)) { 
     ret_val = SUCCESS; 
     /* The '+' here is the key: It toggles 'ALLOW_EXPONENT' and 
      'HAVE_EXPONENT' successively */ 
     flags = (flags + (flags & REQUIRE_DIGIT)) & EXPECT_POS_EXPRESSION; 
    } 
    else if ((*ptr & 0x5f) == 'E') { 
     ret_val = ((flags & (EXPONENT_FLAGS)) == ALLOW_EXPONENT); 
     flags = EXPECT_EXPONENT; 
    } 
    else if (*ptr == '.') { 
     ret_val = (flags & ALLOW_POINT); 
     flags = (flags & EXPECT_POS_INTEGER); 
    } 
    else if (*ptr == '-') { 
     ret_val = (flags & ALLOW_NEGATIVE); 
     flags = (flags & EXPECT_POS_EXPRESSION); 
    } 
    else if (iscntrl (*ptr)) { 
     ret_val = !(flags & REQUIRE_DIGIT); 
     flags = END_EXPRESSION; 
    } 
    else { 
     ret_val = FAILURE; 
     flags = END_EXPRESSION; 
    } 

    ptr++; 

    } while (ret_val && flags); 

    if (err_ptr != NULL) 
    *err_ptr = ptr - 1; 

    return ret_val; 
} 

Forme courte:


/* 
    Copyright (C) 2010 S. Randall Sawyer 

This code is in the public domain. It is intended to be usefully illustrative. 
It is not intended to be used for any particular application. If this code is 
used in any application - whether open source or proprietary, then please give 
credit to the author. 

*/ 

#include <ctype.h> 

int double_parse_short (const char * str, const char ** err_ptr) 
{ 
    int ret_val, flags; 
    const char * ptr; 

    flags = 0x07; 
    ptr = str; 

    do { 

    ret_val = (iscntrl (*ptr)) ? !(flags & 0x04) : (
       (*ptr == '.') ? flags & 0x01 : (
       (*ptr == '-') ? flags & 0x02 : (
       ((*ptr & 0x5f) == 'E') ? ((flags & 0x1c) == 0x08) : (
       (isdigit (*ptr)) ? 1 : 0)))); 

    flags = (isdigit (*ptr)) ? 
       (flags + (flags & 0x04)) & 0x1d : (
       ((*ptr & 0x5f) == 'E') ? 0x0e : (
       (*ptr == '-') ? flags & 0x1d : (
       (*ptr == '.') ? flags & 0x1c : 0))); 

    ptr++; 

    } while (ret_val && flags); 

    if (err_ptr != NULL) 
    *err_ptr = ptr - 1; 

    return ret_val; 
} 

J'espère que cela aide!

Questions connexes