Newsgroup: it.comp.lang.c++
Titolo: Inserimento dati in una rubrica

Ciao ragazzi il programma che vi mostro di sotto gestisce una semplice
rubrica telefonica!Di questa rubrica mi funzionano tutte le procedure tranne
quella di inserimento!La cosa strana è che funziona fin quando vado ad
inserire nome e cognome, se tolgo i commenti e faccio in modo da inserire
anche i restanti campi la procedura non da errori in compilazione ma in
esecuzione!Potreste aiutarmi a capirne il motivo!
Ps : in realtà la procedura non sarebbe proprio così l'ho dovuta
rimaneggiare per cercare di comprendere l'errore quindi mi basta capire
l'errore in questa procedura!
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-----------
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fstream.h>
const int maxdim = 30;
typedef char parola[maxdim];
struct nominativo{
                char* id;
                char* nome;
                char* cognome;
                char* indirizzo;
                char* numtel;
                bool flag;
        };
nominativo* crea(int & dim, int & nelem, int & primovuoto);
bool inserisci(nominativo* R, const int dim, int & nelem, int & primovuoto);
int main(){
   int scelta;
   int dim, nelem, primovuoto;
   nominativo* R;
  do{
       cout << "\n************Menu************\n";
       cout << "\n1 - Crea Rubrica\n";
       cout << "\n2 - Inserisci nella rubrica\n";
       cout << "\n3 - Cancella dalla rubrica\n";
       cout << "\n4 - Stampa a video\n";
       cout << "\n5 - Stampa su file\n";
       cout << "\n6 - Fine\n";
       cout << "\n****************************\n";
       cout << "Scegli dal Menu : ";
       cin >> scelta;
       switch(scelta){
         case 1 : crea(dim, nelem, primovuoto);break;
         case 2 : inserisci(R, dim, nelem, primovuoto) ;break;
         //case 3 : cancella();break;
         case 4 : stampa(R, nelem, primovuoto) ;break;
         case 5 : stampasufile(R, nelem, primovuoto);break;
         case 6 : cout << "\n\aHai scelto di terminare il
programma!!!\n";break;
         default : cout << "\nScelta inesistente\n";
      };
    }while(scelta >= 1 && scelta <= 6);
   system("PAUSE");
   return 0;
}
nominativo* crea(int & dim, int & nelem, int & primovuoto){
   nominativo* R;
   cout << "Quanti nominativi avrai al massimoin rubrica?";
   cin >> dim;
   R = new nominativo [dim];
   nelem = 0;
   primovuoto = 0;
   for(int i = 0; i < dim; i++){
     R[i].id = "";
     R[i].nome = "";
     R[i].cognome = "";
     R[i].indirizzo = "";
     R[i].numtel = "";
     R[i].flag = false;
   }
   return R;
}
bool inserisci(nominativo* R, const int dim, int & nelem, int & primovuoto){
  char temp1[50],temp2[50],temp3[50],temp4[50];
  cin.ignore();
    for(int i = primovuoto; i < dim; i++){
      cout << "Nome : ";
      cin.getline(temp1, 50);
      cout << "Cognome : ";
      cin.getline(temp2, 50);
      cout << "Indirizzo : ";
      cin.getline(temp3, 50);
      cout << "NumTel : ";
      cin.getline(temp4, 50);
      R[i].nome = new char[strlen(temp1) + 1];
      strcpy(R[i].nome, temp1);
      R[i].cognome = new char[strlen(temp1) + 1];
      strcpy(R[i].cognome, temp2);
     /* R[i].indirizzo = new char[strlen(temp1) + 1];
      strcpy(R[i].indirizzo, temp3);*/
     /* R[i].numtel = new char[strlen(temp1) + 1];
      strcpy(R[i].numtel, temp4);*/
      }
}
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-----------

       R[i].nome = new char[strlen(temp1) + 1];
ovvero sfruttando la strlen di temp1 in cui e' stato memorizzato il nome.
Se il tuo nome e' piu' corto degli altri campi si verifica il patatrac!
Devi quindi modificare le restanti linee con gli opportuni tempx:
       R[i].cognome = new char[strlen(temp2) + 1];
       strcpy(R[i].cognome, temp2);
       R[i].indirizzo = new char[strlen(temp3) + 1];
       strcpy(R[i].indirizzo, temp3);
       R[i].numtel = new char[strlen(temp4) + 1];
       strcpy(R[i].numtel, temp4);
