Il modo migliore per verificare se è cifra in base specifica in c
Domanda
So che ctype.h
definisce isdigit
, tuttavia, funziona solo per la base 10. Vorrei verificare se un numero è una cifra in una determinata base int b
.
Qual è il modo migliore per farlo in C?
Modificare
Ho escogitato la seguente funzione:
int y_isdigit(char c, int b) {
static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static int digitslen = sizeof digits - 1;
static int lowest = 0;
int highest = b - 1;
if(highest >= digitslen)
return -1; /* can't handle bases above 35 */
if(b < 1)
return -2; /* can't handle bases below unary */
if(b == 1)
return c == '1'; /* special case */
int loc = strchr(digits, c);
return loc >= lowest && loc <= highest;
}
C'è qualche vantaggio nell'utilizzare la versione che Schnaader ha fatto a questo? (Questo sembra avere l'ulteriore vantaggio di non fare affidamento sul fatto che il chatset dell'utente sia ASCII, non più che importa molto.)
Soluzione
Suggerirei qualcosa di simile:
// input: char c
if (b <= 10) {
if ((c >= '0') && (c < ('0' + b))) {
// is digit
}
} else if (b <= 36) {
if ((c >= '0') && (c <= '9')) {
// is digit
} else if ((c >= 'A') && (c < 'A' + (b - 10))) {
// is digit
}
}
Questo dovrebbe funzionare (non testato) per la base 2..36 se stai usando 0
..9
e A
..Z
.
Un'alternativa sarebbe quella di utilizzare una tabella di ricerca booleana, questo è il modo più veloce per controllare. Ad esempio, è possibile preparare le tabelle per le basi 2..36, usando 256*35 = 8960 byte di memoria, dopo questo il isdigit
Controllare è una semplice memoria lettura.
Altri suggerimenti
Se stai usando basi convenzionali (ad esempio ottale o esadecimale) puoi usare strtol()
Per convertire e verificare una condizione di errore. Se stai usando basi arbitrarie, ad esempio, la base 99 potrebbe non esserci una soluzione fuori dalla scatola.
Il vantaggio di isdigit
è che di solito è una macro che si espande al momento della compilazione. Ce n'è anche un altro isxdigit
.
Se vuoi fare lo stesso per la tua convention di cifre, potresti andare per un inline
funzione che sarebbe quasi altrettanto buona:
inline
bool isdigit42(char c) {
switch (c) {
default: return false;
case '0': return true;
case '1': return true;
.
.
}
}
Il tuo compilatore saprebbe meglio quali casi possono essere abbreviati perché i personaggi sono in una gamma comune di valori. E nel caso in cui questo sia chiamato con un carattere costante di tempo di compilazione, questo dovrebbe essere completamente ottimizzato.