come creare una collezione di dati non omogenea e di numero finito.

Mi trovo a dovere gestire una collezione di dati molti simile ad un database, la collezione è di numero finito ma non è omogenea nel senso che un dato può essere un intero o un double.

La collezione (database) è composta da una stringa di tre caratteri che rappresenta il parametro che ha un valore associato che può essere un intero o un double (o float che sia).
Il parametro deve essere visualizzato su un display 7 segmenti e pigiando un pulsante si accede al valore che può essere modificato tramite i tasti + e -. Il range ammesso è diverso per ogni parametro e quindi fa parte del database. Il numero di parametri è alto, siamo sulla cinquantina (50).

Per gestire questo database ho pensato a strutture contenenti union {int e double} un char[4] scritto in FLASH, un valore minimo intero, e uno massimo intero, ma ancora non ho scritto nulla per il database, mentre c'è il codice per il display, per la tastiera ecc. Ho eseguito dei test per modificare dei parametri è tutto funziona, ma ho usato una collezione omogemea di numero finito e invece a me serve una collezione non omogenea.

Avete idee, codice, link ecc.

Ciao.

Da quel che dici, mi sembra che effettivamente non puoi che usare una struct, anzi un vettore di una struct
http://www.cplusplus.com/doc/tutorial/structures/

Però eviterei le union. Secondo me puoi farne a meno. Utilizza e memorizza i valori numerici in tipo di variabile più grande.
Un database però ha la possibilità di ordinare i dati di una tabella attraverso un indice. Qui viene difficile. A meno di usare linked list.

Prova a guardare anche i dizionari, se ho capito bene potresti usare la stringa come key in correlazione con una struct contenente 4 byte e un parametro (booleano) che ti dice come interpretarli (come float o come long).

In tutti i casi occhio alla RAM :grin:

Avevo scritto e postato, ma il sito ha deciso che non dovevo postare. (Odio le macchine che prendono iniziative)

Da quel che dici, mi sembra che effettivamente non puoi che usare una struct, anzi un vettore di una struct
Data structures - C++ Tutorials

Infatti, ma se la struct contiene una variabile per specificare il tipo e una union { int; double;} posso usare gli array di struttura.

@yoshi93
nid mi sconsiglia le union, tu invece mi consigli 4 variabili byte che occupano quanto un double (su avr8), alla fine sia con la union che con 4 byte il consumo di ram è lo stesso, quindi che strada prendo per la sperimentazione? union o non union questo è il problema. XD

Al momento ho questo codice:

// file:                                                 datacollection.h

// level_type contiene doppia informazione
// i primi due bit meno significativi contengono il tipo
// i secondi due bit contengono il livello di accesso del parametro

typedef struct {
    const char *show_name;
    uint8_t level_type;
    union {
        int16_t int16_data;
        double double_data;
    } data;
} node_list_t;

// file:                               datacollection.c
node_list_t parameter[50];

const char set[] PROGMEM = "SEt";
void initialize_parameter() {

    parameter[0].show_name = set;
    parameter[0].level_type = 1;
    parameter[0].data.double_data = 0.0;
}

PS: al momento ho altro codice sotto test che usa la stringa come chiave proprio come un dizionario, devo trasformare il valore in una union o usare 4 byte separati. Solo che mi sono reso conto che l'accesso tramite chiave non lo uso mai e non mi torna utile per organizzare l'accesso sequenziale, almeno credo devo verificare.

Ciao.

MauroTec:
nid mi sconsiglia le union, tu invece mi consigli 4 variabili byte che occupano quanto un double (su avr8), alla fine sia con la union che con 4 byte il consumo di ram è lo stesso, quindi che strada prendo per la sperimentazione? union o non union questo è il problema. XD

E' solo una questione di comodità. Forse con la union semplifichi certi accessi (come sintassi).