Spero di averci colto!
Maurus

 Ho fatto cmq le modifiche che dicevi e la situazione è rimasta la stessa!
No quello c'entrava pure.
Sicuramente era uno dei problemi.
Poi ce ne sono altri, guarda dove dichiari nel main:
   int scelta;
   int dim, nelem, primovuoto;
   nominativo* R;
Nota bene che sono tutti valori non inizializzati  e sono locali a una
funzione, per cui non vengono neppure inizializzati a 0, come quando si
tratta di valori globali non inizializzati.
Per cui per il momento stanno assumendo un valore intero casuale...
Ora questi stessi valori casualmente inizializzati, tu li passi come
parametri alle tue funzioni:
switch(scelta){
         case 1 : crea(dim, nelem, primovuoto);break;
         case 2 : inserisci(R, dim, nelem, primovuoto) ;break;
         //case 3 : cancella();break;
         case 4 : stampa(R, nelem, primovuoto) ;break;
         case 5 : stampasufile(R, nelem, primovuoto);break;
....
L'unica variabile che ha assunto un valore definito e' la var scelta che ha
preso il valore grazie alla cin, tutti gli altri sono rimasti casuali.
Per quanto riguarda la funzione crea non c'e' problema perche' sono
parametri passati per riferimento che tu poi inizializzi nella funzione
stessa, ma guai grossi avvengono nella funzione inserisci, dove tu dai per
scontato che primovuoto e dim abbiano valori determinati.
Fra parentesi nella stessa funzione inserisci tu non utilizzi mai il
parametro nelem.
Insomma hai da risolvere un po' di problemi relativi al trattamento di
queste variabili prima della chiamata a inserisci.
Ed inoltre non scordarti dell'altro problema che ti ho detto nel post
precedente che e' anche subdolo se non lo correggi.
Maurus


In sostanza e per concludere, dovresti obbligare l'utente a selezionare
prima la scelta crea e poi la scelta inserisci.
Nulla vieta all'utente di scegliere inserisci prima di aver creato la
rubrica, per cui si avranno tutti i problemi di variabili non inizializzate
che ti ho gia' detto, visto che tu queste variabili le inizializzi nella
funzione crea.
Tipicamente in C++ queste inizializzazioni si fanno nel costruttore della
classe, qua tu invece stai dando per scontato che l'utente sia intelligente
e crei la rubrica prima di fare qualsiasi operazione.
La funzione inserisci dovrebbe ritornare un valore booleano senno' non ti
compila.
Un'ultima cosa: il while dovrebbe fare il controllo fino alla scelta 5,
altrimenti non esci mai dal tuo programma.
Maurus

 Sono tuttavia convinto che il prblema stia nelle strlen();
Visto che sei un SanTommaso peggio di me mi obblighi a farti vedere cosa ho
io sia nel codice sia nell'output:-)
Ti invito quindi a copiare il mio codice a compilarlo linkarlo ed eseguirlo
per vedere se avrai un output come il mio o se continui ad avere problemi.
Io uso il VisualC++ 6 senza service pack, ma posso provarlo anche col
DevC++.
**** codice ****
include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fstream.h>
const int maxdim = 30;
typedef char parola[maxdim];
struct nominativo
{
   char* id;
 char* nome;
 char* cognome;
 char* indirizzo;
 char* numtel;
 bool flag;
};
nominativo* crea(int & dim, int & nelem, int & primovuoto);
bool inserisci(nominativo* R, const int dim, int & nelem, int & primovuoto);
int main()
{
 int scelta;
 int dim, nelem, primovuoto;
 nominativo* R;
 do
 {
  cout << "\n************Menu************\n";
  cout << "\n1 - Crea Rubrica\n";
  cout << "\n2 - Inserisci nella rubrica\n";
  cout << "\n3 - Cancella dalla rubrica\n";
  cout << "\n4 - Stampa a video\n";
  cout << "\n5 - Stampa su file\n";
  cout << "\n6 - Fine\n";
  cout << "\n****************************\n";
  cout << "Scegli dal Menu : ";
  cin >> scelta;
  switch(scelta)
  {
   case 1 : crea(dim, nelem, primovuoto);break;
   case 2 : inserisci(R, dim, nelem, primovuoto) ;break;
   // case 3 : cancella();break;
   // case 4 : stampa(R, nelem, primovuoto) ;break;
   // case 5 : stampasufile(R, nelem, primovuoto);break;
   case 6 : cout << "\n\aHai scelto di terminare il programma!!!\n";break;
   default : cout << "\nScelta inesistente\n";
      };
   }
   while(scelta >= 1 && scelta <= 5);
 system("PAUSE");
 return 0;
}
nominativo* crea(int & dim, int & nelem, int & primovuoto)
{
 nominativo* R;
 cout << "Quanti nominativi avrai al massimoin rubrica?";
 cin >> dim;
 R = new nominativo [dim];
 nelem = 0;
 primovuoto = 0;
 for(int i = 0; i < dim; i++)
 {
  R[i].id = "";
  R[i].nome = "";
  R[i].cognome = "";
  R[i].indirizzo = "";
  R[i].numtel = "";
  R[i].flag = false;
 }
 return R;
}
bool inserisci(nominativo* R, const int dim, int & nelem, int & primovuoto)
{
 char temp1[50],temp2[50],temp3[50],temp4[50];
 cin.ignore();
   for(int i = primovuoto; i < dim; i++)
 {
  cout << "Nome : ";
  cin.getline(temp1, 50);
  cout << "Cognome : ";
  cin.getline(temp2, 50);
  cout << "Indirizzo : ";
  cin.getline(temp3, 50);
  cout << "NumTel : ";
  cin.getline(temp4, 50);
  R[i].nome = new char[strlen(temp1) + 1];
  strcpy(R[i].nome, temp1);
  R[i].cognome = new char[strlen(temp2) + 1];
  strcpy(R[i].cognome, temp2);
  R[i].indirizzo = new char[strlen(temp3) + 1];
  strcpy(R[i].indirizzo, temp3);
  R[i].numtel = new char[strlen(temp4) + 1];
  strcpy(R[i].numtel, temp4);
 }
   return 0;
}
**** inizio output ****
Nome : ciccio
Cognome : cicci
Indirizzo : via da qua
NumTel : 1111
Nome : pippo
Cognome : baudo
Indirizzo : via teulada
NumTel : xxxxx
************Menu************
1 - Crea Rubrica
2 - Inserisci nella rubrica
3 - Cancella dalla rubrica
4 - Stampa a video
5 - Stampa su file
6 - Fine
****************************
Scegli dal Menu :
**** fine output ****
Ovviamente ho scelto prima l'opzione Crea e poi l'opzione Inserisci.
Fammi sapere, nel caso lo provo anche col DevC++.
Maurus

Io ho dev c++ 4.9.7.1 e non mi funziona cmq! puo dipendere dal compilatore?

ps ho provato anch'io col visual c++ 6.0 non mi funziona comunque!Ti dico
cosa faccio :
1) compilo
2)eseguo
3)Dal menů scelgo crea
4)scrivo : 2
5)dal menů scelgo inserisci
Quando inserisco l'ultimo dato mi esce il messaggio di windows che c'č stato
un errore se voglio posso inviare inviare un messaggio etc etc..

    default : cout << "\nScelta inesistente\n";
R non viene inizializzato. 
Max


Grande Max!
Ero convinto che la funzione crea lo inizializzasse ma in effetti questa
ritorna R e non gli viene passato come parametro per riferimento come
credevo che fosse.
Il ritorno di R nella funzione crea non viene memorizzato nella R del main
per cui inserisci provoca macelli!
Il bello e' che nelle mie prove col VisualC++ 6 in versione debug
funzionava, forse perche' col debug venivano sovrascritte zone di memoria
non vitali.
Per cui Antonio, grazie a Max, facendo questa modifica all'ultimo codice su
cui si discuteva, dovrebbero essere finiti i problemi:
// nel case del main
   case 1 : R = crea(dim, nelem, primovuoto);break;
// avevamo tralasciato il ritorno di crea !
Maurus

 ha scritto nel messaggio
news:av2q8p$bnq7l$1...@ID-125555.news.dfncis.de...
