限制cin。操作员到特定范围

时间:2014-05-07 17:55:14

标签: c++

如果我想限制cin运算符的范围怎么办?类似下面的代码,我从用户那里获取输入,现在输入必须小于100,即如果用户输入标记> 100它应该报告错误信息。

using namespace std;

void GetInput(const std::string &prompt, int &i, int max)
{
    bool valid = false;
 do
  {
    cout << prompt;
    if (cin >> i && i < max)
    {
        valid = true;
    }
    else
    {
        cout << "Error: Input must be less than " << max << "." << endl;
    }
} while (!valid);

}

class Marks
{
private:
int elec, prog, math, perc = NULL; 

public:

void input()
{

        cout << "enter the marks obtained in Mathematics = ";
        cin >> math;
        cout << "enter the marks obtained in Programming = ";
        cin >> prog;
        cout << "enter the marks obtained in Electronics = ";
        cin >>elec;


} 

void avg()
{
    double avg = NULL;
    avg = (math + prog + elec) / 3;
    cout << "Average = " << avg << endl;
}


void Perc()
{

    perc = ((math + elec + prog)*100) / 300;
    cout << "The Percentage = " << perc <<" %"<< endl;

}


 void grade()
{

     if (perc >= 79)
     {
         cout << "A" << endl;
     }
     else if ((perc > 66) && (perc < 80))
         cout << "B" << endl;

    else if (perc < 66)
        cout << "C" << endl;
}

};

int main(void)
{
    Marks m;
    int maths, prog, elec;
    GetInput("enter the marks obtained in Mathematics = ", maths, 100);
    GetInput("enter the marks obtained in Programming = ", prog, 100);
    GetInput("enter the marks obtained in Electronics = ", elec, 100);

    m.Perc();
    m.avg();
    m.grade();
    system("PAUSE");
    return 0;

}

4 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

int maths;
bool valid = false;
do
{
    cout << "Enter the marks obtained in Mathematics = ";
    if (cin >> maths && maths < 100)
    {
        valid = true;
    }
    else
    {
        cout << "Error: Input must be less than 100." << endl;
    }
} while (!valid);

这将确保输入既是有效的整数值又小于100,只有在输入有效输入后才终止循环。

一般来说:

void GetInput(const std::string &prompt, int &i, int max)
{
  bool valid = false;
  do
  {
      cout << prompt;
      if (cin >> i && i < max)
      {
          valid = true;
      }
      else
      {
          cout << "Error: Input must be less than " << max << "." << endl;
      }
  } while (!valid);
}

并在您的代码中调用它:

int maths, prog, elec;
GetInput("enter the marks obtained in Mathematics = ", maths, 100);
GetInput("enter the marks obtained in Programming = ", prog, 100);
GetInput("enter the marks obtained in Electronics = ", elec, 100);

答案 1 :(得分:0)

在这种情况下,一些运算符重载可以隐藏可重用辅助类的复杂性:

template<typename TMin, typename TMax>
struct unbound_limit_range
{
    const TMin lower_limit;
    const TMax upper_limit;
};

template<typename TMin, typename TMax>
class bound_limit_range
{
    std::istream& the_stream;
    const unbound_limit_range<TMin, TMax> the_limits;
public:
    bound_limit_range(istream& p_stream, const unbound_limit_range<TMin, TMax>& p_limits)
         : the_stream(p_stream), the_limits(p_limits)
    {}

    template<typename TVar>
    istream& operator>>(T& dest)
    {
        while (true) {
            if (!(the_stream >> dest)) return the_stream;

            if (dest < the_limits.lower_limit) {
                std::cout << "Value too low\n";
            }
            else if (dest > the_limits.upper_limit) {
                std::cout << "Value too high\n";
            }
            else {
                return the_stream;
            }

            std::cout << "Try again: " << std::flush;
        }
    }
};

