这是一个函数,它检查用户输入的函数的名称到我正在进行的解释器/解析器中,将它与函数数组进行比较,并执行相应的C ++函数。只要用户输入正确的函数名称,它就可以正常工作,但是如果没有用户输入的名称功能,解释器会以一些无法解释的运行时错误结束,即使我将其编程为打印“未定义的函数”然后继续解析循环:
void parser::eval_cmd(std::string& exp, pro::command fset[])
{
expr = exp;
exp_ptr = (char*) expr.c_str();
bool found = false;
for (int i = 0; i < (int)sizeof(fset); i++)
{
if (fset[i].check(expr))
{
found = true;
exp_ptr = (char*)expr.c_str() + (fset[i].name.size() - 1);
if (fset[i].cmd)
fset[i].cmd(eval_args());
break;
}
}
if (!found) err::show(err::UNDEFINED);
}
我究竟做错了什么?
答案 0 :(得分:7)
你做错了是(int)sizeof(fset)
。这将为您提供指针的大小(以字节为单位),而不是传入的fset
数组中的元素数。
您需要一些其他方法来确定数组中有多少元素,可能是通过传入另一个arg,使用std::
容器而不是数组,或者使用NULL来终止数组。
例如,稍微更改您的函数定义:
void parser::eval_cmd(std::string& exp, const std::vector<pro::command>& fset)
{
...
for (int i = 0; i < fset.size(); i++)
{
...
代码的其余部分保持不变。
<小时/> 编辑:我最好的建议是使用
std::map<string, pro::command>
并允许map
管理查找算法,或std::vector<pro::comand>
并使用上述算法不变。您可以测量内存性能,但我希望vector
超过数组的唯一开销是静态数组上new
ed数组的开销。
如果你的结论是不使用标准容器,这是我的第二好建议:
void parser::eval_cmd(std::string& exp, pro::command fset[], size_t count)
{
...
for (int i = 0; i < count; i++)
{
假设调用者知道(或可以确定)fset数组中的元素数量。 (请参阅Can this macro be converted to a function?获取相关帮助。)
答案 1 :(得分:2)
我看到一个即时错误,虽然没有看到更多的代码,我
不能确定症状可能是什么。你是循环控制
条件使用sizeof(fset)
:fset
是一个指针,因此值将
永远是相同的(通常是4或8,取决于你是否在32岁
位或64位模式)。我fset
的成员较少,那么你就会有
未定义的行为,如果它有更多,你将不会检查任何
后来的功能。
我的建议是std::map
使用fset
,然后跳过
完全循环。
答案 2 :(得分:0)
..., pro::command fset[])
相当于
..., pro::command *fset)
因此,当您执行sizeof(fset)
时,它会计算sizeof(command*)
而非实际sizeof(command)
。如果您不知道fset[]
大小,那么您可以编写template
包装器:
template<unsigned int SIZE> // <--- finds the sizeof fset
void parser::eval_cmd_array(std::string& exp, pro::command (&fset)[SIZE])
{
void parser::eval_cmd(exp, fset, SIZE); // <--- pass the size as 3rd param
}
现在你的原始函数中有数组大小;
void parser::eval_cmd(std::string& exp, pro::command fset[], unsigned int sizeof_fset)
{ //^^^^^^^^^^^^^^^^^^^^^^^^^
//...
for (unsigned int i = 0; i < sizeof_fset; i++)
//... ^^^^^^^^ let it be unsigned :)
}