我正在编写一个程序,将一个parathensized表达式转换为数学表达式,并对其进行评估。我已经写了计算位。
我正在为操作数使用堆栈,并为数字使用队列。向堆栈添加操作数不是问题,但我需要确定输入字符是否为整数,如果是,则将其添加到队列中。这是一些代码:
cout << "Enter the numbers and operands for the expression";
string aString;
do
{
cin >> aString
if (aString = int) // function to convert to read if int, convert to int
{
c_str(...);
atoi(...);
istack.push(int);
}
}
这就是我现在被困住的地方。我知道我将不得不使用c_str和atoi将其转换为int。我采取了错误的做法吗?
答案 0 :(得分:6)
使用流的.fail()
方法。
如果您也需要字符串,则可以先读取字符串,然后尝试使用stringstream
对象将字符串转换为整数,并检查字符串流上的.fail()
以查看是否转换可以做到。
cin >> aString;
std::stringstream ss;
ss << aString;
int n;
ss >> n;
if (!ss.fail()) {
// int;
} else {
// not int;
}
答案 1 :(得分:2)
如果你期望一个整数,我会使用boost::lexical_cast
。
std::string some_string = "345";
int val = boost::lexical_cast<int>(some_string);
如果它无法转换为整数,它将抛出。 performance非常合理,它可以使您的代码非常干净。
我不知道任何非投掷版本。您可以使用类似的东西,但我通常会尽量避免让异常控制程序流。
bool cast_nothrow(const std::string &str, int &val) {
try {
val = boost::lexical_cast<int>(str);
return true;
} catch (boost::bad_lexical_cast &) {
return false;
}
}
编辑:
我不建议您对所描述的结构进行整数验证检查。好的功能可以做到一件好事。
通常你需要一个更正式的语法分析器来处理这些事情。我诚实的建议是在您的项目中嵌入脚本语言或库。这是非常重要的,所以让其他人来做这项艰苦的工作。
如果我真的试图实现你的建议,我可能会做一个基于堆栈的解决方案,将括号级别保持在自己的堆栈框架中。最简单的事情就是硬编码简单的运算符(括号,加法,子等),并假设其余部分都是数字。
最终,您希望将所有内容分解为某种表达类型。它可能看起来像这样:
struct Expression {
virtual ~Expression() {}
virtual float value() const = 0;
};
struct Number : public Expression {
virtual float value() const {return val;}
float val;
};
struct AdditionOper : public Expression {
virtual float value() const {return lhs->value() + rhs->value();}
boost::shared_ptr<Expression> lhs;
boost::shared_ptr<Expression> rhs;
};
我首先解析括号,然后确定表达式的顺序。然后我根据数值操作数拆分所有内容并开始将它们放在表达式中。然后你会遇到像3 + 4 * 6
这样的案件,需要一些小心才能使操作顺序正确。
答案 2 :(得分:2)
我可能会被C ++纯粹主义者搞砸了。
但是,有时候C ++库比C库更有用。我提供这个 那里的C开发人员的解决方案。和C ++开发人员一样,不介意使用其中的一些 C库的功能。
整个检查和转换可以使用sscanf函数在1行C中完成。
int intval;
cin >> aString
if (sscanf(aString.c_str(), "%d", &intval)){
istack.push(intval);
}
sscanf返回匹配和分配的输入参数的数量。所以在这种情况下,它正在寻找一个标准的signed int值。如果sscanf返回1,则它成功分配了值。如果它返回0,那么我们没有int。
答案 3 :(得分:2)
您可以运行将数字的字符串表示形式转换为double的函数并查看是否存在错误,或者您可以查看字符串的内容并查看它是否与数字的模式匹配然后执行转换。
您可以使用boost::lexical_cast<double>()
或std::stod()
(C ++ 11),其中报告错误的异常,或istringstream提取器,其中通过设置失败位或C转换函数报告错误通过设置全局(线程本地,而非)变量errno
来报告错误。
try {
istack.push_back(std::stod(aString));
} catch(std::invalid_argument &e) {
// aString is not a number
}
或
errno = 0;
char const *s = aString.c_str();
char *end;
double result = strtod(s,&end);
if(EINVAL==errno) {
// the string is not a number
} else {
istack.push_back(result);
}
第二个选项的实现可能会使用正则表达式来查看字符串是否与您用于数字的模式匹配,如果匹配,则运行转换函数。以下是浮点值可能出现的模式示例:
std::regex pattern("[+-]?(\d*.\d+|\d+.?)([eE][+-]?\d+)?");
if(std::regex_match(aString,pattern)) {
istack.push_back(std::stod(aString));
} else {
// aString is not a number
}
此外,这可能与您无关,但大多数用于将字符串转换为数字的内置方法都将以某种方式对区域设置敏感。将自己与此隔离的一种方法是使用您创建的字符串流并使用经典语言环境填充。
答案 4 :(得分:1)
我猜C ++(没有提升)方式就是这样:
do
{
std::stringstream ss;
std::string test;
cin >> test;
ss << test;
int num;
if (ss >> num) // function to convert to read if int, convert to int
{
std::cout << "Number : " << num << "\n";
}
}while(true); // don't do this though..
答案 5 :(得分:0)
您是否可以使用ctype.h
http://www.cplusplus.com/reference/clibrary/cctype/。我以前用过这个并没有遇到麻烦。
答案 6 :(得分:0)
特别是如果您正在进行基数为10的输入,我发现最明显的事情是读取字符串,然后检查它是否只包含有效字符:
string s;
cin >> s;
if(strrspn(s.c_str(), "0123456789")==s.length()){
//int
} else{
//not int
}