Newsgroup: it.comp.lang.c++
Titolo: Ricerca su campi di una classe

Salve a tutti. Sto sviluppando un programma che utilizza classi diverse, 
tutte provviste di campi di tipo char[], ma diverse classi hanno campi 
con nome differente. Ad esempio:
class A {
public:
  char andrea[10];
};
class B {
public:
  char enrico[10];
};
Mi chiedevo se sia possibile fare un algoritmo di ricerca che possa 
essere utilizzato su entrambi i campi "andrea" e "enrico". La funzione 
dovrebbe prendere come argomento la lista di oggetti (e per i diversi 
oggetti userei i template), ma non so proprio come fare a gestire i 
campi. Grazie per l'aiuto e la disponibilità.

 campi. Grazie per l'aiuto e la disponibilità.
così a naso direi che potresti scrivere una classe base da cui derivi
andrea ed enrico e passare questo tipo (base) alla funzione che esegue
l'algoritmo di ricerca
-- 
Salvatore

 essere utilizzato su entrambi i campi "andrea" e "enrico". 
non puoi farla al modo che forse vorresti (tipo passare le 
stringhe "enrico" o "andrea" come parametri a qualsivoglia 
funzione, anche template).
Puoi solo metterci una pezza scrivendo macro parametrizzate 
che il preprocessore veda prima del compilatore.
tipo
#define MacroRicercatiporitorno, classe, campo) tiporitorno\
Ricerca (classe Istanza) {\
tiporitorno Val;
for (int J = 0; J < 10; J++)\
	if (campo [J] == Boh)	
		{ Dosomething (Val); return Val; }
return (tiporitorno)0;
};
è solo un esempio eh
quella macro ovviamente non è una funzione, è un generatore 
di funzioni parametrizzato (molto error prone, affidando a 
te la coerenza di tutti i tipi e nomi e producendo messaggi 
di errore indecifrabili, in punti del codice inenarrabili, 
se non lo fai perfettamente).
Se c'è un modo di farlo coi template non lo so e non credo, 
mancando introspezione nativa nel linguaggio. Non mi risulta 
si possa generare, a partire da una stringa definita anche a 
compile-time ma pur sempre un literal, un nome di funzione 
che sia chiamabile, anche coi template.
Naturalmente se qualcuno mi dimostra il contrario è un mito, 
dato che è un idea molto carina.
ciao
soviet


essere utilizzato su entrambi i campi "andrea" e "enrico"
Specifica meglio quello che vuoi fare. In particolare, se ti è
possibile, specifica la tua esigenza di base, piuttosto che la
soluzione che hai escogitato. E' possibile che il tuo problema abbia
soluzioni diverse da quella a cui hai pensato, persino più semplici.

 soluzioni diverse da quella a cui hai pensato, persino più semplici.
Ho due liste di oggetti A e B.
list<A> ListaA;
list<B> ListaB;
A e B sono entrambi costituiti da diversi campi di tipo char[].
class A {
public:
  char campo01 [10];
  char campo02 [11];
};
class B {
public:
  char campo03 [12];
  char campo04 [13];
};
Io devo poter identificare elementi della lista di A e elementi della
lista di B in base a una stringa di caratteri immessa dall'utente. Mi
piacerebbe poter utilizzare lo stesso algoritmo per tutti i campi sia
degli oggetti di tipo A che di tipo B.
list<X>::iterator Ricerca (list<X>& Lista, const char StringaUtente[],
const char Campo[])   <<< E' qui il problema!!
Ovviamente quando vado a cercare so su che campo andarlo a fare.
Grazie a chi ha già risposto, grazie a chi vuole farlo, mi siete
enormemente d'aiuto.
Giano89

lista di B in base a una stringa di caratteri immessa dall'utente.
std::map

 std::map
Non riesco a capire come poter applicare le mappe. Le mie liste sono già
provviste di campi di tipo ID (univoci); addirittura all'interno delle
due classi i campi ID hanno lo stesso nome. Il problema è la ricerca
sugli altri campi usando lo stesso algoritmo.

Non riesco a capire come poter applicare le mappe.
Mi spiace ma delle due l'una: sei tu che non riesci a spiegare bene
che cosa vuoi fare; sono io che non riesco a comprendere bene che cosa
vuoi fare. 
Dal mio punto di vista, usare una std::map è proprio il modo per
implementare un requisito del tipo: "devo poter identificare elementi
della lista in base a una stringa di caratteri immessa dall'utente".
Sempre che per "identificare" tu intenda ottenere un particolare
oggetto in base a una stringa immessa dall'utente.

 oggetto in base a una stringa immessa dall'utente.
Dovrei quindi creare una mappa che ha per chiave il campo che devo
identificare? La mappa mi facilita la ricerca per chiavi, ma qui ho piů
di una chiave.

 const char Campo[])   <<< E' qui il problema!!
