Newsgroup: it.comp.lang.c++
Titolo: Help switch!

Salve :)
Lurko questo NG da tempo e grazie a voi ho risolto molti
fastidiosissimi problemucci che mi si son parati davanti studiando il
c++.
C'e' pero' una robina che non riesco a risolvere. Ecco il codice:
-------------------------------------------------------------------------------------------------------------------
int scelta=0;
	cout << "                Selezionare l'operazione desiderata:\n";
	cout << "\n";
                cout << "\n";
	cout << "                1) Creazione file di dati.\n";
	cout << "\n";
	cout << "                2) Calcolo media. \n";
	cout << "\n";
                cout << "                3) Calcolo media pesata.\n";
	cout << "\n";
                cout << "                4) Calcolo regressione
lineare.\n";
	cout << "\n";
	cout << "                5) Calcolo regressione parabolica.\n";
	cout << "\n";
                cout << "                6) Istogramma.\n";
	cout << "\n";
	cout << "\n";
	cout << "\n";
                cout << "                7) Esci dal programma.\n";
	cout << "\n";
	cout << "\n";
                cout << "\n";
	cout << "Scrivi il numero corrispondente (1 - 7) all'operazione
desiderata e premi invio: ";
	cout << "\n";
	cout << "> ";
	if(!(cin>>scelta))
		{
		cin.clear();
                                cin.ignore();
		cout << "Errore: Inserire un numero da 1 a 7.\n";
		cout << "\n";
	                cout << "\n";
		cout << "Premere invio per continuare\n";
		cin.get();
		cin.get();
		menu();
		}
	switch(scelta)
	{
               case 1:
		clrscr();
	    scrittura_file_dati();
	case 2:
		clrscr();
		funzione_media();
	case 3:
		clrscr();
		funzione_media_pesata();
	case 4:
		clrscr();
		funzione_regressione_lineare();
	case 5:
		clrscr();
		funzione_regressione_parabolica();
	case 6:
		clrscr();
		istogramma();
	case 7:
		system("EXIT");
		return 0;
	default:
		cout << "Non esiste l'opzione numero " << scelta << "\n";
		scelta=0;
		cout << "\n";
	    cout << "\n";
		cout << "Premere invio per continuare\n";
		cin.get();
		cin.get();
		menu();
	}
	return 0;
}
------------------------------------------------------------------------------------------------------------------------------------
il menù funziona correttamente, TRANNE nel caso si scelga l'opzione 7
(uscita dal programma) dopo aver compiuto altre operazioni. In pratica
riesco ad uscire dal programma tramite il case 7 solo la prima volta.
Se scelgo prima qualche altro case e svolgo qualche altra operazione,
quando cerco di uscire dal programma andando al case 7 ottengo delle
cose strane (Il prog passa a qualche altra funzione, mi dice che "non
esiste l'opzione numero 1 ecc. ecc.)
Chi mi aiuta???? Devo consegnare il prog lunedi' per un esame e vorrei
togliere questo baco :)
Grazie in anticipo!
Valeria.
P.S: Ovviamente nel case 7, oltre a system("EXIT"), ho provato a
mettere anche return 0, break ecc.

 C'e' pero' una robina che non riesco a risolvere.
1. system("EXIT") è una roba che non ha nessun senso. Come te la sei 
inventata?
2. Sembra che tu non conosca il funzionamento di 'switch...case'.
I 'case' sono solo dei punti in cui l'esecuzione prosegue se sussiste la 
condizione giusta. Non identificano blocchi indipendenti. Dopo che 
l'esecuzione è passata a un certo 'case', verrà eseguito anche il codice 
corrispondente ai 'case' successivi, a meno che non si esca dal blocco 
'switch' mediante un 'break'.
Max

inventata?
La funzione system richiama un comando riconosciuto da windows ...in
questo caso exit chiude il prompt.
Ok non è standard, ma non è questo il punto. E' solo una delle tante
prove che ho fatto.
Il problema è che in alcun modo riesco ad uscire correttamente dal
programma tramite l'opzione "7" del menu' (tranne la prima volta), ed
è l'unica opzione che non funziona (tutti gli altri case filano lisci
come l'olio anche se ripetuti 100 volte).
Nemmeno inserendo un break ad ogni case la cosa cambia (d'altronde ogni
case rimanda ad una funzione, la quale, una volta terminata, rimanda
nuovamente al menu' in oggetto. Quindi ai "break" il prog non arriva
mai ...).
Cosa non va? Help help :)
Valeria.

 	    scrittura_file_dati();
Sostituisci le due righe sopra (quindi cancella o commenta anche 
"clrscr()") con
cout << "scrittura_file_dati()" << endl;
Fai lo stesso per ogni case e poi esegui il programma.
Kiuhnm

 Kiuhnm
Capisco cosa vuoi dirmi ...se non breakko il programma passa
automaticamente anche al case 2 :)
Il punto è che anche scrivendo cosi':
-----------------------------------------------------------
 case 1:
	     clrscr();
	     scrittura_file_dati();
	      break;
