Newsgroup: it.comp.lang.c++
Titolo: Un consiglio.

Salve a tutto il ng. Il mio non è un problema ma piuttosto la richiesta di
una vostra opinione.
Ho scritto il seguente codice per risolvere questo problema:
"Definire una mappa per la quale la chiave sia il cognome di una famiglia e
il valore sia un vettore dei nome dei figli. Fare interrogazioni e
inserimenti su questa."
Ora il codice viene compilato senza errori ne warning e fa perfettamente
tutto ciò che è richiesto però ho un dubbio: poteva essere fatto in qualche
modo migliore? Mi riferisco supratutto alla parte che riguarda l'allocazione
dinamica del vector per ogni nuova famiglia inserita.
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <conio.h>
#include <stdlib.h>
using namespace std;
typedef vector<string> soon;
typedef map<string, soon *>::value_type valType;
void modify(map<string, soon *> &);
int main(){
    map<string, soon *> family;
    soon *figli;
    char c;
    do{
       clrscr();
       cout<<"Inserire il cognome della famiglia: ";
       string cognome;
       cin>>cognome;
       figli=new soon;
       do{
          clrscr();
          cout<<"\nInserire il nome del figlio: ";
          string vFigli;
          cin>>vFigli;
/*Qualcuno mi sa dire come faccio ad inserire n stringhe ma controllando il
tutto con il while? Mi spiego meglio tipo: while(cin>>qualcosa!="\n")
qualcosa del genere che mi legga tutte le stringhe immesse finchè non ho
premuto invio e me le memorizzi da qualche parte separatamente, una ad una.
Questo che ho scritto è sbagliato e cmq non vorrei usare ne istream_iterator
ne getline. E' possibile?*/
           figli->push_back(vFigli);
          cout<<"\nUn altro figlio da aggiungere? ";
          cin>>c;
          if(c=='n')
                    break;
       }while(c=='y');
       family.insert(valType(cognome, figli));
       cout<<"Continuare? ";
       cin>>c;
       if(c=='n')
             break;
    }while(c=='y');
    do{
        clrscr();
        cout<<"Vuoi modificare qualcosa? ";
        cin>>c;
        if(c=='y')
           modify(family);
    }while(c=='y');
    map<string, soon *>::iterator iter;
    soon::iterator svec;
    clrscr();
    for(iter=family.begin(); iter!=family.end(); ++iter){
        cout<<"Famiglia: "<<(*iter).first<<"\n"<<"Figli: ";
        for(svec=(*iter).second->begin(); svec!=(*iter).second->end();
++svec)
            cout<<*svec<<' ';
        cout<<endl;
    }
}
void modify(map<string, soon *> &ref){
     string word;
     char c;
     clrscr();
     cout<<"Di quale famiglia vuoi modificare i dati? ";
     cin>>word;
    map<string, soon*>::iterator it=ref.find(word);
    if(it==ref.end()){
       cerr<<"ATTENZIONE: non esiste nessuna famiglia "<<word
           <<" nell'archivio\n";
       exit(2);
    }
    clrscr();
    soon::iterator iter=(*it).second->begin();
    cout<<(*it).first<<'\n';
    for(;iter!=(*it).second->end(); ++iter)
        cout<<*iter<<' ';
    cout<<"\n\n\n";
    do{
       cout<<"Inserire nuovo figlio: ";
       cin>>word;
       (*it).second->push_back(word);
       cout<<"\nNuovo figlio? ";
       cin>>c;
       if(c=='n')
          break;
       clrscr();
    }while(c=='y');
}
Il mio è solo un atto di pignoleria quindi ringrazio il doppio delle volte
chi deciderà di perdere un po' di tempo qui.
---Seek and Destroy---

 dinamica del vector per ogni nuova famiglia inserita.
Scusa, non ho letto bene il tuo codice e quindi potrei non aver compreso
il problema. Se intendi dire che usi l'allocazione dinamica (new) per
creare nuovi vector allora forse potevi, come migliore alternativa,
utilizzare un contenitore per questi vector adeguato alle operazioni
necessarie (un vector di vector, una list di vector e cosě via).
EMG

 una vostra opinione.
Mi vengono in mente due soluzioni, ma non so se è quello che vuoi.
Per prima cosa, a scanso di equivoci, ti ricordo che istream legge
le stringhe usando come separatore gli spazi (gli spazi iniziali vengono
ignorati). Inoltre il carattere '\n' è considerato uno spazio.
Ti faccio subito un esempio:
#include <iostream>
#include <string>
using namespace std;
int main()
{
  string a, b;
  cin >> a;
  cin >> b;
}
Per immettere le due stringhe puoi scrivere (ad esempio)
hello [INVIO]
word [INVIO]
oppure
hello [SPAZIO] word [INVIO]
Nota:
[INVIO] serve per terminare l'input  in quanto il DOS e WINDOW usano la bufferizazione di
riga -rifacendosi ad UNIX-
Volendo puoi implementare un istream che non presenta questo problema e per cui puoi fare
hello [SPAZIO] word [SPAZIO]
Ad esempio puoi usare la funzione di input definita in conio.h (se usi il Borland) int getch()
che non attende la pressione di [INVIO]
Spero che questa digressione non sia stata inutile.
Ed ora i miei due suggerimenti:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
ostream& operator<<(ostream& out, const vector<string>& v)
{
  out << "{";
  copy(v.begin(), v.end(), ostream_iterator<string>(out,", "));
  return out << "\b\b}";
}
int main()
{
  {
    // METODO PIU' SEMPLICE
    // COME SEPARATORE SI PUO' USARE [SPAZIO] OPPURE [INVIO]
    // AD ESEMPIO  Luca  Arturo  Gianluca  end
    const string end("end");      // stringa da immettere per terminare l'input
    vector<string> input;
    string str;
    while(cin >> str && str != end) input.push_back(str);
    cout << "input: " << input << '\n';
  }
  {
    // IN QUESTO CASO COME SEPARATORE SI PUO' USARE SOLO [SPAZIO]
    // [INVIO] TERMINA L'INPUT
    string line;
    getline(cin, line);                  // legge una linea di testo in line
    istringstream in(line);            // stringstream sostituisce la strstream
    string str;
    vector<string> input;
    while(in >> str) input.push_back(str);
    cout << "input: " << input << '\n';
  }
}
Spero di esserti stato di aiuto.
Se cerchi una soluzione migliore ti conviene attendere la risposta degli esperti
di questo newsgrop (alcuni credo siano in ferie in quanto non stanno postando)
Ciao  Manlio Perillo

 wrote in message 8mke4l$an5$1...@nslave2.tin.it...
