C++ 中无法解释的错误解析器源代码

发布于 2024-12-05 11:07:07 字数 689 浏览 1 评论 0原文

该函数检查用户输入到我正在制作的解释器/解析器中的函数名称,将其与函数数组进行比较,并执行相应的 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);
}

我到底做错了什么?

This is the function that checks the name of the function entered by the user into the interpreter/parser I am making, compares it with the array of functions, and executes the corresponding C++ function. It works fine as long as the user enters a correct function name, but the interpreter ends with some unexplained runtime error if there is no function of the name the user entered, even though I programmed it to print "Undefined Function" and then carry on the parse loop:

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);
}

What exactly am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爺獨霸怡葒院 2024-12-12 11:07:07

你做错的是(int)sizeof(fset)。这给出了指针的大小(以字节为单位),而不是传入的 fset 数组中的元素数量。

您需要一些其他方法来确定数组中有多少元素,可能是通过传入另一个参数、使用 std:: 容器而不是数组,或者以 NULL 终止数组。

例如,稍微更改函数定义:

void parser::eval_cmd(std::string& exp, const std::vector<pro::command>& fset)
{
    ...

    for (int i = 0; i < fset.size(); i++)
    {
        ... 

代码的其余部分保持不变。


EDIT: My best advice is to use std::map<string, pro::command> and allow map to manage the lookup algorithm, or std::vector<pro::comand> and use the above algorithm unchanged. You can measure the memory performance, but I expect that the only overhead of vector over array is the overhead of a newed array over a static array.

如果您确实得出不使用标准容器的结论,这是我的第二个最佳建议:

void parser::eval_cmd(std::string& exp, pro::command fset[], size_t count)
{
    ...

    for (int i = 0; i < count; i++)
    {

大概调用者知道(或可以确定) fset 数组中的元素数量。 (参见这个宏可以转换为函数吗?< /a> 寻求帮助。)

What you are doing wrong is (int)sizeof(fset). That gives you the size of a pointer, in bytes, not the number of elements in the passed-in fset array.

You need some other way of determining how many elements are in the array, perhaps by passing in another arg, by using an std:: container instead of an array, or by NULL-terminating the array.

For example, changing your function definition slightly:

void parser::eval_cmd(std::string& exp, const std::vector<pro::command>& fset)
{
    ...

    for (int i = 0; i < fset.size(); i++)
    {
        ... 

The remainder of the code is unchanged.


EDIT: My best advice is to use std::map<string, pro::command> and allow map to manage the lookup algorithm, or std::vector<pro::comand> and use the above algorithm unchanged. You can measure the memory performance, but I expect that the only overhead of vector over array is the overhead of a newed array over a static array.

If you do reach the conclusion not to use standard containers, here is my 2nd-best advice:

void parser::eval_cmd(std::string& exp, pro::command fset[], size_t count)
{
    ...

    for (int i = 0; i < count; i++)
    {

Presumably the caller knows (or can determine) the number of elements in the fset array. (See Can this macro be converted to a function? for help with that.)

眼角的笑意。 2024-12-12 11:07:07

我立即看到一个错误,尽管没有看到更多代码,但我
不能确定症状是什么。你是循环控制
条件使用sizeof(fset)fset是一个指针,所以该值将
始终相同(通常为 4 或 8,具体取决于您是否处于 32
位或 64 位模式)。我 fset 的成员较少,那么你就会有
未定义的行为,如果有更多,您将不会检查任何
以后的功能。

我的建议是使用 std::map 作为 fset,并跳过
完全循环。

I see an immediate error, although without seeing more of the code, I
can't say for sure what the symptoms might be. You're loop control
condition uses sizeof(fset): fset is a pointer, so the value will
always be the same (typically 4 or 8, depending on whether you are in 32
bit or 64 bit mode). I fset has less members, then you'll have
undefined behavior, and if it has more, you'll not check for any of the
later functions.

My recommendation would be to use an std::map for fset, and skip the
loop completely.

三生殊途 2024-12-12 11:07:07
..., 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 :)
}
..., pro::command fset[])

is equivalent to

..., pro::command *fset)

So when you do, sizeof(fset), it calculates the sizeof(command*) and not the actual sizeof(command). If you are unaware of the fset[] size then you can write a template wrapper:

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
}

Now you have got the array size in your original function;

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 :)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文