Loop infinito

di il
11 risposte

Loop infinito

Salve a tutti
il seguente codice va in loop infinito
il codice dovrebbe accettare un numero in input è se uno involontariamente inserisce una lettera o preme ctrl+c il programma dovrebbe riaccettare l'input.
ma ahime non fa ciò che dovrebbe fare la prima volta fa accettare l'input ma in caso di falso input,cioè inserisco un carattere al posto di un numero, va in loop infinito.

int n;	retu=SetConsoleCtrlHandler( (PHANDLER_ROUTINE) mysethandle, TRUE);
	vedi_flag();
	primo:  a=0;
	cout << "ecco i flag di stream prima dell' input\n";
	cout << "variabile a = " << a <<"\n";
	cout << "input n : ";	cin >>n;
	cout << "\nvaiabile retu = " << retu << "\n";
	vedi_flag();	a=cin.fail();
	if (a==1)
	{ 
		cin.clear (); a=0;
	    cout << "\n rieseguiamo l'input per falsovalore\n";
	    goto primo;
	}
	a=cin.rdstate();
	if (a > 1) {
		cin.clear();		cin.ignore();
		cout << "\n interruzione per ctrl+c input sbagliato riprova\n";
		goto primo;
	}
	cout << "premi quello che vuoi per terminare\n";
	cin >>n; 	return 0;
se vi puo servire inserisco anche lo schema dei flag.

stato iniziale
flag Valore
Rdstate 0
Eof 0
Fail 0
Bad 0
Good 1

Stato dopo input corretto
flag Valore
Rdstate 1
Eof 0
Fail 0
Bad 0
Good 1
Stato dopo input errato
Flag Valore
Rdstate 2
Eof 0
Fail 1
Bad 0
Good 0
per finire una domanda che può sembrare sciocca come faccio ad azzerare un solo flag senza doverli azzerare tutti con la cin.clear ?
grazie a chiunque mi spieghi il comportamento anomalo del codice su indicato
p.s.della discussione sul uso/non uso del goto sinceramente non me ne frega niente!

