[c++] Fermare una funzione ricorsiva

valentino861
Devo far andare una funzione finchè non premo un determinato tasto ma non so come. Pensavo di usare GOTO e poi di far leggere da tastiera la pressione di quel determinato tasto e se non ci fosse entro 3 secondi di continuare con la ricorsione, o una cosa del genere. Che ne dite?

Risposte
apatriarca
Ma devi farlo con la ricorsione?! Ogni volta che fai una chiamata ricorsiva aggiungi dati nello stack e quindi in questo modo rischi di mandare in crash la tua applicazione. È molto più sensato fare questo genere di cose con un ciclo infinito in cui ad ogni iterazione viene verificata la condizione e usare break per uscire dal ciclo alla pressione del tasto.

Perché vuoi usare un goto per uscire? È sufficiente non richiamare la funzione ricorsiva alla fine della funzione in cui viene premuto il tasto per terminare la ricorsione.

valentino861
no no goto mi era venuto in mente cosi.
Ok allora uso un ciclo for ma come faccio a fargli verificare e se passa un tot tempo a fargli eseguire automaticamente un'azione?

Ti spiego il programma dovrebbe funzionare per un tempo non definito e la durata della funzione è di circa 3 minuti. Quindi vorrei che ogni 3 minuti mi venisse data la possibilità di bloccare il programma altrimenti lui continua da solo ed esegue nuovamente la funzione

apatriarca
Che API usi per il tempo e per la lettura del tasto? La funzione sarebbe qualcosa come il seguente (è una specie di pseudocodice):

int funzione()
{
    int64 start = get_time();
    
    for (;;) {
        int64 now = get_time();
        
        if (now - start > MAX_INTERVAL) return TIME_ELAPSED;
        else if (button_pressed(key)) return BUTTON_PRESSED;
    }
]

valentino861
allora per prendere il tempo uso la libreria time.h e poi mi sono fatto io una funzione per creare degli intervalli di tempo

void wait(double seconds){
	clock_t endwait;
	endwait=clock()+seconds*CLOCKS_PER_SEC;
	while (clock()<endwait);
}



Mi spieghi il codice che hai scritto?

apatriarca
Se usi time.h allora la funzione sarebbe...

/*
 * Restituisce TEMPO_SCADUTO se sono passati 3 minuti, TASTO_PREMUTO se è stato premuto il tasto
 */
int funzione()
{
    clock_t inizio = clock(); // memorizza quando la funzione è stata chiamata

    for (;;) { // ciclo infinito...

        clock_t adesso = clock(); // memorizza il tempo attuale

        // se il tempo passato è maggiore di 3 minuti allora esci, altrimenti verifica che sia stato premuto il tasto
        if ((adesso - inizio) >= 180*CLOCKS_PER_SEC) return TEMPO_SCADUTO;
        else if (button_pressed(key)) return TASTO_PREMUTO;
    }
}

valentino861
aspetta è leggermente diverso. Voglio che il programmi aspetti tipo 10 secondi, se non viene premuto nessun tasto allora fa un altro giro sennò si blocca. Quindi se io non tocco la tastiera lui deve ripartire dopo un certo tempo.

apatriarca
L'unica differenza tra la mia funzione e il tuo wait è che ad ogni ciclo verifica anche se viene premuto un tasto. Probabilmente non riesco a capire che cosa vuoi fare esattamente ma a me sembra adatta.

valentino861
Scusa ma forse sono più io che non mi spiego. La tua funzione riconosce se premi un tasto e stampa tasto premuto ed esco dalla funzione e fin qui va bene, anche se la verifica io la farei fuori dal for perchè una volta che il mio programma è entrato nel for non lo voglio interrompere. A me serve però anche che se in 10 secondi non viene premuto un tasto allora deve ricominciare da capo il for. capito?

apatriarca
Immagino che tu sia in grado di verificare se un qualche tasto sia stato premuto dall'ultima volta che è stata fatta la verifica. Supponiamo che questa funzionalità sia data da una funzione chiamata test che restituisce true se è stato premuto il pulsante. Se ho capito bene allora quello che vuoi fare è

