-2

我必须编写一个程序,要求用户输入一个数字,如果他们输入零,它将打印出他们输入了零,如果他们输入负数或正数,它将打印出他们输入了负数或正数。我有它,所以它不接受字母和逗号等。但我不知道如何让这个不接受小数?任何线索我怎么能做到这一点?除了 cplusplus.com 之外,任何具有良好 c++ 参考的好网站

#include <iostream>
#include <string>
#include <limits>
#include <cmath>
#include <iomanip>
#include <cstdlib>

using namespace std;

    int getInt()
    {
    int choice=0;
    while (!(cin >> choice))
        {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(),'\n');
        cout << "Please input a valid integer: " << '\n';
        }
    return (choice);
    }

int print_zero()
{
 cout << "The number you entered is a zero. " << '\n';
 return 0;
}

int print_negative()
{
 cout << "You entered a negative number. " << '\n';
 return 0;
}

int print_positive()
{
    cout << "You entered a positive number. " << '\n';
    return 0;
}

int main ()
    {

    cout << "your number please:-" << '\n';
    int choice = getInt();

    if (choice == 0)
    {
        print_zero();
    }

    if (choice < 0)
    {
        print_negative();
    }

    if (choice > 0)
    {
        print_positive();
    }

cout << endl << "All done! Nice!!" << endl;

return 0;
}
4

2 回答 2

0

除了上一个答案之外,您还可以选择创建自己的std::num_get<char>facet 以将自定义输入解析无缝集成到 IOStreams 接口中。

如果您在读入整数时碰巧输入了浮点文字,则流仍将解析尽可能多的字符,只要这些字符可以在您要提取的数据类型中使用。当流找到流的结尾、空白字符或不符合类型格式要求的字符时,它才会停止读取。在我们的例子中,流将找到字符.然后停止读取。

结果是即使部分输入已被消耗,读取也被认为是成功的。但是,下一次读取将不成功,因为下一个字符是 a .,它在整数中不可用。

这是我们将用于自定义方面的信息。在读取输入后,我们只需检查下一个字符是否为小数点。如果它,您有几个选项来报告错误:

你可以...

  • 输出错误信息

    输出错误信息对控制台用户来说是最方便的,但不符合 IOStreams 的设计。当检测到错误输入时,流不会将错误消息输出到控制台,因此您的方面也不应该。

  • 抛出异常

    您可以抛出异常,但请注意它们不会传播到流之外。这是因为默认情况下流被编程为不抛出异常。相反,std::ios_base::badbit只要检测到异常,它们就会在流中设置。您必须exceptions()在执行输入之前或之后在流上设置掩码以捕获异常。另一个需要注意的是,只有std::ios_base::failure从溪流中抛出,所以你只能抓住它。

  • 设置流状态

    设置流状态对您方面的用户最有意义,并且符合 IOStreams 的设计。这样,您就不必彻底改变使用流的方式。只需在流状态下检查输入是否成功,就像您自然地使用普通方面一样。

设置流状态是我们将在以下代码中使用的方法:

#include <locale>

class num_get : public std::num_get<char>
{
public:
    // Override do_get which is a virtual function in the std::num_get<char>
    // base class. It is called by the public member function get() in the
    // implementation of std::basic_istream<charT>::operator>>(int&)

    // You might want to put this into a helper function and call it in
    // both the signed and unsigned overloads

    iter_type do_get( iter_type it, iter_type end, std::ios_base& str,
                      std::ios_base::iostate& err, long& v ) const
    {
        // Store a locale object for later use.
        std::locale loc(str.getloc());

        // delegate the extraction to the default base class function
        it = std::num_get<char>::do_get(it, end, str, err, v);
        
        // If the extraction succeeded, tell the user if positive or negative,
        // or zero
        if (!(err & std::ios_base::failbit))
        {
            if (v == 0)
                std::cout << "The number you entered is a zero.\n";
            std::cout << "You entered a " <<
                ((v >= 0) ? "positive" : "negative") << " number.\n";
                    
            // Check whether the end has not been met (because of further
            // input that can't be used in a long). And if the first character
            // of that input is a decimal point (or '.' in en_US) then get
            // rid of that input for convenience, and set failbit

            if (it != end && *it == std::use_facet<std::numpunct<char>>(loc).decimal_point())
            {
                // We get rid of that input by calling the base class function
                // again which does all the necessary parsing.

                // Note that if you do not want to get rid of the invalid
                // floating point input, then simply remove these two lines.
                it = std::num_get<char>::do_get(++it, end, str, err, v);
                // Clear out v
                v = 0;
                
                // set failbit
                err |= std::ios_base::failbit;
            }
        }    
        return it;
    }
};

要在流中设置此构面,请将其安装到语言环境中并将该语言环境“灌输”到流中。像这样:

// Create a new locale with std::num_get<char> facet replaced by our custom facet
std::locale new_locale(std::cin.getloc(), new num_get);
// Imbue this new locale into std::cin
std::cin.imbue(new_locale);

完成后无需删除构面。这由持有它的语言环境的析构函数处理。

如果您想获得不同的行为,则应在实际使用流之前完成本地化设置。

Live Example

于 2014-05-20T19:58:46.867 回答
0

一个相当简单的事情是使用类似的东西

std::string line;
std::getline(std::cin, line);

size_t pos;
int x = 0;

try
{
  x = std::stoi(line, &pos);

  if (pos < line.length())
  {
    std::cout << "Warning, non-digit character " << line[pos] << " detected!\n"
    return;
  }
}
catch (std::exception&)
{
  std::cout << "That didn't look like an integer to me.\n";
  return;
}

getline从输入中获取所有文本,而不是仅仅停留在无法转换为您请求的格式的第一个字符(例如 an int)。它也为您摆脱了任何不方便的尾随\n

std::stoi进行从std::string到的转换int。阅读文档,如果您不小心,它可能会引发异常!它返回 中第一个未转换字符的位置pos。如果pos小于 的长度line,则表示其中某处存在不属于 的无效字符int

于 2014-05-20T18:03:15.607 回答