2011-10-04 5 views
4

분수 클래스에 대해 instream 연산자와 오버로드하려고합니다. 사용자로부터 문자열을 받아서 Fraction 클래스의 적절한 인수로 파싱 할 수있는 함수를 만들었지 만, >> >> 오버로드 함수에서이를 구현하는 방법을 잘 모르겠습니다. 분획의 세 가지 유형이있다분수 클래스에 대한 과부하 >> C++

그 사용자를 입력 할 수있다 : 1. 정수 (예 5) 2. 혼합 수 (예 : 2 + 5/5) 3. 일반 분획 (예, 1/2)

내 접근 방식은이 입력을 main 함수의 사용자로부터 문자열로 받아 들여 유효한 Fraction 클래스 매개 변수를 얻기 위해 구문 분석 한 다음 새로 생성 된 소수 개체를 스트림으로 반환하는 것이 었습니다. 나는 이것을하는 방법을 모르겠다. 내 연산자 오버로딩의 정의에서

,이 있습니다

istream& operator>>(istream& in,const Fraction& input) 

을하지만 문자열을 수용하고있어, 여기 매개 변수의 유형은 문자열이어야하지 않겠습니까? 나는 그 부분에 대해 매우 혼란스러워하고있다. 그런 다음 Fraction 객체를 반환하고 싶습니다. 다음은 정수 처리의 예입니다.

int num1 = atoi(input.c_str()); 
    Fraction output(num1); 
    in >> output; 
    return in; 

여기 올바른 길에 있습니까?

+1

'istream & operator >> (istream & in, const Fraction & input)'매우 이상한 서명. 당신은 정말로 출력이 변경 될 수없는 것에 출력을 의미합니까? –

답변

0

표준 접근 방식은 성분들로 사용자 정의 입력 작업을 중단하는 것입니다 :

std::istream & operator>>(std::istream & in, Fraction & input) // not const! 
{ 
    std::string token; 

    if (!(in >> token)) { return in; } // error 

    int num, den; 
    const bool res = parse_token(token, num, den); // write this! 

    if (!res) 
    { 
    in.setstate(std::ios::failbit); 
    return in; 
    } 

    input.set(num, den); // or whatever 
} 

요점은 예 경우 문자열이 유효한 비율을 나타내는 지 여부를 결정하는 parse_token(const std::string &, int &, int &) 함수를 작성하고, 분자와 분모를 각각의 두 변수에 넣습니다.

+0

어떻게 토큰이 사용자 입력에 할당 되었습니까? 그것이 나를 혼란스럽게 만든다. –

+0

토큰은'in >> token'에서 입력 스트림에서 추출한 단일 문자열입니다. 토큰에 공백이 없으면 즉'1/2'는 작동하지만'1/2'는 (보통의 형식화 된 입력 규칙에 따라) 작동하지 않는 경우에만 작동합니다. –

1

streams이 아닌 strings으로 작업해야합니다. 사용자가 string으로 입/출력을 원하면 항상 stringstream을 사용할 수 있습니다. 당신의 입력 매개 변수가 const를 안 귀하의 정의는, 스트림의 언어가 istream에서 Fraction을 추출 의미

istream& operator>>(istream& in,const Fraction& input) 

있음을 유의하십시오. 반면에, 출력에 ostream 하나에 Fraction

ostream& operator<<(ostream& in,const Fraction& input) //Here const is good 

은 또한, 하나의 최종 문서가 istream/ostream이 요소로 char 기본 특성 작업 특정 구현 있다는 것입니다 선언합니다.

istream& operator>>(istream& in, Fraction& input)

: 그것은 const하지 않을 수 있도록 더 일반적인 구현은 출력 매개 변수가 될 필요이

template< typename Elem, typename Traits > 
std::basic_istream< Elem, Traits >& operator>>(std::basic_istream< Elem, Traits >& in, Fraction& input) 

template< typename Elem, typename Traits > 
std::basic_ostream< Elem, Traits >& operator<<(std::basic_ostream< Elem, Traits >& out, Fraction const& output) 
5

귀하의 일부처럼 정의 사업자로, 스트림의 모든 종류의 작업 것 그런 다음 함수 내부에서 std::string으로 추출한 다음 관련 데이터를 inputFraction 개체에 저장합니다. 대신 모든 구문 분석을 수행해야 당신이 아니라 입력 std::string을 복용보다는 Fraction 클래스의 오버로드를 분석하고 해석 매개 변수에서 새 Fraction 목적을 시도하려는 operator>> 함수의

1

, 오버플로 된 함수 operator>> 안에있는 사용자의 입력 값이 이미 입력 스트림에 직접 액세스 할 수 있기 때문입니다. 즉, 당신이하고있는 일은 중복되고 조금 혼란 스럽습니다 ... Fraction 개체에 대해 operator>> 오버로드가 발생하면 전체 사용자 입력을 받아 해당 사용자 입력에서 Fraction 개체를 만들어야합니다.Fraction 개체가 완료되기 전에 몇 단계를 거치지 마십시오.

그래서 당신은 같은 것을 원하는 것 :

//set values of Fraction object through pass-by-reference 
istream& operator>>(istream& in,Fraction& input); 

을하고 좋아 사용

Fraction new_fraction_obj; //has only default-constructor-set values 
std::cin >> new_fraction_obj; //now will have the user-input values after call 

마지막으로, 당신이 찾아 사용자 입력을 구문 분석하는 동안 경우 올바르게 포맷되지 않은 경우, 또는 잘못된 유형 등이있는 경우 ios::setstate()을 호출하여 istream 객체의 오류 비트를 설정하면 스트림 사용자가 입력에 문제가 있음을 감지하고 참조로 전달되는 Fraction 객체를 찾습니다. ~ 안에 유효하지 않은 상태.

2

다른 사람들이 이미 문제를 설명 했으므로 여기에 데모 코드에 대한 설명이 나와 있습니다.

class Fraction { 
int top, bottom; 
public: 
    Fraction(int top_, int bottom_) :top(top_), bottom(bottom_) {} 
    Fraction(const Fraction& rhs) : top(rhs.top), bottom(rhs.bottom) {} 
    Fraction& operator=(const Fraction& rhs) {top=rhs.top; bottom=rhs.bottom; return *this} 

    int get_numerator() {return top;} 
    int get_denomerator() {return bottom;} 
    double get_value() {return double(top)/bottom;} 
}; 

istream& operator>>(istream& in, Fraction& input) { 
    int numer; 
    int denom=1; 
    int whole=0; 
    int peekchar; 
    bool valid=false; 

    in >> numer; //get the numerator 
    peekchar = in.peek(); //peek at next character 
    if(in && peekchar == '+') { //if next character is a + 
     in.get(); //skip the + character 
     whole = numer; //then first character was whole, not numerator 
     in >> numer; //get the real numerator 
     valid = true; 
     peekchar = in.peek(); 
    } 
    if(in && peekchar == '/') { //if next character is a/
     in.get(); //skip the/character 
     in >> denom; //get the denominator 
     valid = true; 
    } 
    if (in || valid) { //if we succeeded in reading 
     if (denom == 0) 
      denom = 1; 
     numer += (whole*denom); 
     input = Fraction(numer, denom); 
    } 
    return in; 
} 
ostream& operator<<(ostream& in,const Fraction& output) { 
    return in << output.get_numerator() << '/' << output.get_denominator(); 
} 
int main() { 
    Fraction my_fract; 
    cout << "Enter a fraction\n"; 
    cin >> my_fract; 
    cout << "you entered " << my_fract; 
} 
}