@Mauro:
mi sfugge il perchè della necessità di una collezione non omogenea ... se non prevedi di avere un sistema per aggiungere/togliere parametri (e relativi valori) a runtime, mi sembra molto più indicato usare un array di struct, e accedervi direttamente via indice (ripeto, se non ne devi aggiungere/togliere in maniera dinamica), anche se prevedi di dover accedere ad un valore via chiave identificativa, mi sembra molto più semplice utilizzare l'array di struct e implementare una funzione search che prende la stringa come parametro e cicla sull'array per trovare l'indice giusto ...

Per il discorso occupazione di memoria, se pensi di essere così a corto di spazio potresti risparmiare l' intero al costo di scrivere un pò più di codice per gestire gli incrementi degli interi memorizzati nei double ...

mi sfugge il perchè della necessità di una collezione non omogenea ... se non prevedi di avere un sistema per aggiungere/togliere parametri

Non omogenea è riferito al fatto che una struct può contenere valori double o int, in effetti non omogenea normarlmente è riferita ad oggetti di diverso tipo, quindi il termine che ho usato non è proprio azzeccato ma non mi veniva niente altro.

Per il discorso occupazione di memoria, se pensi di essere così a corto di spazio potresti risparmiare l' intero al costo di scrivere un pò più di codice per gestire gli incrementi degli interi memorizzati nei double ...

L'idea mi è passata per la testa, ma poi l'ho scartata momentaneamente, ora rivalutandola mi sembra ancora più semplice, sempre che funzioni quello che ho in mente. Un double castato ad intero è possibile, quindi prima di visualizzare il valore sul display se necessario (flag di tipo) lo casto a int. che dici potrebbe funzionare?

Per la memoria ancora non ho fatto il conto, ma alla fine se non ci sto dentro limito il numero di parametri in quanto non sono tutti e 50 necessari. I parametri aggiungono funzionalità e flessibilità solo pochi sono vitali per il funzionamento dell'algoritmo.

Ciao.

MauroTec:
Non omogenea è riferito al fatto che una struct può contenere valori double o int, in effetti non omogenea normarlmente è riferita ad oggetti di diverso tipo, quindi il termine che ho usato non è proprio azzeccato ma non mi veniva niente altro.

Ok .. io con non omogenea avevo inteso 'sparsa' e quindi pensavo ad un array associativo, soprattutto perchè inizialmente avevi parlato di database, quindi pensavo volessi avere la possibilità di memorizzare i parametri per 'chiave' e recuperarli per 'chiave'.

Se avessi tipi di dato più complessi la soluzione standard, rimanendo alle struct è di avere una struct contenitore con i dati in comune (il nome), il tipo di dato a cui fa riferimento e un puntatore ad una struct adeguata, o per evitare di dover gestire l'allocazione dinamica della memoria l'indice a cui fare riferimento in un array di struct del tipo giusto.

In pratica dovresti avere un array di struct tipo1, un array di struct tipo2 e un array di struct base dove ogni elemento dell'array contiene il tipo di dato e l'indice dell'array a cui fare riferimento ... diventa complicato e molto più flessibile usando delle classi, ma si entra nella programmazione ad oggetti e non so quanto per i tuoi scopi sia necessario dato che le dimensioni ed il tipo della struttura dati ti sono note al momento della compilazione.

L'idea mi è passata per la testa, ma poi l'ho scartata momentaneamente, ora rivalutandola mi sembra ancora più semplice, sempre che funzioni quello che ho in mente. Un double castato ad intero è possibile, quindi prima di visualizzare il valore sul display se necessario (flag di tipo) lo casto a int. che dici potrebbe funzionare?

Per la memoria ancora non ho fatto il conto, ma alla fine se non ci sto dentro limito il numero di parametri in quanto non sono tutti e 50 necessari. I parametri aggiungono funzionalità e flessibilità solo pochi sono vitali per il funzionamento dell'algoritmo.

Ciao.

Un double castato a intero è sicuramente possibile ed era quello che avevo in mente, dovrai tenere conto del tipo di dato quando vai a gestire la modifica in quanto il double dovrà essere incrementato di 0.1 o 0.01 o in funzione del tipo, mentre l'intero dovrà essere modificato con incrementi di +- 1