2012-11-21 42 views
6

Chức năng này được cho là đọc một phần nhỏ và đặt nó vào một mảng. Nếu người dùng nhập '0', chức năng được cho là sẽ thoát. Tôi đang cố gắng làm điều này bằng cách sử dụng hàm cin.peek() nhưng thực thi luôn đi vào câu lệnh if và không cho phép người dùng thoát ra.Cách sử dụng đúng cách cin.peek()

Làm thế nào tôi nên đúng mã này (Tôi mở cửa cho không sử dụng peek(), tôi nghĩ đó là cách đơn giản nhất để làm việc đó.)

Cảm ơn!

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

thử nghiệm này của peek() hoạt động tuy nhiên:

#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

Tôi đã thêm trường hợp tôi có thể xem peek() để hoạt động chính xác nhưng tôi không thấy điều gì gây ra sự cố trong trường hợp của tôi. – Zzz

Trả lời

11

Có hai vấn đề với việc bạn sử dụng std::istream::peek():

  1. Chức năng này truy cập các ký tự tiếp theo và làm không bỏ qua khoảng trắng hàng đầu. Bạn có thể muốn bỏ qua khoảng trắng phía trước trước khi xác định ký tự tiếp theo là gì, ví dụ: sử dụng trình xử lý std::ws: (std::cin >> std::ws).peek().
  2. Kết quả từ std::istream::peek() không phải là char. Thay vào đó, nó là một std::char_traits<char>::int_type (đó là một chính tả ưa thích của int). Kết quả có thể, ví dụ, là std::char_traits<char>::eof() và nếu giá trị '0' xảy ra là âm (tôi không biết bất kỳ nền tảng nào ở đó, tuy nhiên, ví dụ: ký tự vui từ tên của tôi 'ü' là giá trị âm trên nền tảng nơi char đã được ký), bạn cũng sẽ không nhận được kết quả chính xác. Nghĩa là, bạn thường so sánh kết quả của std::istream::peek() so với kết quả của std::char_traits<char>::to_int_type(), ví dụ, bạn muốn sử dụng một cái gì đó như thế này: std::cin.peek() == std::char_traits<char>::to_int_type('0')

Điều đó nói rằng, chương trình của bạn không kiểm tra xem nó có thể đọc thành công bên giao đại diện và mẫu số, cách nhau bằng dấu gạch chéo. Bạn luôn muốn xác minh đọc rằng đã thành công, ví dụ, sử dụng một cái gì đó giống như

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

Chỉ cần để giải trí, bạn có thể tạo ra một kẻ thao túng để thử nghiệm mà một nhân vật là một dấu gạch chéo, quả thật vậy:

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

Bằng cách này, bạn sẽ đóng gói thử nghiệm cho dấu gạch chéo. Nếu bạn cần sử dụng điều này ở nhiều nơi, điều này khá tiện dụng.

+0

Đây thực sự là thông tin hữu ích, nhưng tôi vẫn còn lại với cùng một vấn đề, trừ khi tôi không hiểu điều gì đó trong lời giải thích của bạn :). Khi người dùng nhập thực thi '0' vào câu lệnh if. – Zzz

+0

Tôi đang dán mã (trong câu hỏi) hoạt động bằng cách sử dụng peek(), nhưng tôi không thể tìm ra cách áp dụng nó trong trường hợp sử dụng của mình. – Zzz

+0

Bạn có thêm bỏ qua khoảng trắng, tức là, ít bit «std :: ws' này? Tôi đã sẵn sàng để đặt cược rằng nhân vật mà bạn nhìn thấy trong bài kiểm tra là một số loại không gian, rất có thể là một dòng mới. –

Các vấn đề liên quan