template<typename TMin, typename TMax>
bound_limit_range<TMin, TMax> operator>>(std::istream& stream, const limit_range<TMin, TMax>& limits) { return { stream, limits }; }

template<typename TMin, typename TMax>
unbound_limit_range<TMin, TMax> limit_range(TMin lower, TMax upper) { return { lower, upper }; }

相当混乱,但你可以简单地写:

cout << "enter the marks obtained in Mathematics = ";
cin >> limit_range(0, 100) >> maths;
cout << "enter the marks obtained in Programming = ";
cin >> limit_range(0, 100) >> prog;
cout << "enter the marks obtained in Electronics = ";
cin >> limit_range(0, 100) >> elec;

if (cin) { /* all succeeded */ }

答案 2 :(得分:0)

您可以创建一个为您执行此操作的操纵器:

#include <iostream>

template<int, int>
struct input_range_impl
{
    input_range_impl(int& val) : val_(val)
    {
    }

    template<int I, int U>
    friend std::istream& operator>>(std::istream&, const input_range_impl<I, U>&);
private:
    int& val_;
};

template<int I, int U>
std::istream& operator>>(std::istream& is, const input_range_impl<I, U>& manip)
{
    if (!(is >> manip.val_) || !(I <= manip.val_ && manip.val_ >= U))
        is.setstate(std::ios_base::failbit);
    return is;
}

template<int I, int U>
input_range_impl<I, U> input_range(int& val)
{
    return { val };
}

void input()
{
    std::cout << "enter the marks obtained in Mathematics = ";
    std::cin >> input_range<0, 100>(maths);
    std::cout << "enter the marks obtained in Programming = ";
    std::cin >> input_range<0, 100>(prog);
    std::cout << "enter the marks obtained in Electronics = ";
    std::cin >> input_range<0, 100>(elec);
}

答案 3 :(得分:0)

除了我的另一个答案,这是设置范围的另一种方法,但将语义合并到流的语言环境中安装的std::num_get<facet>中。它有点复杂,但它会覆盖流的提取整数的默认行为并使用自定义范围检查代码:

#include <iostream>
#include <utility>

int input_range() { static int idx = std::ios_base::xalloc(); return idx; }

void erase_range(std::ios_base::event evt, std::ios_base& str, int index)
{
    if (evt == std::ios_base::erase_event)
    {
        delete static_cast<std::pair<int, int>*>(str.pword(index));
    }
}

class num_get : public std::num_get<char>
{
public:
    iter_type do_get( iter_type in, iter_type end, std::ios_base& str, 
                      std::ios_base::iostate& err, long& v ) const
    {
        long temp;
        in = std::num_get<char>::do_get(in, end, str, err, temp);

        if (in != end)
            err |= std::ios_base::failbit;

        void*& p = str.pword(input_range());

        if (p)
        {
            auto values = *static_cast<std::pair<int, int>*>(p);
            if (!(values.first <= temp && temp <= values.second))
            {
                err |= std::ios_base::failbit;
            } else
                v = temp;
        }
        return in;
    }
};

template<int I, int J>
std::istream& set_range(std::istream& is)
{
    void*& p = is.pword(input_range());
    erase_range(std::ios_base::erase_event, is, input_range());

    if (is)
    {
        p = new std::pair<int, int>(I, J);

        if (!dynamic_cast<const num_get*>(
                &std::use_facet<std::num_get<char>>(is.getloc())))
        {
            is.imbue(std::locale(is.getloc(), new num_get));
            is.register_callback(&erase_range, input_range());
        }
    }
    return is;
}

你可以像这样使用它:

void input()
{
    std::cin >> set_range<0, 100>;

    std::cout << "enter the marks obtained in Mathematics = ";
    if (!(std::cin >> maths))
        std::cout << "Error!";
    std::cout << "enter the marks obtained in Programming = ";
    // so on...
    std::cout << "enter the marks obtained in Electronics = ";
    // and so forth...
}