2016-05-13 13 views
7

Mi chiedevo quale sia il modo più efficace per produrre una nuova linea da console. Si prega di spiegare perché una tecnica è più efficiente. Efficiente in termini di prestazioni.Il modo più efficiente per generare una nuova riga

Ad esempio:

cout << endl; 
cout << "\n"; 
puts(""); 
printf("\n"); 

La motivazione per questa domanda è che trovo la mia auto scrittura loop con uscite e ho bisogno di uscita di una nuova linea dopo tutte le iterazioni del ciclo. Sto cercando di scoprire qual è il modo più efficace per farlo, supponendo che nient'altro abbia importanza. Questa supposizione che nient'altro conta è probabilmente sbagliata.

+2

'fputc ('\ n', stdout)'? –

+0

Tutti gli esempi restituiscono il carattere di fine riga (facoltativamente preceduto dal ritorno a capo, a seconda del sistema operativo). Il ritorno a capo è denotato '\ r'. – kfx

+1

_ @ Harrison Tran_ Qual è l'effetto effettivo che ti aspetti? Alcuni collegamenti per l'output di formattazione del testo potrebbero prendere in considerazione l'estensione di ''\ r'' e/o la chiamata di' flush() 'in modo esplicito, a prescindere. –

risposta

1

La risposta a questa domanda è davvero "dipende".

In isolamento - se tutti si sta misurando è la prestazione di scrivere un carattere '\n' al dispositivo di uscita standard, non modificando il dispositivo, non cambiare ciò che si verifica il buffering - allora sarà difficile da battere opzioni come

putchar('\n'); 
fputchar('\n', stdout); 

std::cout.put('\n'); 

Il problema è che questo non raggiunge molto - tutto ciò che fa (supponendo che l'output sia su una schermata o una finestra dell'applicazione visibile) è spostare il cursore sullo schermo e spostare l'output precedente verso l'alto. Non è esattamente un'esperienza interessante o di valore per un utente del tuo programma. Quindi non lo farai da solo.

Ma ciò che entra in gioco influisce sulle prestazioni (ma lo misurate) se non produciamo newline in modo isolato? Vediamo;

  • uscita di stdout (o std::cout) è tamponato per default. Perché l'output sia visibile, le opzioni includono lo spegnimento del buffering o il codice per svuotare periodicamente il buffer. È anche possibile utilizzare stderr (o std::cerr) poiché il buffer è di default, supponendo che anche stderr sia indirizzato alla console e che l'output abbia le stesse caratteristiche di prestazione di stdout.
  • stdout e std::cout sono formalmente sincronizzati di default (ad esempio, guardare in alto std::ios_base::sync_with_stdio) per consentire la miscelazione di uscita per stdout e std::cout (lo stesso vale per stderr e std::cerr)
  • Se le uscite di codice di più di un insieme di caratteri di nuova riga, ci è l'elaborazione (accesso o lettura dei dati su cui si basa l'output, con qualsiasi mezzo) per produrre queste altre uscite, la loro gestione tramite funzioni di output, ecc.
  • Esistono diverse misure di prestazione, e quindi diversi mezzi di migliorare l'efficienza in base a ciascuno di essi. Ad esempio, potrebbero esserci cicli CPU, tempo totale di visualizzazione dell'output sulla console, utilizzo della memoria, ecc. Ecc.
  • La console potrebbe essere una schermata fisica, potrebbe essere una finestra creata dall'applicazione (ad esempio, ospitata in X, finestre). Le prestazioni saranno influenzate dalla scelta dell'hardware, dall'implementazione dei sottosistemi windowing/GUI, dal sistema operativo, ecc.

Quanto sopra è solo una selezione, ma ci sono numerosi fattori che determinano cosa potrebbe essere considerato più o meno prestazione.

10

putchar('\n') è il più semplice e probabilmente il più veloce. cout e printf con stringa "\n" funzionano con stringa terminata null e questo è più lento perché si elaborano 2 byte (0A 00). A proposito, il ritorno a capo è \r = 13 (0x0D). Il codice \n è Line Feed (LF).

+0

Qual è la differenza tra ritorno a capo e avanzamento riga? –

+8

@HarrisonTran - il ritorno a capo sposta la posizione di stampa all'inizio della riga corrente. L'avanzamento riga sposta la posizione di stampa su una riga. Insieme producono una nuova linea. Ma questo non ha nulla a che fare con la domanda che hai fatto e sono sconcertato dalla loro menzione in questa risposta. –

+0

Stai mescolando i livelli. In C e C++ '\ r' è il ritorno a capo, e' '\ n' è una nuova riga. In ASCII, 0x0A è il feed di riga e 0x0D è il ritorno a capo. La maggior parte dei compilatori codifica '\ r' e' \ n' internamente come 0x0D e 0x0A per comodità, ma questo è un dettaglio di implementazione, non un requisito. –

3

Su Ubuntu 15.10, g ++ v5.2.1 (e un vecchio VxWorks, e OSE)

È facile dimostrare che

std::cout << std::endl; 

mette una nuova char linea nel buffer di uscita, e quindi scarica il buffer sul dispositivo.

Ma

std::cout << "\n"; 

mette una nuova char linea nel buffer di uscita, e non fa uscita al dispositivo. Saranno necessarie alcune azioni future per attivare l'output del char newline nel buffer sul dispositivo.

Due di tali azioni sono:

std::cout << std::flush; // will output the buffer'd new line char 

std::cout << std::endl; // will output 2 new line chars 

Ci sono anche diverse altre azioni che possono scatenare il colore del buffer std :: cout.


#include <unistd.h> // for Linux 
void msDelay (int ms) { usleep(ms * 1000); } 

int main(int, char**) 
{ 
    std::cout << "with endl and no delay " << std::endl; 

    std::cout << "with newline and 3 sec delay " << std::flush << "\n"; 
    msDelay(3000); 

    std::cout << std::endl << " 2 newlines"; 
    return(0); 
} 

E, a commento di qualcuno che conosce (mi dispiace, non so come copiare il suo nome qui), ci sono eccezioni per alcuni ambienti.

+1

_ "e non viene emesso sul dispositivo." _ Questo non è garantito, sfortunatamente, e si potrebbe effettivamente avere un'implementazione che implica l'aggiunta di ''\ r'' e l'attivazione di' flush() '. –

4

In realtà dipende dall'implementazione del SO/Compilatore.

Il più efficiente, almeno effetto collaterale modo garantito per produrre un carattere di nuova riga '\n' è quello di utilizzare std::ostream::write() (e per alcuni sistemi richiede std::ostream è stato aperto in modalità std::ios_base::binary):

static const char newline = '\n'; 
std::cout.write(&newline,sizeof(newline)); 
6

Non lo sai specificare se si sta richiedendo che l'aggiornamento alla schermata sia immediato o differito fino al prossimo flush.Pertanto:

se si sta utilizzando iostream IO:

cout.put('\n'); 

se si sta utilizzando stdio io:

std::putchar('\n'); 
2

vorrei suggerire di usare:

std::cout << '\n'; /* Use std::ios_base::sync_with_stdio(false) if applicable */ 

o

fputc('\n', stdout); 

E attivare l'ottimizzazione e lasciare che il compilatore decida qual è il modo migliore per fare questo lavoro banale.

Problemi correlati