PDA

Visualizza la versione completa : [C++] Unità di misura


ing82
12-04-2015, 15:48
Problema: gestire la possibilità di cambiare le unità di misura durante l'esecuzione di un programma. Ad esempio, se io preferisco inserire le dimensioni in cm, posso scegliere cm, un altro utente preferisce i mm, può inserire le dimensioni in mm. Stessa cosa per i risultati delle elaborazioni, sia visualizzazione a video che salvataggio dati.

Pensavo di risolvere così: tutte le operazioni all'interno del programma vengono fatte come se i dati fossero secondo le unità di misura del sistema internazionale (m per lunghezze, kg per la massa, s per il tempo, ecc).
La possibilità di cambiare le unità di misura viene gestita mediante una classe che serve a "manipolare" un oggetto che permette all'utente di scegliere le unità di misura.
Questo oggetto viene passato come parametro a tutte le funzioni del programma che si occupano di input e output, in modo che verificata l'unità di misura impostata dall'utente, attraverso l'opportuno coefficiente effettuino la conversione dall'unità scelta dall'utente a quella del sistema internazionale per svolgere le operazioni su di essi, in fase di visualizzazione per passare dal sistema internazionale alle unità scelte dall'utente.

Soluzioni migliori?

Grazie

MItaly
12-04-2015, 18:42
Di norma questa è la soluzione che si usa, talvolta usando come unità interna il sottomultiplo più piccolo utilizzabile (in modo da poter lavorare con interi, se la cosa può essere utile dal punto di vista delle prestazioni o per evitare problemi di precisione FP). Spesso comunque l'oggetto che rappresenta la scelta dell'utente in termini di unità di misura viene tenuto come globale, in modo da evitare di doverlo continuamente passare in giro; in quest'ultimo caso però bisogna stare molto attenti a distinguere tra funzioni di parsing/output da/per utente e da/per formati human-readable (ma che comunque non devono essere influenzati dalle preferenze).

ing82
12-04-2015, 19:14
Spesso comunque l'oggetto che rappresenta la scelta dell'utente in termini di unità di misura viene tenuto come globale, in modo da evitare di doverlo continuamente passare in giro; in quest'ultimo caso però bisogna stare molto attenti a distinguere tra funzioni di parsing/output da/per utente e da/per formati human-readable (ma che comunque non devono essere influenzati dalle preferenze).

Scusa l'ignoranza, in termini terra terra?

Vuol dire dichiarare l'oggetto "unità di misura" prima del main?

Faccio un esempio di quello che invece pensavo di fare io.
Nel file preferenze.h definisco



class unitamisura
{
...//quanto serve a farlo funzionare
}

e in preferenze.cpp l'implementazione effettiva

creo il programma



#include <iostream>
#include <string>
#include <windows.h>
#include .....
#include <preferenze.h>

int main()
{
unitamisura umisura;
......
//da qualche parte ho definito la funzione "input" dell'oggetto "oggetto"
......
oggetto.input(umisura,/*altri eventuali parametri*/);
.......
}


Qualche link a documentazione che parli di queste problematiche? Da quanto cercato in giro non ho trovato niente, forse perchè in prima battuta ho ristretto la ricerca alle sole pagine in italiano...

Grazie per la disponibilità

ing82
14-04-2015, 11:44
Spesso comunque l'oggetto che rappresenta la scelta dell'utente in termini di unità di misura viene tenuto come globale, in modo da evitare di doverlo continuamente passare in giro; in quest'ultimo caso però bisogna stare molto attenti a distinguere tra funzioni di parsing/output da/per utente e da/per formati human-readable (ma che comunque non devono essere influenzati dalle preferenze).

Per la prima parte della risposta credo di essermi chiarito le idee, anche in merito a vantaggi e svantaggi legati alle dichiarazioni "globali", mi resta arabo la seconda parte


in quest'ultimo caso però bisogna stare molto attenti a distinguere tra funzioni di parsing/output da/per utente e da/per formati human-readable (ma che comunque non devono essere influenzati dalle preferenze).

Probabilmente fa parte dell'ABC del programmatore, ma programmando per necessità e non per professione...

Grazie di nuovo

Scara95
14-04-2015, 12:08
Premesso che tutte le operazioni di input/output sono influenzate da un oggetto globale,
Se voglio esportare il tutto in un formato standard dovrò stare attento a com'è impostato questo oggetto globale/dovrò evitare di utilizzarlo.

ing82
14-04-2015, 18:04
Premesso che tutte le operazioni di input/output sono influenzate da un oggetto globale,
Se voglio esportare il tutto in un formato standard dovrò stare attento a com'è impostato questo oggetto globale/dovrò evitare di utilizzarlo.

:confused: :confused: :confused: :confused: :confused: :confused: :confused: :confused: :confused: :confused: :confused: :confused: :confused: ...........

(l'ignoranza è una brutta bestia)

MItaly
14-04-2015, 23:10
Il discorso è molto semplice: se hai delle funzioni per leggere e scrivere in "formato utente" (senza possibilità di override) devi usarle solo per la GUI, e stare attento a non usarle per compiti apparentemente simili ma che non devono essere influenzati dalle preferenze, come ad esempio la scrittura/lettura da formati file testuali.

Mi spiego meglio con un esempio: nella libreria C esiste il concetto di "locale". Il "locale" ha come idea il contenere le impostazioni di formattazione di numeri, date, valuta, ... preferite per l'utente. In Italia, ad esempio, vogliamo i numeri con la virgola come separatore decimale, il punto (o l'apostrofo) come eventuale separatore delle migliaia, il simbolo € e due decimali per la valuta, le date in formato GG/MM/AAAA, l'ora in formato 24h, eccetera; in America invece si usa il punto come separatore decimale, la virgola per le migliaia, $ e due decimali per la valuta, le date in formato MM/GG/AAAA, l'ora in formato AM/PM.
Ora, le funzioni di input, di output e di parsing di default (scanf, printf, strtod, ...) sono sensibili al locale: se viene impostato il locale italiano, una printf("%g\n", 1234.5) stamperà "1234,5" (o 1.234,5, dipende da un po' di cose); alla stessa maniera, scanf("%g", &var) e strtod riconosceranno il formato italiano e non più quello di default (il "locale C").

Tutto questo andrebbe bene se le funzioni in questione fossero usate solo per l'interazione con l'utente; il problema è che in C queste sono le uniche funzioni fornite per la stampa e il parsing dei numeri (che, nel caso dei numeri in floating point, è un problema molto meno banale di quanto si creda), per cui molto più spesso vengono usate per la scrittura e la lettura di formati testuali ma pensati per essere letti da altri programmi (ad esempio CSV o similari), dove quello che si vuole è avere una rappresentazione testuale univoca dei dati, e non influenzata dalle impostazioni internazionali. Di conseguenza, a memoria d'uomo nessuno ha mai usato davvero il locale (specie il facet riguardante la formattazione dei numeri decimali), perché è praticamente certo che se lo si tocca si rompe qualcosa.

Di conseguenza quello che ti dicevo sopra: stai attento a separare bene le funzioni pensate per la formattazione destinata all'utente (che devono seguire le impostazioni personalizzate) e quelle per scrittura/parsing di dati testuali ma pensati per essere machine-readable (e che quindi non devono essere influenzati dalle impostazioni custom).

Loading