我必须编写一个程序,要求用户输入一个数字,如果输入为零,则打印输出为0,如果输入负数或正数,则打印出他们输入的数字负数或正数。我有它所以它不接受字母,逗号等。但我无法弄清楚如何让这个不接受小数?我有什么线索可以做到这一点?除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;
}
答案 0 :(得分: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
从输入中获取所有文本,而不是仅仅停留在无法转换为您请求的格式的第一个字符(例如int
)。它也为你摆脱了任何不方便的尾随\n
。
std::stoi
执行从std::string
到int
的转换。阅读docs,如果你不小心,可以抛出异常!它返回pos
中第一个未转换字符的位置。如果pos
小于line
的长度,则表示某处的某个地方不属于int
。
答案 1 :(得分:0)
除了上一个答案之外,您还可以选择创建自己的std::num_get<char>
方面,以便将自定义输入解析无缝集成到IOStreams界面中。
如果您在读取整数时碰巧输入浮点文字,则流仍将尽可能多地解析字符,只要这些字符可用于您要提取的数据类型即可。当流找到流的结尾,空格字符或不符合该类型的格式要求的字符时,它才会停止读取。在我们的例子中,流将找到字符.
,然后停止阅读。
结果是即使部分输入已被消耗,读取也被认为是成功的。然而,下一个读取将不成功,因为下一个字符是.
,它在整数中不可用。
这是我们将用于定制我们的方面的信息。在读取输入后,我们只需检查下一个字符是否为小数点。如果是,您有几个选项来报告错误:
你可以......
输出错误消息
输出错误消息对于控制台用户来说是最方便的,但不符合IOStream的设计。当检测到错误输入时,流不会向控制台输出错误消息,因此您的方面也不应该。
抛出异常
您可以抛出异常,但请注意它们不会在流外传播。这是因为默认情况下编程流不会抛出异常。相反,只要检测到异常,它们就会在流中设置std::ios_base::badbit
。您必须在执行输入之前或之后在流上设置exceptions()
掩码以捕获异常。另一个警告是,只有std::ios_base::failure
从流中抛出,所以你只能抓住它。
设置流状态
设置流状态对于facet的用户最有意义,并且与IOStream的设计保持一致。这样,您就不必彻底改变使用流的方式。只需检查流状态下输入是否成功,就像使用普通方面一样自然而然。
设置流状态是我们将在以下代码中使用的方法:
#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;
}
};
要在流中设置此方面,请将其安装到区域设置中,并且&#34; imbue&#34;该区域设置进入流。像这样:
// 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);
完成后无需删除构面。这由包含它的语言环境的析构函数处理。
如果你想获得不同的行为,应该在实际使用流之前完成区域设置。