2014-12-10 10 views
6

seguito è an example from cppreference.com,Confuso circa l'utilizzo di 'std :: istreambuf_iterator'

The Code is: 
#include <vector> 
#include <sstream> 
#include <iostream> 
#include <iterator> 

int main() 
{ 
// typical use case: an input stream represented as a pair of iterators 
std::istringstream in("Hello, world"); 
std::vector<char> v((std::istreambuf_iterator<char>(in)), 
         std::istreambuf_iterator<char>()); 
std::cout << "v has " << v.size() << " bytes. "; 
v.push_back('\0'); 
std::cout << "it holds \"" << &v[0] << "\"\n"; 


// demonstration of the single-pass nature 
std::istringstream s("abc"); 
std::istreambuf_iterator<char> i1(s), i2(s); 
std::cout << "i1 returns " << *i1 << '\n' 
      << "i2 returns " << *i2 << '\n'; 
++i1; 
std::cout << "after incrementing i1, but not i2\n" 
      << "i1 returns " << *i1 << '\n' 
      << "i2 returns " << *i2 << '\n'; 
++i2; // this makes the apparent value of *i2 to jump from 'a' to 'c' 
std::cout << "after incrementing i2, but not i1\n" 
      << "i1 returns " << *i1 << '\n' 
      << "i2 returns " << *i2 << '\n'; 

} 

Ho due domande:

  1. Qualcuno può elaborare il codice di std::vector<char> v((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());, io non capisco di cosa si tratta facendo..e perché possiamo stampare la stringa "Hello, world" usando semplicemente cout<<&v[0]
  2. Perché il valore apprend di * i2 passa da "a" a "c"? qualcuno può spiegarne i meccanismi?

Grazie mille!

risposta

10

qualcuno possa elaborare il codice di ...

std::vector<T> ha un costruttore che prende due iteratori su <T> - uno per l'inizio e uno per la fine del campo.

Questo costruttore rende un flusso di iteratore di input da un flusso di input in:

std::istreambuf_iterator<char>(in) 

È possibile accedere ai suoi elementi di andare avanti fino a raggiungere la fine del flusso. Una volta raggiunta la fine del flusso, l'iteratore diventa equivalente ad un iteratore creato utilizzando il costruttore di default:

std::istreambuf_iterator<char>() 

Pertanto, passando questa coppia di iteratori costruisce un vector<T> dai dati letti da un flusso di input. L'intero flusso verrà consumato.

Perché il valore di apprent *i2 salto per "a" a "c"?

Entrambi gli iteratori stanno leggendo dallo stesso flusso. Quando si incrementa il primo iteratore, viene consumato 'b' dal flusso sottostante. Nel frattempo, i2 si riferisce al primo carattere del flusso, che ha ottenuto senza avanzare nel momento in cui è stato costruito.

Una volta incrementato lo i2, chiede allo stream il carattere successivo. Il carattere 'b' è già stato consumato, quindi il carattere successivo è 'c'.

Infine, il codice tira un piccolo trucco che si può avere trascurato: si spinge un terminatore null nella vector<char> al fine di essere in grado di stampare il vettore utilizzando il const char* sovraccarico operator <<(...).

+0

Inoltre, come è in grado di stampare il messaggio come '& v [0]'? :) – 0x499602D2

+0

Perché 'v [0]' è un 'char' quindi' & v [0] 'è un' char * ' –

+0

Molto dettagliato! Grazie per la tua risposta!!!! –

2

Un valore predefinito istreambuf_iterator è fondamentalmente un iteratore di fine file, ovvero un altro iteratore lo confronta solo quando raggiunge la fine del file.

Pertanto, il codice:

std::vector<char> v((std::istreambuf_iterator<char>(in)), 
         std::istreambuf_iterator<char>()); 

...legge char s da in fino a quando il primo iteratore è stato incrementato per eguagliare il secondo iteratore, che si verifica quando (e solo quando) il primo iteratore raggiunge la fine del file (stringstream, in questo caso). In breve, copia l'intero contenuto del file nel vettore.

La stampa "ciao mondo" parte è un po 'più semplice: ostream ha un operator<< sovraccarico per char *, che presuppone che i char * punti a una stringa in stile C, quindi dovrebbe stampare l'intera stringa che è puntato. Dal momento che hanno fatto un push_back per aggiungere uno '\0' alla stringa, questo lo rende una stringa in stile C.

La seconda parte sta dimostrando che anche se avete due iteratori nello stream, avete ancora un solo flusso e una posizione di lettura in quel flusso. Allo stesso tempo, ogni iteratore contiene una copia dell'elemento più recente letto dallo stream.

Pertanto, ogni volta che si Incremento sia iterator (o qualsiasi iteratore nello stesso flusso) incrementa la posizione di lettura corrente. Quindi, inizi con i1 e i2 puntando entrambi all'inizio del flusso. Quindi si incrementa i1. Questo incrementa la posizione di lettura e legge b in i1, quindi quando si annulla il numero i1, questo è ciò che otterrete. Quando si incrementa i2, questo sposta nuovamente la posizione di lettura e legge c in i2, pertanto il dereferenziazione i2 darà c.

In breve, l'uso di due (o più) iteratori non cambia la natura del flusso - ogni volta che si incrementa qualsiasi iteratore nello stesso torrente, che legge il elemento successivo da quel flusso - e il "prossimo elemento" è sempre determinato dallo stream stesso, in base alla sua posizione di lettura una.

+1

Grazie per la tua risposta! davvero utile !!! Grazie per il tuo tempo! –

Problemi correlati