2012-11-21 16 views
6

Questa funzione dovrebbe leggere una frazione e inserirla in una matrice. Se l'utente inserisce "0", la funzione dovrebbe uscire. Sto cercando di farlo usando la funzione cin.peek() ma l'esecuzione va sempre nella dichiarazione if e non consente all'utente di uscire.Come utilizzare correttamente cin.peek()

Come dovrei correttamente Questo codice (io sono aperto a non utilizzare peek(), ho pensato che fosse il modo più semplice di farlo.)

Grazie!

void enterFrac(Fraction* fracs[], int& index) 
    { 
     int n, d; 
     char c, slash; 
     cout << "Enter fractions (end by entering a 0): "; 
     c = cin.peek(); 

     if (c != '0') 
     { 
      cin >> n >> slash >> d; 
      Fraction* f = new Fraction(); 
      f->num = n; 
      f->den = d; 
      fracs[index] = f; 
      index++; 
     } 
    } 

Questa prova di peek() funziona comunque:

#include <iostream> 
using namespace std; 

int main() { 
    char c; 
    int n; 
    char str[256]; 

    cout << "Enter a number or a word: "; 
    c=cin.peek(); 

    if ((c >= '0') && (c <= '9')) 
    { 
    cin >> n; 
    cout << "You have entered number " << n << endl; 
    } 
    else 
    { 
    cin >> str; 
    cout << " You have entered word " << str << endl; 
    } 

    return 0; 
} 
+0

Ho aggiunto un caso in cui posso fare in modo che peek() funzioni correttamente, ma non vedo quale sia la causa del problema nel mio caso. – Zzz

risposta

11

Ci sono due problemi con l'utilizzo del std::istream::peek():

  1. Questa funzione di accesso il carattere successivo e non salta gli spazi bianchi iniziali. Probabilmente vuoi saltare lo spazio bianco iniziale prima di determinare quale sia il carattere successivo, ad esempio, utilizzando il manipolatore std::ws: (std::cin >> std::ws).peek().
  2. Il risultato da std::istream::peek() non è un char. Invece, è un std::char_traits<char>::int_type (che è una fantasia fantasia di int). Il risultato potrebbe essere, ad esempio, std::char_traits<char>::eof() e se il valore di '0' è negativo (non sono a conoscenza di alcuna piattaforma in cui si trova, tuttavia, ad esempio, il personaggio divertente dal mio nome 'ü' è un valore negativo su piattaforme in cui char è firmato) non otterresti neanche il risultato corretto. Cioè, si confronta normalmente il risultato di std::istream::peek() contro il risultato di std::char_traits<char>::to_int_type(), cioè, utilizza qualcosa di simile: std::cin.peek() == std::char_traits<char>::to_int_type('0')

Detto questo, il programma non verifica se è in grado di leggere correttamente il designatore e il denominatore, separato da una barra. È sempre desidera verificare che la lettura ha avuto successo, ad esempio, utilizzando qualcosa di simile

if ((std::cin >> nominator >> slash >> denominator) && slash == '/') { 
    ... 
} 

Solo per divertimento, è possibile creare un manipolatore per la prova che un personaggio è una barra, anzi:

std::istream& slash(std::istream& in) { 
    if ((in >> std::ws).peek() != std::char_traits<char>::to_int_type('/')) { 
     in.setstate(std::ios_base::failbit); 
    } 
    return in; 
} 

In questo modo, incapsuleresti il ​​test per la barra. Se hai bisogno di usarlo in più posti questo è abbastanza utile.

+0

Questa è un'informazione veramente utile, ma mi rimane lo stesso problema, a meno che non abbia capito qualcosa nella tua spiegazione :). Quando l'utente inserisce l'esecuzione "0", inserisce l'istruzione if. – Zzz

+0

Sto incollando il codice (nella domanda) che funziona usando peek(), ma non riesco a capire come applicarlo nel mio caso d'uso. – Zzz

+0

Hai aggiunto saltando spazi bianchi, cioè questo piccolo bit 'std :: ws'? Sarei pronto a scommettere che il personaggio che vedi nel test è una sorta di spazio, molto probabilmente una nuova riga. –