题
所以我目前正在学习 C++,并决定制作一个程序来测试我迄今为止所学到的技能。现在在我的代码中,我想检查用户输入的值是否是双精度值,如果不是双精度值,我将放置一个 if 循环并要求他们重新输入它。我遇到的问题是如何检查用户输入的变量类型,例如,如果用户输入字符或字符串,我可以输出错误消息。这是我的代码:
//cubes a user entered number
#include <iostream>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
double user;
cin >> user; //user entering the number
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
编辑:我不得不说我刚刚开始,对您的代码没有丝毫线索,但我会查看您的链接。顺便说一句,我还没有学会如何使用模板,我正在学习处理数据,只有我的 C++ Primer Plus 第 5 版中的第 3 章。
解决方案
有是检查是否一个字符串确实包含标准库内的双没有合适的方法。你可能想使用升压。下面的解决方案是由配方3.3启发 C ++食谱:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
double cube(double n);
int main()
{
while(true)
{
cout << "Enter the number you want to cube: ";
string user;
cin >> user;
try
{
// The following instruction tries to parse a double from the 'user' string.
// If the parsing fails, it raises an exception of type bad_lexical_cast.
// If an exception is raised within a try{ } block, the execution proceeds
// with one of the following catch() blocks
double d = lexical_cast <double> (user);
cout << "The cube of " << d << " is " << cube(d) << "." << endl;
break;
}
catch(bad_lexical_cast &e)
{
// This code is executed if the lexical_cast raised an exception; We
// put an error message and continue with the loop
cout << "The inserted string was not a valid double!" << endl;
}
}
return 0;
}
double cube (double n)
{
return n*n*n;
}
其他提示
安全的 C++ 方式
您可以使用以下方法为此定义一个函数 std::istringstream
:
#include <sstream>
bool is_double(std::string const& str) {
std::istringstream ss(str);
// always keep the scope of variables as close as possible. we see
// 'd' only within the following block.
{
double d;
ss >> d;
}
/* eat up trailing whitespace if there was a double read, and ensure
* there is no character left. the eof bit is set in the case that
* `std::ws` tried to read beyond the stream. */
return (ss && (ss >> std::ws).eof());
}
为了帮助您弄清楚它的作用(简化了一些要点):
- 创建使用给定字符串初始化的输入字符串流
- 使用以下方法从中读取双精度值
operator>>
. 。这意味着跳过空格并尝试读取双精度值。 - 如果无法读取双精度值,如
abc
流设置 失败-少量。请注意,像这样的情况3abc
将会成功并且将会 不是 设置失败位。 - 如果设置了失败位,
ss
评估为零值,这意味着 错误的. - 如果读取了双精度值,我们会跳过尾随空白。如果我们位于流的末尾(请注意
eof()
将返回 真的 如果我们试图读到最后。std::ws
正是这样做的),eof
将返回 true。请注意,此检查可确保3abc
不会通过我们的检查。 - 如果两种情况,则右侧和左侧
&&
评估为 真的, ,我们向调用者返回 true,表明给定的字符串是双精度型。
类似的,你检查 int
和其他类型。如果您知道如何使用模板,那么您也知道如何将其推广到其他类型。顺便说一句,这正是 boost::lexical_cast
提供给您。一探究竟: http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm.
C 方式一
这种方式有优点(速度快),但也有主要缺点(不能使用模板泛化,需要使用原始指针):
#include <cstdlib>
#include <cctype>
bool is_double(std::string const& s) {
char * endptr;
std::strtod(s.c_str(), &endptr);
if(endptr != s.c_str()) // skip trailing whitespace
while(std::isspace(*endptr)) endptr++;
return (endptr != s.c_str() && *endptr == '\0');
}
strtod
将设置 endptr
到处理的最后一个字符。在我们的例子中,这是终止空字符。如果未执行转换,则 endptr 设置为给定字符串的值 strtod
.
C 方式二
有人可能会认为 std::sscanf
就可以了。但监督某些事情很容易。这是正确的方法:
#include <cstdio>
bool is_double(std::string const& s) {
int n;
double d;
return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 &&
n == static_cast<int>(s.size()));
}
std::sscanf
将返回转换后的项目。尽管标准规定 %n
不包括在该计数中,几个来源相互矛盾。比较一下是最好的 >=
使其正确(请参阅手册页 sscanf
). n
将设置为已处理字符的数量。它与字符串的大小进行比较。两个格式说明符之间的空格用于可选的尾随空格。
结论
如果您是初学者,请阅读 std::stringstream
并以 C++ 方式进行。在您对 C++ 的一般概念感到满意之前,最好不要乱用指针。
sscanf的可以做你想做的;它返回正确处理参数的个数。这应该让你开始:
//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
string user;
cin >> user; //user entering the number
// Convert the number to a double.
double value;
if(sscanf(user.c_str(), "%lf", &value) != 1)
{
cout << "Bad! " << user << " isn't a number!" << endl;
return 1;
}
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
发布在其他的答案其他方法都有各自的优点和缺点。这其中有尾随字符的问题,而不是“C ++” - 。ÿ
我不得不说,我刚开始并没有丝毫的有关代码的线索,但我会检查你的链接。顺便说一句,我还没有学会如何使用模板还没有,我正在学习有关数据处理,只有第3章在我的C ++的Primer Plus第五版。
可以退回到C和使用的strtod
您程序在一个字符串中读取信息,然后将其传递给试图将字符串转换成双重的功能。
bool is_double(const char* strIn, double& dblOut) {
char* lastConvert = NULL;
double d = strtod(strIn, &lastConvert);
if(lastConvert == strIn){
return false;
} else {
dblOut = d;
return true;
}
}