Domanda

Sto scrivendo un semplice codice che estrarrà un mucchio di nomi, coppie int da un file. Sto modificando il codice esistente che utilizza solo:

string chrom;
unsigned int size;
while ( cin >> chrom >> size ) {
    //  save values
}

Ma voglio usare un altro file di input (simile) che ha le stesse prime due colonne, ma sono seguiti da altri dati (che verranno ignorati). Quindi scrivo:

string chrom;
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}

Ma questo non riesce a compilare, dando il tipico osceno modello std lib spew:

 error: no match for "operator>>" in "std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >(((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& line))), std::operator|(_S_out, _S_in)) >> chrom"
istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
[...another dozen lines...]

destro. line non è uno std :: string, ma alcune varianti di std :: basic_string, ecc. Tuttavia, istanziando esplicitamente le opere stringstream.

string chrom;
unsigned int size;
string line;
while ( getline(genome, line) ) {
    stringstream ss(line);
    if ( ss >> chrom >> size ) {
       // save values
    }
    // Discard remainder of line
}

Perché? Cosa c'è di sbagliato nel primo caso? Il esempio basic_io al sempre utile cplusplus.com funziona, perché non codice?

Aggiornamento: Un altro punto di riferimento: lo stringstream temporaneo funziona quando il primo valore estratto è un int anziché una stringa:

unsigned int chrom;  // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}
È stato utile?

Soluzione

Tre gruppi di funzioni membro e un gruppo di funzioni globali sovraccaricano questo "operatore di estrazione" (> >), vedi http: //www.cplusplus. com / riferimento / istream / istream / operatore% 3E% 3E / .

  • stringstream (linea); --creato un oggetto temporaneo
  • stringstream ss (line); - un oggetto normale.

quando " chrom " è int, operatore > > è sovraccaricato come estrattore aritmetico che è funzioni membro. Sia l'oggetto normale che l'oggetto temporaneo funzionano correttamente.

Quando " chrom " è stringa, operatore > > dovrebbe essere sovraccarico come istream & amp; operatore > > (istream & amp; is, char * str) , questa è una funzione globale che dovrebbe prendere il riferimento all'oggetto come parametro. Tuttavia, dato l'oggetto temporaneo, non è consentito passare oggetti temporanei tramite riferimento non const nel C ++ standard. La funzione di sovraccarico non può ottenere il riferimento dell'oggetto temporaneo a meno che la funzione di sovraccarico non sia definita come istream & amp; operatore > > (const istream & amp; is, char * str) . Sfortunatamente, non è questo il fatto. Le funzioni non possono essere sovraccaricate nel caso di oggetto temporaneo, e quindi dare l'errore come error: nessuna corrispondenza per la funzione ...

Altri suggerimenti

Per espandere la risposta di John Weldon, l'operatore extrace " > > " fa due cose:

  1. Estrae il valore successivo e lo posiziona nella variabile a destra dell'operatore.
  2. Incrementa la posizione corrente del flusso a sinistra.

Pertanto, modifica sia l'operando sinistro che quello destro. Nel tuo caso, l'operando di sinistra è un valore temporaneo e il compilatore si acciglia di modificarlo.

Alcuni operatori in C e C ++ richiedono che il valore a sinistra dell'operatore sia un valore, vale a dire che possono essere modificati.

Qui è una spiegazione più completa.

Perché il primo valore estratto da stringstream è uno std :: string. Se fosse, diciamo, un int, la versione stringstream (line) funzionerebbe.

Non esiste un operatore con funzioni membro > > in stringstream per std :: string. Pertanto, il flusso temporaneo non può funzionare come lvalue.

Non che io abbia compreso appieno quanto sopra ... ma forse è un punto di partenza per una risposta migliore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top