-----------------------------------------------------------
e via di seguito per tutti gli altri case ..... non funziona egualmente
:)
Credo perche' al break non ci arriva mai (salta ad una funzione che
poi, una volta completa, rimanda a questo menu' ).
Ancora non capisco :)
Dove sta l'errore? :)
Valeria.

 Dove sta l'errore? :)
Non si può vivere senza un debugger. Ogni IDE degno di rispetto ne è 
dotato. In Visual C++, per es., trovi il menù "Debug" tramite il quale 
puoi iniziare a debuggare il tuo programma.
Le cose da imparare sono almeno 5:
1) Il debugger ti permette di eseguire un programma una linea o una 
sezione di codice alla volta.
2) In ogni momento puoi controllare il valore di ogni variabile.
3) Per eseguire una linea di codice si usa il comando "Step Out" (o 
"step") (F10 in VC++).
4) Per entrare all'interno di una funzione (con "step" la eseguiresti in 
blocco) si usa il comando "Step Into" (o "trace") (F11 in VC++).
5) Si possono mettere break-point (cioè punti di pausa) lungo il codice 
(F9 in VC++) che indicano i punti esatti dove l'esecuzione verrà 
interrotta. In VC++ si preme F5 ogniqualvolta si vuole che il programma 
venga eseguito a velocità normale, ma che si fermi in corrispondenza di 
ogni breakpoint.
6) Non si può vivere senza e, se anche si può, è controproducente farlo.
Kiuhnm

 mettere anche return 0, break ecc.
L'istruzione system("EXIT") non ha senso.
Quello che fa e' lanciare un'istanza dell'interprete di comandi di 
sistema, sotto Windows 1/2/3/95/98/ME lancia 
COMMAND.COM
, sotto Windows 
NT/2000/XP/2003 lancia CMD.EXE. Poi passa un comando a questo processo, 
il processo dell'interprete di comandi esegue il comando, mentre il 
programma principale aspetta che sia finito, e quando il comando e' 
finito, l'interprete di comandi termina e il programma principale 
riprende l'esecuzione.
Nel tuo caso, 'system("EXIT")' lancia un interprete di comandi per 
dirgli, "termina", il che e' perfettamente inutile visto che 
terminerebbe subito dopo.
In ogni caso, il programma chiamante non puo' terminare, a meno che il 
comando sia "tskill" o "taskkill" (o "kill" sotto Unix).
Per terminare il tuo preogramma usa invece:
   exit(0);
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

Grazie Carlo!!!!
Forse ....FORSE funziona :))
Son contenta. Farò qualche altra prova ...tanto entro stasera devo
anche codare l'integrale sulla funzione di gauss ...hai voglia a
smanettare  :)
Valeria.

 esiste l'opzione numero 1 ecc. ecc.)
Credo di aver capito cosa hai fatto!
Fai una cosa. Scrivi un proggramma nuovo, fatto esattamente come hai 
fatto quello "vero", ma minimale.
Mettici un menu di tre opzioni, tipo:
1) stampa "ciao"
2) stampa "hallo"
3) esci
Ricorda: struttura il codice esattamente come hai fatto con il tuo 
programma "vero". Implementando ciascun comando con una funzione 
separata etc.
Posta tutto il codice così come lo compili (ovvero non copiarlo a mano 
ma usa il cut&paste). Tutto. Tutti i file (tranne gli include di 
sistema, ovviamente).
Per chi non ha capito cosa è successo ma ha un pochino di esperienza: 
rileggete i post di Valeria. Non solo quello originale da cui quoto ma 
anche gli'altri in cui dice che le funzioni che implementano i comandi 
"rimanndano" al menu e in cui dice che i break sembrano non servire. 
Considerino che non si era accorta della mancanza di break e che ha 
detto altrove che alcune funzioni deve ancora implementarle.
Per Valeria: il mio non è sadismo. Ma voglio che fai tu la fatica di 
preparare il codice "minimale" perchè in realtà ci sono molti modi 
simili ma leggermente diversi in cui puoi aver fatto quello che temo. E 
visto che il problema è tuo non è giusto che io/noi si faccia lo sforzo 
di scrivere 3, 4 o magari più versioni complete del suddetto codice 
minimale solo per spiegarti dove "potresti" aver sbagliato.
Quindi fai la tua parte. Posta lo "scheletro" che ti ho descritto. Di ci 
dovrebbe volere veramente poco per farlo. E ti risponderemo dove 
esattamente è il problema. O meglio ancora: inseriremo qualche
   cout << "**** " << __LINE__ << " @ " << __FILE__ << endl;
nei punti strategici in modo che eseguendo il codice tu ti accorga da 
sola di dove sta l'errore (sempre che l'aver fatto e poi eseguito il 
programmino minimale che ti ho suggerito non te lo abbia già rivelato).
E a proposito: il suggerimento di usare exit(0) sembra funzionare, ma 
... nasconde il problema invece di risolverlo. Il codice relativo al 
comando di uscita è corretto fin dal tuo primo post, salvo la 
system("EXIT") che è totalmente inutile.
Toglila. L'uscita che ti serve la ottieni con il solo return.

