超载>>对于分数类 C++

发布于 2024-12-08 03:24:28 字数 623 浏览 0 评论 0原文

我正在尝试重载 instream 运算符 >>对于分数类。我创建了一个函数,可以从用户处获取字符串并将其解析为我的 Fraction 类的正确参数,但我不确定如何在我的 >> 中实现它重载功能。

用户可以输入三种类型的分数: 1. 整数(例如5) 2.带分数(如2+4/5) 3. 常规分数(例如 1/2)

我的方法是在主函数中接受用户输入的字符串形式,解析它以获取有效的 Fraction 类参数,然后将这个新创建的分数对象返回到流。我只是不知道该怎么做。

在我的运算符重载定义中,我有这样的:

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

但是如果我接受一个字符串,那么这里参数的类型不应该是字符串吗?我只是对那部分感到非常困惑。然后我想返回一个 Fraction 对象。这是处理整数的示例。

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

我走在正确的轨道上吗?

I'm trying to overload the instream operator >> for a fraction class. I've created a function that can take a string from the user and parse it into the proper arguments for my Fraction class but I'm unsure how to implement this in my >> overloading function.

There are three types of fractions that a user can input:
1. whole numbers (e.g. 5)
2. mixed numbers (e.g. 2+4/5)
3. regular fractions (e.g. 1/2)

My approach was to accept this input as a string from the user in the main function, parse it to get the valid Fraction class parameters, then return this newly created fraction object to the stream. I'm just not sure how to do this.

In my operator overloading definition, I have this:

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

But if I'm accepting a string, shouldn't the type of the parameter here be a string? I'm just very confused about that part. I want to then return a Fraction object. Here's an example of handling whole numbers.

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

Am I on the right track here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

颜漓半夏 2024-12-15 03:24:28

您的分数需要作为输出参数,因此它不能是 const:

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

然后在函数中,您将提取到 std::string 中,然后对其进行解析,并将相关数据存储到您的函数中输入 Fraction 对象。

Your fraction is needed to be an output parameter so it can't be const:

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

Then inside your function, you would extract into a std::string which you then parse, and store the relevant data into your input Fraction object.

所有深爱都是秘密 2024-12-15 03:24:28

这就是我对演示代码所做的事情,因为其他人已经解释了问题。

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

Here's what I would do for demo code since everyone else already explained the problems.

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;
}
}
绅士风度i 2024-12-15 03:24:28

您应该使用,而不是字符串。如果用户想要向字符串输入/输出,则始终可以使用stringstream。请注意,您的定义

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

在流语言中意味着从 istream 中提取 Fraction,因此您的输入参数不应该是 const。另一方面,要将 Fraction 输出到 ostream,需要声明

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

另外,最后要注意的是 istream/ostream 是特定的实现,使用 char 作为元素和默认特征。更通用的实现适用于任何类型的流,其运算符定义如下

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)

You should be working with streams, not strings. If the user wants to input/output to/from a string it can always use an stringstream. Note that your definition is

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

which in stream language means extract a Fraction from a istream, so your input parameter shouldn't be const. On the other hand, to output a Fraction to an ostream one would declare

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

Also, one final note is that istream/ostream are specific implementations that work with char as element and the default traits. A more general implementation would work with any kind of stream, with operators defined like this

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)
早乙女 2024-12-15 03:24:28

对于要为 Fraction 类重载的 operator>> 函数,而不是获取输入 std::string,请对其进行解析,然后尝试从解析的参数创建一个新的 Fraction 对象,您应该在 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

最后,如果在尝试解析用户输入时发现它的格式不正确,或者类型错误等,请设置 的失败位istream 对象通过调用 ios::setstate() 以便流的用户可以检测到输入有问题,并且 Fraction 对象正在通过引用传递处于无效状态。

For your operator>> function that you want to overload for the Fraction class, rather than taking an input std::string, parse it, and then attempt to make a new Fraction object from the parsed parameters, you should instead be doing all the parsing of the user's input inside the operator>> overloaded function, since that already has direct access to the input stream. In other words what you're doing is redundant, and a bit confusing ... with the operator>> overload for a Fraction object, the intention should be to take the entire user input and create a Fraction object from that user input ... not go through a couple steps before the Fraction object is complete.

So you would want something like:

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

and use it like:

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

Finally, if while attempting to parse the user input you find that it is not correctly formatted, or is the wrong types, etc., set the fail-bit of the istream object by calling ios::setstate() so that the user of the stream can detect there was something wrong with the input, and the Fraction object that is being passed-by-reference is in an invalid state.

捶死心动 2024-12-15 03:24:28

标准方法是将自定义输入操作分解为多个组成部分:

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 &) 函数来确定是否一个字符串表示一个有效的分数,如果是,则将分子和分母放入两个相应的变量中。

The standard approach would be to break your custom input operation up into constituents:

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
}

The crux is to write the parse_token(const std::string &, int &, int &) function that determines whether a string represents a valid fraction, and if yes puts the numerator and denominator in the two respective variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文