2012-11-21 20 views
6

Diese Funktion soll einen Bruch lesen und ihn in einem Array platzieren. Wenn der Benutzer '0' eingibt, soll die Funktion beendet werden. Ich versuche, dies mit der Funktion cin.peek() zu tun, aber die Ausführung geht immer in die if-Anweisung und erlaubt dem Benutzer nicht, zu beenden.Wie man richtig cin.peek() verwendet

Wie soll ich das richtig Code (ich bin offen zu nicht peek() verwenden, ich dachte, es wäre der einfachste Weg, es zu tun.)

Dank!

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++; 
     } 
    } 

Dieser Test von peek() funktioniert jedoch:

#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

Ich fügte einen Fall hinzu, in dem ich peek() richtig arbeiten lassen kann, aber ich sehe nicht, was das Problem in meinem Fall verursacht. – Zzz

Antwort

11

zwei Probleme mit der Verwendung von std::istream::peek() Es gibt:

  1. Diese Funktion Zugriff auf das nächste Zeichen und macht nicht Überspringen von führenden Leerzeichen. Wahrscheinlich möchten Sie führende Leerzeichen überspringen, bevor Sie bestimmen, was das nächste Zeichen ist, z. B. mit dem Manipulator std::ws: (std::cin >> std::ws).peek().
  2. Das Ergebnis von std::istream::peek() ist kein char. Stattdessen ist es ein std::char_traits<char>::int_type (das ist eine schicke Schreibweise von int). Das Ergebnis kann z. B. std::char_traits<char>::eof() sein und wenn der Wert '0' zufällig negativ ist (mir ist keine Plattform bekannt, wo es ist; aber z. B. ist der lustige Charakter von meinem Namen 'ü' ein negativer Wert auf Plattformen, wo char ist signiert), würden Sie auch nicht das richtige Ergebnis erhalten. Das heißt, Sie in der Regel das Ergebnis von std::istream::peek() gegen das Ergebnis der std::char_traits<char>::to_int_type() vergleichen, das heißt, Sie so etwas wie diese verwenden würde: std::cin.peek() == std::char_traits<char>::to_int_type('0')

Das heißt, das Programm prüft nicht, ob es erfolgreich die nominator lesen konnte und der Nenner, getrennt durch einen Schrägstrich. Sie immer wollen, dass das Lesen zu überprüfen, war erfolgreich, zum Beispiel mit so etwas wie

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

nur für Unterhaltung, können Sie einen Manipulator zum Testen erstellen, dass ein Zeichen ein Schrägstrich ist in der Tat:

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; 
} 

Auf diese Weise würden Sie den Test für Schrägstrich kapseln. Wenn Sie dies an mehreren Stellen verwenden müssen, ist dies sehr praktisch.

+0

Das sind wirklich hilfreiche Informationen, aber ich habe immer noch das gleiche Problem, es sei denn, ich habe etwas in Ihrer Erklärung nicht verstanden :). Wenn der Benutzer '0' eingibt, wird die if-Anweisung eingegeben. – Zzz

+0

Ich bin Code einfügen (in der Frage), die mit peek() funktioniert, aber ich kann nicht herausfinden, wie es in meinem Anwendungsfall anwenden. – Zzz

+0

Haben Sie das Überspringen von Leerzeichen hinzugefügt, d. H. Dieses kleine 'std :: ws' Bit? Ich wäre bereit zu wetten, dass der Charakter, den Sie im Test sehen, eine Art Platz ist, höchstwahrscheinlich ein Zeilenumbruch. –