Avevo gia' fatto questa prova .....quindi ho il programmino minimale
bello pronto :)
Il fatto è che cosi' funziona tutto perfettamente!!!
Quindi o son io a non accorgermi di qualche cosetta diversa nel prog
principale ....oppure c'e' qualche robina che non capisco.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <iostream.h>
int menu();
void func1();
void func2();
void func3();
void func4();
void main()
{
	cout << "Blabla bla bla \n";
	cout << "bla bla bla \n";
	cout << "Premere invio per continuare\n";
	cin.get();
	menu();
}
int menu()
{
	int scelta=0;
	cout << "                Selezionare l'operazione desiderata:\n";
	cout << "\n";
    cout << "\n";
	cout << "                1) func1.\n";
	cout << "\n";
	cout << "                2) func2. \n";
	cout << "\n";
    cout << "                3) func3.\n";
	cout << "\n";
    cout << "                4) func4.\n";
	cout << "\n";
	cout << "\n";
    cout << "                5) Chiudi programma.\n";
	cout << "\n";
    cout << "\n";
	cout << "Scrivi il numero corrispondente (1 - 5) all'operazione
desiderata e premi invio: ";
	cout << "\n";
	cout << "> ";
	if(!(cin>>scelta))
		{
		cin.clear();
        cin.ignore();
		cout << "Errore: Inserire un numero da 1 a 5.\n";
		cout << "\n";
	    cout << "\n";
		cout << "Premere invio per continuare\n";
		cin.get();
		cin.get();
		menu();
		}
	switch(scelta)
	{
    case 1:
		func1();
		 break;
	case 2:
		func2();
		break;
	case 3:;
		func3();
		break;
	case 4:
		func4();
		break;
	case 5:
		return 0;
		break;
	default:
		cout << "Non esiste l'opzione numero " << scelta << "\n";
		scelta=0;
		cout << "\n";
	    cout << "\n";
		cout << "Premere invio per continuare\n";
		cin.get();
		cin.get();
		menu();
	}
	return 0;
}
void func1()
{
	cout << "Ciao! Sei dentro func1\n";
	cout << '\n';
	cout << "Premi invio per tornare al menu'\n";
	cout << "> ";
	cin.get();
	cin.get();
	menu();
}
void func2()
{
	cout << "Ciao! Sei dentro func2\n";
	cout << '\n';
	cout << "Premi invio per tornare al menu'\n";
	cout << "> ";
	cin.get();
	cin.get();
	menu();
}
void func3()
{
	cout << "Ciao! Sei dentro func3\n";
	cout << '\n';
	cout << "Premi invio per tornare al menu'\n";
	cout << "> ";
	cin.get();
	cin.get();
	menu();
}
void func4()
{
	cout << "Ciao! Sei dentro func4\n";
	cout << '\n';
	cout << "Premi invio per tornare al menu'\n";
	cout << "> ";
	cin.get();
	cin.get();
	menu();
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Quindi non devi richiamare il menu() da dentro il menu, ma usare un
ciclo for() o while().
Es.
<pseudocode>
bool terminate = false;
while(!terminate) {
  showMenu();
  int choice = getChoice();
  switch(choice) {
    case ...
      break;
    case ...
      break;
    case ...
      break;
    case END_MENU:
      terminate = true;
      break;
    }
  }
</pseudocode>
nelle varie funzioni richiamate non devi richiamare il menu, al massimo
puoi prevedere di tornare un valore booleano che puoi assegnare a
terminate (se vuoi che si possa uscire anche tramite quelle funzioni).
Spero sia chiaro :-)

 	cout << "> ";
Non è più semlice scrivere:
  cout <<	
	"                Selezionare l'operazione desiderata:\n"
	"\n"
	"\n"	
	"                1) func1.\n"
	"\n"
	"                2) func2. \n"
	"\n"
	"                3) func3.\n"
	"\n"
	"                4) func4.\n";
	"\n"
	"\n"
	"                5) Chiudi programma.\n";
	"\n"
	"\n"
	"Scrivi il numero corrispondente (1 - 5) all'operazione desiderata e 
premi invio: "
	"\n"
	"> "
	;
Io credo di si.
Facci sapere.

Grazie a tutti!
Faro' tutte le prove del caso e vi faro' sapere. Credo di aver capito
:)
P.s: Sapete per caso dove reperire online una buona guida all'I/O su
file? (ifstream, ofstream ecc.).
Non riesco infatti, sul mio testo, a capire la sintassi esatta per far
leggere un file di double disposti su piu' colonne. Fin ora ho risolto
creando dei "file di sistema" per ogni colonna .....ma non è molto
scientifico ...
Valeria.

Come non detto! Leggere dei double disposti su piu' colonne da un file
era piu' semplice di quel che pensavo.
Meglio cosi' :)