come programmare una tabella di ricerca di variabili di input e output

2

Questa è una piccola applicazione C ++ (e la tabella non è enorme neanche), quindi se possibile vorrei evitare di includere qualcosa di diverso da STL (e boost).

Quindi al problema:

Ho una tabella di corrispondenza predefinita delle condizioni di input e output. Questa tabella contiene 4 variabili di input (stati) e la loro combinazione porta a 1 variabile di output. In sostanza:

output = f(a,b,c,d) 

vale a dire. "la variabile di uscita è una funzione di 4 variabili di input"

  • La variabile di uscita è un allarme e può assumere uno dei 3 stati (ok, warning, fault).
  • "A" può assumere 1 di 3 stati (ad esempio 0 o 1 o 2). Allo stesso modo
  • "B" può assumere 1 di 5 stati
  • "C" può assumere 1 di 3 stati
  • "D" può assumere 1 di 2 stati

Voglio fornire i valori alle variabili di input e ottenere la variabile di output in cambio da questa tabella di ricerca.

La tabella potrebbe apparire un po 'come questa:

A | B | C | D | output  
----------------------
1 | 3 | 0 | 1 | ok
0 | 2 | 1 | 2 | fault
0 | 0 | 0 | 0 | warning

... e così via. Quindi la tabella non avrà più di 150 voci (un po 'di ottimizzazione l'ha aiutato) che non è enorme, ma è ancora troppo grande se provo a creare if-statid annidate. Cosa posso fare per evitare enormi dichiarazioni di if ?

Quello che sto cercando è uno schema di progettazione, o qualche buon riferimento su cui leggere.

Ad esempio una specie di map che può contenere 4 chiavi e 1 valore sarebbe l'ideale. Qualcosa come la mappa sarebbe probabilmente l'ideale.

    
posta nass 30.06.2016 - 20:47
fonte

2 risposte

4

Soluzione di tempo di compilazione 1 (pulita)

Potresti "concatenare" i valori di input usando tuple e mappare queste tuple al tuo tipo di output. Ecco come farlo con una stringa come output:

string f (int a, int b, int c, int d) {
    using input =  tuple<int,int,int,int>;

    static map<input,string> mytable =  {
        { input{ 1, 3, 0, 1 }, "ok"}, 
        { input{ 0, 2, 1, 2 }, "fault"},
        { input{ 0, 0, 0, 0 }, "warning"}
    };
    return mytable[input{a,b,c,d}];
}

Ecco una demo online . Tieni presente che nello snippet precedente, se la combinazione non esce, una nuova combinazione viene aggiunta alla mappa con una stringa vuota. Se dovessi gestire tali errori, potresti ad esempio utilizzare mytable.at(...) anziché mytable[...] per lanciare un'eccezione fuori limite

Questo approccio è molto potente , perché le tuple possono aggregare i tipi reali utilizzati dall'utente per i dati di input. È facile da mantenere. Inoltre, la ricerca della mappa è molto efficiente : O (log n) rispetto a O (n) per una if-chain.

Tempo di compilazione soluzione 2 (facile)

Un altro approccio potrebbe essere quello di combinare gli stati, se ognuno ha un valore numerico. Questo non è così pulito come il precedente a causa della strong ipotesi sul tipo di input, ma potrebbe fare il trucco:

string f (int a, int b, int c, int d) {
    // assumes that a,b,c and d are between 0 and 9 

    static map<int,string> mytable =  {
        { 1301, "ok"}, 
        { 0212, "fault"},
        { 0000, "warning"}
    };
    return mytable[a*1000+b*100+c*10+d];
}

Tieni presente che potresti anche utilizzare un'istruzione switch in questo caso. La maggior parte del compilatore moderno genera una tabella di branche ottimizzata, che sarà comunque almeno performante di una catena if se non di più.

Approccio al tempo di esecuzione (flessibile)

Una variante della soluzione 1 potrebbe essere quella di inizializzare la mappa in fase di esecuzione. Invece di specificare un elenco di inizializzazione nel codice, basta leggere i dati di input e di output da un file e creare la mappa durante l'avvio dell'applicazione.

Potrebbe non essere rilevante per il tuo problema. Ma volevo menzionarlo qui, perché a volte questo può aiutare a ottenere un software molto flessibile che consente all'utente di scegliere il comportamento desiderato a un costo minimo.

    
risposta data 30.06.2016 - 21:54
fonte
0

Questa è una funzione matematica di base che traduce un dominio in un altro. I suggerimenti dati dai membri precedenti sono eccellenti. Manterrei il numero intero come una chiave, in quanto richiede meno spazio. L'approccio esadecimale dato da Cristophe potrebbe essere la soluzione migliore qui, in quanto fornisce un modo semplice per ottenere indietro i singoli input se necessario. Non dimenticare, se non hai uscite per tutte le combinazioni di input, assicurati di gestire correttamente l'output predefinito.

    
risposta data 01.07.2016 - 09:07
fonte

Leggi altre domande sui tag