11 Risposte

  • Re: Loop infinito

    Dopo la cin.clear manca una

    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');


    P.S. A parte per i test, spero toglierai quei goto ... anche se non te ne frega niente ...
  • Re: Loop infinito

    Grazie per la risposta
    siccome più che la cin dovrei usare la ReadConsoleInputA
    mi sorge spontanea una domanda :
    ma le due funzioni cin.clear e cin.ignore vanno bene anche per la ReadConsoleInputA oppure per quest'ultima funzione ci sono apposite funzioni che svolgono lo stesso compito?
  • Re: Loop infinito

    Beh, allora la situazione è diversa e avresti dovuto dirlo prima ... magari non avrei perso tempo con cin e compagnia ...

    La ReadConsoleInputA è una API specifica di Windows e non una funzionalità standard di C++ come la cin.

    Per gestire i suoi errori, come per tutte le API, dovrai esaminare il suo valore di ritorno e usare le API collegate, come documentato su MSDN in



    Quando scriverai il codice con questa API, allora se ne riparlerà.
  • Re: Loop infinito

    Ciao è scusami se ti ho fatto perdere tempo con la cin.
    ma visto che mi dava lo stesso funzionamento anomalo scrivendola sia con la cin che con la readconsoleinputa ho erroneamente pensato che aggissero nella stessa maniera.
    pultroppo il link che mi hai postato non funziona
  • Re: Loop infinito

    Ora funziona ...
  • Re: Loop infinito

    Ecco la versione con la ReadConsoleInputA
    // inputkey.cpp : definisce il punto di ingresso dell'applicazione console.
    #include "stdafx.h"
    #include <iostream>
    #include <windows.h>
    using namespace std;
    int _tmain(int argc, _TCHAR* argv[])
    {
    	cout << "\n inserisci un numero :";
    	HANDLE myconsole;
    	DWORD wstdmode,letti;
    	INPUT_RECORD buffec[1];
    	int errore,i;
    	myconsole = GetStdHandle(STD_INPUT_HANDLE);
    	if (myconsole == INVALID_HANDLE_VALUE)
    	{
    		errore=GetLastError();
    		cout << "il programma è andato in errore n. " << errore <<  " nella funzione GetStdHandle\n";
    		cin >> i;
    		return 0;
    	}
    	wstdmode=ENABLE_ECHO_INPUT;
    	if (! SetConsoleMode(myconsole, wstdmode) ) 
    	{
    		errore=GetLastError();
    		cout << "il programma è andato in errore n. " << errore <<  " nella funzione SetConsoleMode\n";
    		cin >> i;		
                                CloseHandle(myconsole); 
                                return 0;
    	}
    	// prepariamoci alla lettura dei caratteri
    	char mystring[10]; char c;
    	int numero,indy; indy=0;numero=0;	short int segno;
    	while (c != '\n' && indy < 10)
    	{
    	 if (! ReadConsoleInputA( myconsole, buffec, 1, &letti) )  
    	   {
            errore=GetLastError();
    		cout << "il programma è andato in errore n. " << errore <<  " nella funzione ReadConsoleInput\n";
    		cout << "premi un tasto per terminare\n";
    		cin >> i;		indy=44;
    	 }
    	 c=buffec.KEY_EVENT. AsciiChar; 
    	 if (c=='-' && indy !=0)	 { goto riaccetta; }
    	 if (c=='+' && indy !=0)	 { goto riaccetta; }
    	 if (c < '0' && c>'9'){ goto riaccetta; } // gestione falso input
         mystring[indy]=c; indy++;
    riaccetta:;
    	}
    	CloseHandle(myconsole);	return 0;
    }
    
    adesso il falso input lo gestisco ma come gestisco il ctrl+c.
    grazie anticipatamente per la risposta che mi darai.
  • Re: Loop infinito

    Prima di tutto, questo codice non mi sembra corretto ... Cosa è questa riga

    c=buffec.KEY_EVENT. AsciiChar;

    ?

    E dove sta la gestione degli eventi?

    Un esempio di uso della ReadConsoleInput è questo

  • Re: Loop infinito

    Allora c=buffec.KEY_EVENT. AsciiChar;
    era un tentativo per copiarmi il codice da analizzare.
    comunque adesso ho aggiunto una gestione degli eventi
    ti riposto il codice
    #include "stdafx.h"
    #include <iostream>
    #include <windows.h>
    void keyeventproc(KEY_EVENT_RECORD,char);
    using namespace std;
    int _tmain(int argc, _TCHAR* argv[])
    {
    	cout << "\n inserisci un numero :";
    	HANDLE myconsole;
    	DWORD wstdmode,letti;
    	INPUT_RECORD irInBuf[2];
    	int errore,i;
    	myconsole = GetStdHandle(STD_INPUT_HANDLE);
    	if (myconsole == INVALID_HANDLE_VALUE)
    	{
    		errore=GetLastError();
    		cout << "\nil programma è andato in errore n. " << errore <<  " nella funzione GetStdHandle\n";
    		cin >> i;
    		return 0;
    	}
    	wstdmode=ENABLE_ECHO_INPUT;
    	if (! SetConsoleMode(myconsole, wstdmode) ) 
    	{
    		errore=GetLastError();
    		cout << "\nil programma è andato in errore n. " << errore <<  " nella funzione SetConsoleMode\n";
    		cin >> i;
    		return 0;
    	}
    	// prepariamoci alla lettura dei caratteri
    	char mystring[10];
    	char c;
    	int numero,indy; indy=0;numero=0;
    	short int segno; c=' ';
    	while (c != '\n' && indy < 10)
    	{
    		for (int kindy=0;kindy<2;kindy++)
    		{
    	 if (! ReadConsoleInputA( myconsole, irInBuf, 2, &letti) )  
    	   {
            errore=GetLastError();
    		cout << "il programma è andato in errore n. " << errore <<  " nella funzione ReadConsoleInput\n";
    		cout << "premi un tasto per terminare\n";
    		cin >> i;
    		indy=44;
    	 }
    	 //gestione evento
    	  switch(irInBuf[0].EventType)
    	  {
                    case KEY_EVENT: // keyboard input 
    					{
    						keyeventproc (irInBuf[0].Event.KeyEvent,c);
                          break; 
    					}
    				default: 
    					{
    						cout << "non ci interessano almeno per il momento!\n";
    							break;
    					}
    	}
    		}
    	 if (c=='-' && indy !=0)	 { goto riaccetta; }
    	 if (c=='+' && indy !=0)	 { goto riaccetta; }
    	 if (c < '0' && c>'9'){ goto riaccetta; } // gestione falso input
         mystring[indy]=c; indy++;
    riaccetta:;
    	}
    	CloseHandle(myconsole);
    	return 0;
    }
    void keyeventproc( KEY_EVENT_RECORD ker,char c)
    {
    	if(ker.bKeyDown)
    	{ c=' '; }
    	else { 
    		c= ker.uChar.AsciiChar;
    	 }
    }
  • Re: Loop infinito

    Non ho provato il codice ma se funziona e aggiungi l'handler per il controllo del Ctrl Break risolvi.
  • Re: Loop infinito

    Visto che sto usando la ReadConsoleInputA
    con quali funzioni dovrei gestire i flag che non siano cin.clear() cin.fail() etc etc?
    perchè se non li gestisco rischio di mandare in loop infinito la gestione del ctrl c e del ctrl break e mi ritroverei quasi al punto di partenza.
  • Re: Loop infinito

    No, non ci sono flag ... controlla il risultato dell'API ...

    Prova a scrivere il codice con il controllo del Ctrl-break ...
Devi accedere o registrarti per scrivere nel forum
11 risposte