2010-07-16 12 views
18

Ho uno std :: istream che si riferisce ai dati della matrice, qualcosa di simile:C++ leggere da istream fino a capo (ma non gli spazi bianchi)

0.0 1.0 2.0 
3.0 4.0 5.0 

Ora, al fine di valutare il numero di colonne vorrei avere qualche codice come:

std::vector<double> vec; 
double x; 
while((...something...) && (istream >> x)) 
{ 
    vec.push_back(x); 
} 
//Here vec should contain 0.0, 1.0 and 2.0 

dove il ... qualcosa ... parte restituisce false dopo aver letto 2.0 e IStream nel punto dovrebbe essere di 3.0 in modo che la prossima

istream >> x; 

dovrebbe impostare x uguale a 3.0.

Come conseguire questo risultato? Immagino che le condizioni di tempo

Grazie mille in anticipo per il vostro aiuto!

+0

Giusto per chiarire, la ragione per cui vorrei seguire questo approccio (se fattibile) è di evitare di creare oggetti temporanei (a parte il doppio x). La matrice viene quindi creata da std :: scambiando il vettore sopra con la memoria interna della matrice (è implementata tramite un vettore std ::). – stepelu

+0

bene, puoi farlo con un temporaneo in 10 linee semplici, oppure puoi farlo senza il temporaneo in 50 linee dure. Utilizzare un temporaneo. –

risposta

12

utilizzare il metodo peek per controllare il carattere successivo:

while ((istream.peek()!='\n') && (istream>>x)) 
+3

Questo è facilmente rotto se la riga contiene * qualsiasi * spazio bianco prima del Clifford

+0

True; non c'è alcun controllo degli errori qui, sto solo assumendo che l'input sia ben formato. – tzaman

6

Leggere le righe in una stringa: std :: std::getline(), quindi assegnare la stringa a un oggetto std::istringstream ed estrarre i dati da quello anziché direttamente da istream.

+0

Mi spiace di non averlo chiarito ma questo è quello che sto cercando di evitare. Il punto è che non so in anticipo se la matrice avrà molte colonne o molte righe e avere 10.000 doppi di stringhe non è un approccio molto efficace al problema :) Scusa ancora per non averlo chiarito, colpa mia. – stepelu

0

Leggere il numero, quindi leggere un carattere per vedere se è newline.

1

È possibile utilizzare std::istream::peek() per verificare se il carattere successivo è una nuova riga. Vedere this entry nel riferimento cplusplus.com.

2
std::vector<double> vec; 
{ 
    std::string line; 
    std::getline(ifile, line); 
    std::istringstream is(line); 
    std::copy(std::istream_iterator<double>(is), std::istream_iterator<double>(), 
       std::back_inserter(vec)); 
} 
std::cout << "Input has " << vec.size() << " columns." << std::endl; 
std::cout << "Read values are: "; 
std::copy(vec.begin(), vec.end(), 
      std::ostream_iterator<double>(std::cout, " ")); 
std::cout << std::endl; 
+0

OP in particolare menzionato prima di non voler bufferizzare un'intera linea. – tzaman

+0

Il suo codice proposto richiede che dopo un po 'il vettore debba contenere la prima riga: '// Qui vec dovrebbe contenere 0.0, 1.0 e 2.0'. Non vuole leggere una riga o l'intero file? –

+0

Sì, voglio terminare il ciclo while dopo aver letto la prima riga (e mantenere il resto in istream per ulteriori letture) ma vorrei evitare di dover creare una stringa per memorizzare la prima riga intera prima di metterla nel vettore . – stepelu

0

ho avuto problema simile
ingresso è come qui sotto:

1 2 
3 4 5 

Il primo due erano N1 e N2
Poi c'è una nuova riga
quindi elementi 3 4 5, io non so quanti saranno.

// read N1 & N2 using cin 
int N1, N2; 
cin >> N1; 
cin >> N2; 

// skip the new line which is after N2 (i.e; 2 value in 1st line) 
cin.ignore(numeric_limits<streamsize>::max(), '\n'); 

// now read 3 4 5 elements 
int ele; 
// 2nd EOF condition may required, 
// depending on if you dont have last new-line, and it is end of file. 
while ((cin_.peek() != '\n') && (cin_.peek() != EOF)) { 
    cin >> ele; 
    // do something with ele 
} 

Questo ha funzionato perfettamente per me.

Problemi correlati