Codifica C: legge solo il numero in virgola mobile con decimale e rifiuto di caratteri interi e speciali

Sto cercando di scrivere un codice in C (gcc) per accettare solo numeri mobili con decimali e rigetti interi, caratteri speciali, immissione alfanumerica.

Le voci valide sono:

1.23, 3.45, 6.77 

Voci non valide:

 abc, e34, 834ww, 6, 9, 

e alcune cose blah che non è un galleggiante. Questo è quello che ho provato:

 #include  int main() { double floatnum; double decpart=0.000000; printf("Enter a floating number num: "); while (decpart == 0.0000000) { scanf("%lf", &floatnum); int intpart = (int)floatnum; double decpart = floatnum - intpart; if (decpart == 0.000000){ printf("Invalid floating point number, enter again: "); } else { printf("Number entered = %.2f\n", floatnum); break; } } return 0; } 

Non voglio il codice esatto, ma ho bisogno di alcuni indicatori / indizi su quale sarebbe il modo migliore per farlo.

Ho rielaborato il tuo codice lasciando cadere la parte scanf e sostituendolo con una combinazione di fgets e strtod .

Controlli effettuati:

  • numero valido inserito (controllando se l’endptr restituito dai punti strtod sul char linefeed , il che significa che l’intera stringa immessa è stata analizzata correttamente): evita numeri 42.4xxxx E moduli come 42.4xxxx accettati da atof per esempio
  • se lo spazio finale viene aggiunto dopo il numero singolo, viene sostituito dal linefeed e quindi accettato dal programma
  • il tuo codice di controllo decimale, invariato
  • il programma consente numeri come 12.455e+1 pass ( 124.55 ), ma forse è una caratteristica piuttosto che un bug poiché è valido come float.

codice fisso:

 #include  #include  #include  int main() { double decpart; printf("Enter a floating number num: "); char buf[100]; int len; char *endptr; while (fgets(buf,sizeof(buf),stdin) != NULL) { len = strlen(buf)-1; // right strip spaces (replace by linefeed like fgets ends the input) while (len>0) { len--; if (buf[len]==' ') { buf[len]='\n'; } else { break; } } double floatnum = strtod(buf,&endptr); if ((endptr==buf)||(endptr[0]!='\n')) { printf("Invalid floating point number, enter again: "); } else { int intpart = (int)floatnum; double decpart = floatnum - intpart; if (decpart == 0.000000){ printf("Invalid floating point number, enter again: "); } else { printf("Number entered = %.2f\n", floatnum); break; } } } return 0; } 

test:

 Enter a floating number num: no Invalid floating point number, enter again: 45 Invalid floating point number, enter again: 45.6xxx Invalid floating point number, enter again: 45.6 Number entered = 45.60 

Come hai commentato sopra, stai prendendo un carattere alla volta, quindi puoi contare il numero di decimali e caratteri mentre prendi l’input e poi controlla se count_alpha> 0 e count_dots> 1, quindi il suo valore non valido è valido.

Non voglio il codice esatto, ma ho bisogno di alcuni suggerimenti / indizi su quale sarebbe il modo migliore per ottenerlo (leggere solo il numero in virgola mobile con decimale e scarto di numeri interi e caratteri speciali).

  1. Leggi come stringa ( fgets() )

  2. La stringa assicurata contiene un '.' , 'E' o 'e' , rifiutare altrimenti.

  3. Verifica se converte come FP correttamente senza junk finale. ( strtod() o sscanf("%lf %n",... ) ed è finito ( isfinite() )

La specifica è ambigua: hai intenzione di accettare 0.00 come un valore in virgola mobile con decimali, anche se capita di avere un valore integrale?

La tua implementazione la respingerebbe, ma accetterebbe 1e-1 che non corrisponde ai criteri.

Ecco un’alternativa che accetta numeri positivi con cifre prima e dopo un punto decimale:

 #include  #include  int main() { char buf[80]; double floatnum; printf("Enter floating point numbers: "); while (scanf("%79s", buf) == 1) { int len = strlen(buf); int pos = -1; sscanf(buf, "%*[0-9].%*[0-9]%n", &pos); if (pos == len && sscanf(buf, "%lf", &floatnum) == 1) { printf("Number entered = %.2f\n", floatnum); } else { printf("Invalid floating point number: %s, enter again: ", buf); } } return 0; } 

Se si desidera accettare anche numeri e numeri negativi con un segno positivo ridondante, è ansible estendere il validatore per saltare un segno iniziale.