2012-06-11 16 views
5

Io uso le seguenti righe a info progressi di uscita la mia simulazione nel mio programma C++,rimozione del cursore lampeggiante nel terminale, come?

double N=0; 
double percent=0; 
double total = 1000000; 
for (int i; i<total; ++i) 
{ 
    percent = 100*i/total; 
    printf("\r[%6.4f%%]",percent); 
} 

Funziona benissimo!

Ma il problema è che vedo il cursore del terminale continua a lampeggiare ciclicamente attraverso i numeri, questo è molto fastidioso, qualcuno sa come sbarazzarsi di questo?

Ho visto alcuni programmi come wget o ubuntu apt, usano la barra di avanzamento o anche le percentuali, ma non sembrano problemi di cursore intermittente, mi chiedo come hanno fatto?

Grazie!

risposta

10

Solo un'ipotesi: prova a utilizzare un numero corretto di caratteri '\ b' (backspace) invece di '\ r'.

== == EDIT

Io non sono un mago shell di Linux, ma questo può funzionare:

system("setterm -cursor off"); 
// ...display percentages... 
system("setterm -cursor on"); 

Non dimenticare di #include <cstdlib> o <iostream>.

+0

Purtroppo, nessun successo :( – Daniel

+0

Perché hai bisogno di percentuali? Potresti scrivere solo caratteri "#", uno dopo l'altro. Ad esempio uno "#" per ogni nuovo 10% s. – kol

+0

OOPS, adoro i numeri :) Ok, Proverò # e ti faccio sapere i risultati, ma comunque, solo un google, qualcuno ha detto che wget non ha usato ncurses – Daniel

0

Queste app stanno probabilmente utilizzando ncurses. Vedi mvaddstr

+0

wget e l'FBI sono due esempi di programmi che non usano ncurses, ma sono in grado di nascondere completamente il cursore. –

16

È possibile nascondere e mostrare il cursore usando il DECTCEM (modalità cursore di testo dicembre abilitare) la modalità in DECSM e DECRM:

fputs("\e[?25l", stdout); /* hide the cursor */ 

fputs("\e[?25h", stdout); /* show the cursor */ 
+0

Intendi nel ciclo, dopo questo comando 'printf (" \ r [% 6.4f %%] ", percentuale);' ? – Daniel

+0

Ovunque siano richiesti. In genere nasconderai il cursore prima di qualsiasi aggiornamento, eseguirai tutti gli aggiornamenti, quindi lo mostrerai di nuovo alla fine. Potresti anche combinarli tutti in un solo 'printf', se vuoi. – LeoNerd

0

Un modo per evitare un cursore lampeggiante è (come suggerito) per nascondere il cursore temporaneamente.

Tuttavia, questa è solo una parte della soluzione. Il vostro programma dovrebbe anche tener conto di questo:

  • dopo aver nascosto il cursore e modificando lo schermo, prima di che mostra il cursore di nuovo mossa di nuovo alla posizione originale.
  • nascondere/mostrare il cursore mantiene il cursore solo in modo che lampeggi notevolmente quando gli aggiornamenti richiedono solo una piccola quantità di tempo. Se ti è capitato di mescolare questo con un processo che richiede tempo, il tuo cursore lampeggerà.

La soluzione suggerita che utilizza setterm non è portatile; è specifico per la console Linux. E l'esecuzione di un eseguibile usando system non è realmente necessaria. Ma anche in esecuzione

system("tput civis"); 
... 
system("tput cnorm"); 

è un miglioramento rispetto all'uso di setterm.

Il controllo del codice sorgente per wget non trova sequenze di escape che nascondano il cursore. Quello che stai vedendo con la sua barra di avanzamento è che lascia il cursore approssimativamente nello stesso posto ogni volta che fa qualcosa che richiede tempo. L'output sul terminale impiega così poco tempo da non notare la riscrittura momentanea della linea (stampando un ritorno a capo, quindi scrivendo di nuovo la maggior parte della riga).Se fosse più lento, nascondere il cursore aiuterebbe — fino a un punto.

Questa tecnica di occultamento del cursore viene utilizzata nei driver del terminale per alcuni editor (vim e vile).

+0

Penso che il vero motivo per cui 'wget' non ha questo problema è perché stampano su' stderr' che è senza buffer, invece di 'stdout' che è bufferizzato. – santileortiz

-1

Il motivo per cui il cursore salta in giro è perché stdout è memorizzato nel buffer, quindi non si sa in realtà quanti caratteri vengono stampati in un determinato momento. Il motivo wget non ha un cursore di salto è che in realtà stanno stampando su stderr invece. Provare quanto segue:

fprintf(stderr,"\r[%6.4f%%]",percent); 

Questo ha anche il vantaggio di non ingombrare il file se si sta salvando il resto dell'output da qualche parte con un tubo come:

$ ./executable > log.data 
Problemi correlati