2012-11-21 32 views
6

Ta funkcja ma odczytać ułamek i umieścić go w tablicy. Jeśli użytkownik wpisze "0", funkcja powinna wyjść. Próbuję to zrobić za pomocą funkcji cin.peek(), ale wykonanie zawsze przechodzi do instrukcji if i nie pozwala użytkownikowi na wyjście.Jak prawidłowo używać cin.peek()

Jak należy prawidłowo zakodować to (jestem otwarty na nie za pomocą peek(), myślałem, że to najprostszy sposób to zrobić.)

Dzięki!

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

Ten test peek() działa jednak:

#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

Dodałem przypadek, w którym można uzyskać peek() do pracy poprawnie, ale nie widzę, co jest przyczyną problemu w moim przypadku. – Zzz

Odpowiedz

11

Istnieją dwa problemy związane z korzystaniem z std::istream::peek():

  1. Ta funkcja dostępu następny znak i robi nie pomiń wiodące białe znaki. Prawdopodobnie chcesz pominąć wiodące białe znaki przed określeniem, czym jest następny znak, np. Za pomocą manipulatora: std::ws: (std::cin >> std::ws).peek().
  2. Wynik z std::istream::peek() nie jest char. Zamiast tego jest to std::char_traits<char>::int_type (co jest fantazyjną pisownią int). Rezultatem może być np. std::char_traits<char>::eof() i jeśli wartość '0' jest ujemna (nie znam żadnej platformy, na której się znajduje, jednak np. Zabawna postać o moim imieniu 'ü' ma wartość ujemną na platformach, na których char jest podpisany), że nie uzyskasz poprawnego wyniku. Oznacza to, że normalnie porównać wynik z std::istream::peek() przeciwko wyniku std::char_traits<char>::to_int_type(), czyli byłoby użyć coś takiego: std::cin.peek() == std::char_traits<char>::to_int_type('0')

Powiedział, że program nie sprawdza, czy może z powodzeniem odczytać licznik i mianownik, oddzielony ukośnikiem. Ci zawsze chcą zweryfikować, że czytanie było udane, na przykład, za pomocą czegoś podobnego

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

tylko dla rozrywki, można utworzyć manipulator do testowania, że ​​postać jest ukośnik, rzeczywiście:

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

W ten sposób zamkniesz test na ukośnik. Jeśli potrzebujesz tego w wielu miejscach, jest to bardzo przydatne.

+0

To jest naprawdę pomocna informacja, ale wciąż mam ten sam problem, chyba że nie zrozumiałem czegoś w twoim wyjaśnieniu :). Gdy użytkownik wprowadzi "0", wykonanie wchodzi do instrukcji if. – Zzz

+0

Wklejam kod (w pytaniu), który działa za pomocą funkcji peek(), ale nie mogę wymyślić, jak zastosować ją w moim przypadku użycia. – Zzz

+0

Czy dodałeś pomijanie białych znaków, tj. Tego małego 'std :: ws' bit? Mogę się założyć, że postać, którą widzisz w teście, jest jakąś przestrzenią, najprawdopodobniej nową linią. –