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.)

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top