2011-03-04 21 views
10

Se si dispone di un set di valori stringa piccoli e si desidera recuperare un valore numerico per rappresentarli, qual è il modo migliore per farlo tramite una tabella di ricerca?Tabella di ricerca del valore in C per stringhe?

Se fossi solo bisogno di fare uno sguardo verso l'alto, so che la soluzione ottimale sarebbe solo una serie di istruzioni if:

if (strcmp(str, "foo") == 0) 
    tmp = FOO; 
else if (strcmp(str, "bar") == 0) 
    tmp = BAR; 

Ma, mi chiedo perché questi piccoli valori di stringa rappresentano un attributo in un piccolo progetto sto scrivendo in C, e gli attributi possono essere di sola lettura o di lettura-scrittura (non scrivere solo per ora, forse mai).

Quindi quello che faccio al momento giusto per assicurarmi che le cose funzionino è avere una funzione di ricerca composta da una clausola if-then come sopra per cercare quali valori sono di sola lettura, e una seconda funzione che cerca quali valori vengono letti -Scrivi. Ma questo è grande e brutto per me.

Sto pensando, ho tre funzioni. Una funzione è la funzione di ricerca e restituisce un valore int che è la forma numerica della stringa. Ma questa funzione di ricerca può anche assumere un flag che determina se recupera un valore di sola lettura o un valore di lettura-scrittura. Se un'operazione di scrittura viene eseguita su un valore che è realmente di sola lettura, la funzione restituirà -EINVAL (o qualcosa di equivalente).

Le altre due funzioni, ora ancora la lettura e la scrittura, chiamano semplicemente questa funzione di ricerca, passando una stringa del valore e la bandiera che determina se sono per la lettura o la scrittura.

Il fatto è che non so come sia modellato in C (se può essere modellato), e la ricerca di Google è noiosa con tutte le farm di contenuti che eliminano questo posto (e mi danno invece le risposte C++/C#) .

Quindi questo è come penso che guarderò:

int lookup_func(const char *name, const char *flag) { 
    int tmpval = 0; 

    /* code to do the lookup. */ 

    if (tmpval == 0) 
     return -EINVAL; 
    else 
     return tmpval; 
} 

int get_readonly_bit(const char *name) { 
    return lookup_func(name, "ro"); 
} 

int get_readwrite_bit(const char *name) { 
    return lookup_func(name, "rw") 
} 

Pensieri? L'idea è di ridurre le dimensioni del codice non ripetendo i rami if-then per queste due funzioni, che differiscono leggermente nella progettazione generale, e lasciano semplicemente che una specie di funzione di ricerca capisca quale funzione serve a questo valore.

+0

+1 per const correttezza ... * ma la bandiera è meglio come un int (o enum) * – pmg

+0

You want an [funzione di hash] (http://en.wikipedia.org/wiki/Hash_function). A seconda dei valori della stringa, potrebbe essere semplice come restituire il valore della prima lettera ... – pmg

+0

@ pmg: c'è ancora una probabilità di più stringhe con lo stesso hash. Piccolo, ma è :) –

risposta

6

Non consideri semplicemente di mettere un tavolo? Anche una tabella hash va bene se ci sono molte proprietà.

int lookup(const char *name) 
{ 
    typedef struct item_t { const char *name; int writable; int value; } item_t; 
    item_t table[] = { 
    { "foo", 0, FOO }, 
    { "bar", 1, BAR }, 
    { NULL, 0, 0 } 
    }; 
    for (item_t *p = table; p->name != NULL; ++p) { 
     if (strcmp(p->name, prop_name) == 0) { 
      return p->value; 
     } 
    } 
    return -EINVAL; 
}
+0

Bella soluzione. Se sei preoccupato solo per il codice "grande e brutto", questo dovrebbe essere fatto, giusto? Se la tabella è lunga e il tuo programma fa molte ricerche, proverei a lavorare su quel ciclo: ad es. cerca un'implementazione di ricerca binaria che si applica alle stringhe ed è scritta in c, ovviamente. – AudioDroid

+1

@ AudioDroid: cosa c'è di grande e di brutto? È semplice, comprensibile e abbastanza robusto e l'ho visto usato in molti posti. L'algoritmo è O (n) che potrebbe essere un problema per le liste lunghe. Tuttavia, se si tratta di un problema dovrebbe essere determinato con l'analisi delle prestazioni, non con congetture. – JeremyP

+0

Personalmente scoraggio questo tipo di soluzione per scopi diversi da quelli banali. Quando si utilizzano le stringhe in questo modo, il problema delle impostazioni locali e della distinzione tra maiuscole e minuscole può essere problematico. Inoltre, l'efficienza è sospetta.Uno strcmp implica una sequenza di confronti ripetuti quando un confronto di una chiave hash è sufficiente. Quando si confrontano le prestazioni dell'hashing con uno strcmp, il metodo hash dimostra prestazioni migliori per tutti tranne gli elenchi banali (nella mia esperienza). – Throwback1986

Problemi correlati