[...]
Forse ho trovato qualcosa che potrebbe essere più comodo:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T> inline
ostream& operator<<(ostream& out, const vector<T>& v)
{
  if(v.size() == 0) return out << "{}";
  out << "{";
  copy(v.begin(), v.end(), ostream_iterator<T>(out, ", "));
  return out << "\b\b}";
}
int main()
{
  vector<string> input;
  string str;
  while(getline(cin, str) && str.length()) input.push_back(str);
  cout << "input: " << input << '\n';
}
In questo modo l'input è molto più versatile perchè si possono immetere nomi
separati da spazi (ad esempio "Enrico Maria").
Esempio di input:
nome_1 [INVIO]
    .
    .
    .
nome_n [INVIO]
[INVIO]                       (per immettere la stringa nulla e terminare l'input)
Il codice usa getline che tu volevi evitare, ma non vedo in quale altro modo
si possa procedere.
Con il DJGPP funziona benissimo, tuttavia con il BCC5.5 c'è un problema:
non so se è un BUG della libreria ma quando si immette una stringa nulla
(premendo solo invio), la stringa non risulta nulla, ma con str.length() == 1 e con
str[0] == '\0').
Per rimediare ho scritto del codice che usa la normale getline:
  // ...
  const size_t LIMITE = 80 * 2;
  // tanto dal promt del DOS non si possono immettere piu' di tanti caratteri
  vector<string> input;
  char str[LIMITE];
  while(cin.getline(str, LIMITE) && strlen(str))
  {
    cout << "nome immesso: " << str << '\n';
    input.push_back(str);
  }
Ma ancora una volta con il BCC5.5 (forse per un BUG) il programma si comporta in modo strano.
Prova a farlo girare...
Con il DJGPP ed il vecchio Borland C++ 5.02 funziona benissimo
Ciao  Manlio Perillo

 str[0] == '\0').
Io uso il DJGPP e quindi bene però il fatto che premendo solo invio si
ottiene una lunghezza di 1 e str[0]='\0' è normale visto che una stringa
termina sempre con questo carattere.Quindi anche se non immetti niente il
carattere di fine stringa dovrà esserci comunque perchè sarà una stringa
vuota. Forse la funzione lenght() in DJGPP è implementata in modo che ignori
questo carattere.
Cmq grazie del tuo interessamento e dei tuoi consigli.
---Seek and Destroy---


Non vorrei sbagliare, ma stai confondendo le std::string con le C-style string.
Un std::string nulla ha lunghezza zero.
Inoltre la std::string non usa '\0' per terminare una stringa.
Manlio Perillo

 wrote in message
8moq4m$54n$1...@nslave1.tin.it...

Si, forse hai ragione tu perchè ultimamente ho altre cose per la testa però
la std::string internamente è implementata come una stringa C-style. Mi
spiego meglio: il membro privato che contiene la stringa vera e propria è
dichiarato come char *; infatti poi std::string.c_str() restituisce la
stringa stile C che è memorizzata dal membro privato appena detto. Dunque
questa è una stringa stile C che termina con uno '\0' e credo sia dimostrato
anche dal fatto che il tuo compilatore ti da  str[0]=='\0'. Ripeto, come ho
detto prima, secondo me dipende anche da come sono poi implementati i vari
metodi tra cui appunto lenght().
La cosa giusta secondo me è che lenght() debba restituire zero in caso di
stringa nulla perchè se no davvero dobbiamo ancora tenere a mente quel
fastidiosissimo carattere di fine stringa e i vantaggi delle classi
contenitori astratti vanno a farsi friggere. La classe string è stata
implementata proprio per eliminare la gestione a basso livello delle
stringhe, quindi array di char, il terminatore '\0', e cose del genere -per
lo stesso motivo sono stati creati pure i vari vector, list ecc.- ma
internamente sono sempre "fatti" utilizzando il C e sappiamo bene cosa
significhi. Dunque è giusto che la lenght() restituisca zero e ci nasconda
poi i dettagli della memorizzazione.
Questo è ciò che penso io e se hai la documentazione corretta ti prego di
farmela pervenire perchè non vorrei sbagliare per sempre credendo invece di
dire bene.
Scusami per aver detto cose che sicuramente già sai e che forse ho
interpretato anche male.
Ps: mi puoi descrivere (tecnicamente) la differenza tra la lenght() e la
size()? Grazie.
Ciao.
---Seek and Destroy---

 Ciao.
Sono semplicemente la stessa cosa!
Ciao  Manlio Perillo

 size()?
A me sembra siano sinonimi. Sbaglio?
EMG