Ho parzialmente risolto il problema modificando le classi. Poichč i
campi sono tutti dello stesso tipo, ho aggiunto un puntatore a carattere
che di volta in volta indirizzo al campo sul quale mi interessa
effettuare la ricerca.
Rimangono comunque da fare due funzioni differenziate, senza possibilitą
di uso dei template, per le due classi.
Che ne pensate?
-- 
~~~~~ GIANO ~~~~~
E-mail:  
alex89...@gmail.com
Website: 
http://gianopage.altervista.org/
Skype:   alex89.ficus
Twitter: 
http://twitter.com/giano89
"Per una persona ottimista, il bicchiere e' pieno a meta'. Per una
persona pessimista, e' vuoto a meta'. Per l'ingegnere, e' due volte piu'
grande del necessario."
-----PGP KEY FINGERPRINT-----
7B19 3021 2218 5AE5 F90D  895F 64E3 5598 5920 9728

 Che ne pensate?
Io ti confesso che continuo a vedere qualcosa che non funziona. Se tu 
descrivessi meglio il *problema* che tu stai descrivendo, potremmo 
esserti più di aiuto. Tu invece continui a descrivere la soluzione che 
hai adottato.
Stai scrivendo qualcosa che vorrebbe assomigliare ad un piccolo 
database in memoria?
I campi char[] hanno nomi diversi per un buon motivo? Quale è il senso 
di tutto questo?
In primo luogo se fai frequentemente ricerche con una chiave, considera 
di usare mappe invece che liste, come Andrea ti ha già suggerito (O(log 
n) è meglio di O(n)).
In secondo luogo, perchè non usi find_if? Ti fai un funtore che bel 
bello controlla la tua chiave e usi quello. IMHO è una gran comodità.
-- 
I have never designed a language for its own sake.
Niklaus Wirth

 bello controlla la tua chiave e usi quello. IMHO è una gran comodità. 
Da quel che ho capito sulle mappe, posso stabilire una sola chiave per
record. Qui, non sapendo quale campo funge da chiave, non ho idea di
come applicare le mappe.
Grazie a tutti come sempre.


 nome e per il numero di campi, ma non per il tipo (che è sempre char[]).
No. Questo è un sottoproblema che hai avendo scelto una certa strada per
risolvere il tuo problema originario. 
Io posso dirti che la soluzione che presenti (per i vari problemi che mi
vengono in mente) non è molto buona.
Di fatto sei in O(n) per le ricerche (tra l'altro senza apparentemente
alcun buon motivo). Non solo: fai i confronti su stringhe. Di fatto sei
potenzialmente in O(m*n) dove m è la lunghezza massima della stringa
(anche se, in effetti, il confronto potrebbe durare meno se le cose
"vanno bene").
Mancano inoltre informazioni sulla frequenza delle ricerche rispetto ad
inserimenti o modifiche (e nel caso, quali modifiche sono ammesse).
Mancano informazioni sulla mole dei dati. Un conto è fregarsene della
complessità con 100 record, un conto è farlo con 1000000.
-- 
-riko

 nome e per il numero di campi, ma non per il tipo (che è sempre char[]).
*Soluzione*: dai ai tuoi database una rappresentazione uniforme, per
esempio rendendo esplicita la struttura dei tuoi database, ad es:
class Database {
  std::map<std::string, int> campi; // nome campo, indice del campo
nel record
  std::vector<std::vector<std::string> > record; // un vector per
record
};
In questo modo puoi manipolare comodamente sia i nomi dei campi che il
loro valore all'interno di specifici record.
Ciao,
Nicola

 complessità con 100 record, un conto è farlo con 1000000.
So che è un algoritmo pessimo, ma è anche vero che le ricerche sono
poche, ed è per questo che ho dato la precedenza agli inserimenti, anche
perchè lo scopo principale del programma è percorrere tutto il database
ed elaborarlo tutto. La ricerca è un'operazione saltuaria ma che non
posso non metterci.
Per quanto riguarda i database principali si presume non crescano molto,
tant'è che il buffer che uso per caricare i database da file è limitato
a 200 righe. Per i database secondari la lunghezza può essere anche
maggiore, ma sono ordinati e uso solo i primi elementi della lista.
Grazie anche a Nicola per la soluzione: ora provo a vedere come si
comporta così, per gli aggiornamenti c'è sempre tempo!


 posso non metterci.
Prova a guardare boost::multi-index, usa i template in modo avanzato 
proprio per permettere la ricerca su piu` campi e dota i campi stessi di 
indice, il link ad un semplice esempio:
http://www.boost.org/doc/libs/1_36_0/libs/multi_index/example/basic.cpp
L'unica cosa leggermente sporca e` che per "taggare" i campi su cui 
effettuare la ricerca/scorrere gli elementi deve creare delle struct 
vuote per ogni campo indicizzato che vengono usate come parametro del 
template.
Il link alla home:
http://www.boost.org/doc/libs/1_36_0/libs/multi_index/doc/index.html
Bye,
  Gabry