puts("Attendo per 10 secondi. Premere un tasto per terminare.");

wait(10.0); // la tua funzione per aspettare

while(!test()) {
    puts("Non è stato premuto alcun pulsante. Attendo per altri 10 secondi.");
    wait(10.0);
}


E' corretto questa volta?

valentino861
ok però la mia idea originale era che invece dell'ultimo wait avrei messo un goto.Diciamo che la funzione che mi interessa cattura dati da un sensore e la chiamiamo data(). Se non viene premuto nessun tasto al posto di wait io metterei :

Inizio:
data();
puts("Attendo per 10 secondi. Premere un tasto per terminare.");

wait(10.0); // la tua funzione per aspettare

while(!test()) {
    puts("Non è stato premuto alcun pulsante, continuo con l'acquisizione dati");
    goto inizio;
} 
    puts("Acquisizione dati interrotta.");

apatriarca
Ma se usi goto non hai alcun bisogno di usare un ciclo...

inizio:

data();
puts("Attendo per 10 secondi. Premere un tasto per terminare.");

if (!test()) {
    puts("Non è stato premuto alcun pulsante, continuo con l'acquisizione dati"); 
    goto inizio;    
}

puts("Acquisizione dati interrotta.");


E' possibile fare la stessa cosa anche usando un ciclo. Per esempio:

for (;;) {
    data();
    puts("Attendo per 10 secondi. Premere un tasto per terminare.");

    if (test()) break;

    puts("Non è stato premuto alcun pulsante, continuo con l'acquisizione dati");
}

puts("Acquisizione dati interrotta.");

valentino861
cosa significa for (;;) ?? E' tipo un ciclo infinito?

In ogni caso va bene anche cosi, ma cosa cambia? Non sono un informatico ma ho letto un pò che la funzione goto è molto mal vista.

apatriarca
for ( ; ; ) è un ciclo infinito, ci sono altri modi per farlo. L'uso del goto può rendere il codice meno chiaro e quindi rendere più complicata la sua comprensione. In alcuni casi il codice con il goto è invece più semplice e leggibile. Il mio consiglio è di usarlo con parsimonia. Personalmente non lo uso quasi mai.

valentino861
ho fatto una funzione test() che mi legge da tastiera se premo un tasto...il problema è che il programma non avanza finchè non premo un tasto, insomma ancora il problema orginale!?!?!?? help me

valentino861
cioè non riesco a farlo ripartire senza spingere un tasto? Aspetta che premo un tasto e poi riparte

apatriarca
Potresti postare il tuo di codice. È difficile consigliarti senza avere alcuna idea delle API che utilizzi.

valentino861
//Funzione per l'attesa
void wait(double seconds){
	clock_t endwait;
	endwait=clock()+seconds*CLOCKS_PER_SEC;
	while (clock()<endwait);
}

int test(){
	bool tester=1;
	cin>>tester;
	if(tester!=0){
		return 1;
	}
	
return 0;
}


int main()
{

for(;;){
		//dati();
		puts("Attendo per 5 secondi. Premere un tasto per terminare.\n");	
		if (test()) break;
		wait(1);
		puts("Non è stato premuto alcun pulsante, continuo con l'acquisizione dati\n");
	}

puts("Acquisizione dati interrotta."); 

	getchar();
	getchar();

	return 0;
}



apatriarca
Il problema è la tua funzione test
int test(){ 
   bool tester=1; 
   cin>>tester; 
   if(tester!=0){ 
      return 1; 
   }
return 0; 
}

Non puoi usare cin per sapere se è stato premuto un tasto perché rimane in attesa finché non gli arrivano dei dati attraverso lo stream. Dovresti rifarti ad una diversa API. Per che tipo di piattaforma stai progettando questo software? Puoi usare librerie non standard del C++?

valentino861
Uso visual studio 2005 e lavoro su windows. Che consigli mi dai?

valentino861
qualche consiglio ragazzi?!

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.