找到你要的答案

Q:Parsing strings of equations in c using scanf

Q:在C使用scanf字符串方程解析

I need to parse input from a user that could be any number of variations: 1+1 4( 3-0 ) =x 1*(3)-8

How do I do this using scanf to get the raw_input, then split out all of the different values and tell either if it is a string ie x = - () or a int?

This is what I was thinking

    char * raw_input;
    scanf("%s",raw_input);

It takes a array of char and then I just need to split and convert into a single elements. What is the best way of doing the input and (splitting and converting)

Thanks

I need to parse input from a user that could be any number of variations: 1+1 4( 3-0 ) =x 1*(3)-8

我怎样使用scanf获得raw_input做这个,然后分裂出所有的不同的价值观可以告诉如果它是一个字符串,即x = -()或一个int?

这就是我的想法

    char * raw_input;
    scanf("%s",raw_input);

它需要一个数组的char,然后我只需要分裂和转换成一个单一的元素。什么是最好的方式做输入和(分裂和转换)

谢谢

answer1: 回答1:

If you want to write your own code, the best way is to define your expression in form of a grammar. To easily parse the grammar, it's best to make it simple.

For example, to parse expressions in the form like this (1+(3*4+x)*y)+1, you could write such a grammar:

Expression -> Addition | null
Addition -> Multiplication RestOfAddition
RestOfAddition -> null | + Addition
Multiplication -> Element RestOfMultiplication
RestOfMultiplication -> null | * Element
Element -> number | variable | ( Expression )

Then in your program, for every non-terminal in this grammar (the ones on the left of ->), you write one function, like this:

ExpTree *Expression(char *exp, int *position)
{
    if (exp[*position])
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = LAMBDA;
        node->value = 0;
        return node;
    }
    else
        return Addition(exp, position);
}

ExpTree *Addition(char *exp, int *position)
{
    ExpTree *node = malloc(sizeof(*node));
    node->type = ADDITION;
    node->left = Multiplication(exp, position);
    node->right = RestOfAddition(exp, position);
    return node;
}

ExpTree *RestOfAddition(char *exp, int *position)
{
    ExpTree *node;
    if (exp[*position] == '+')
    {
        ++*position;
        return Addition(exp, position);
    }
    else
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = LAMBDA;
        node->value = 0;
        return node;
    }
}

Similarly, Multiplication and RestOfMultiplication would be written as functions.

ExpTree *Element(char *exp, int *position)
{
    if (exp[*position] == '(')
    {
        ExpTree *node;
        ++*position;
        node = Expression(exp, position);
        if (!exp[*position] != ')')
             printf("Expected ) at position %d\n", *position);
        else
             ++*position;
        return node;
    }
    else if (exp[*position] == ')')
    {
        printf("Unexpected ) at position %d\n", *position);
        return NULL;
    }
    else if (exp[*position] >= '0' && exp[*position] <= '9')
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = INTEGER;
        node->value = extract_int(exp, position);
        return node;
    }
    else if ((exp[*position] >= 'a' && exp[*position] <= 'z') ||
             (exp[*position] >= 'A' && exp[*position] <= 'Z') ||
             exp[*position] == '_')
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = VARIABLE;
        node->value = extract_variable(exp, position);
        return node;
    }
    else
    {
        printf("Warning: unexpected character %c in location %d\n", exp[*position], *position);
        return NULL;
    }
}

Where extract_int and extract_variable are two functions that take the expression and the position on it, go ahead while they are seeing a number (or a letter in the extract_variable function) they build the number (variable) from the expression string and return it, setting position to after where they finished.

Note: This is not code for copy paste. It is not complete and lacks sufficient error checking. Some details have been omitted and is offered as a solution to teach how simple parsing is done rather than easiest solution.

如果你想编写你自己的代码,最好的方法是用语法的形式来定义你的表达式。要轻松地解析语法,最好使它简单。

例如,以这样的形式解析表达式(1 +(3×4××××)+ 1,你可以写出这样的语法:

Expression -> Addition | null
Addition -> Multiplication RestOfAddition
RestOfAddition -> null | + Addition
Multiplication -> Element RestOfMultiplication
RestOfMultiplication -> null | * Element
Element -> number | variable | ( Expression )

然后在你的程序中,每个非终端在这个语法(左边的那些- >;),你写一个函数,像这样:

ExpTree *Expression(char *exp, int *position)
{
    if (exp[*position])
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = LAMBDA;
        node->value = 0;
        return node;
    }
    else
        return Addition(exp, position);
}

ExpTree *Addition(char *exp, int *position)
{
    ExpTree *node = malloc(sizeof(*node));
    node->type = ADDITION;
    node->left = Multiplication(exp, position);
    node->right = RestOfAddition(exp, position);
    return node;
}

ExpTree *RestOfAddition(char *exp, int *position)
{
    ExpTree *node;
    if (exp[*position] == '+')
    {
        ++*position;
        return Addition(exp, position);
    }
    else
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = LAMBDA;
        node->value = 0;
        return node;
    }
}

同样,乘法和restofmultiplication会写成函数。

ExpTree *Element(char *exp, int *position)
{
    if (exp[*position] == '(')
    {
        ExpTree *node;
        ++*position;
        node = Expression(exp, position);
        if (!exp[*position] != ')')
             printf("Expected ) at position %d\n", *position);
        else
             ++*position;
        return node;
    }
    else if (exp[*position] == ')')
    {
        printf("Unexpected ) at position %d\n", *position);
        return NULL;
    }
    else if (exp[*position] >= '0' && exp[*position] <= '9')
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = INTEGER;
        node->value = extract_int(exp, position);
        return node;
    }
    else if ((exp[*position] >= 'a' && exp[*position] <= 'z') ||
             (exp[*position] >= 'A' && exp[*position] <= 'Z') ||
             exp[*position] == '_')
    {
        ExpTree *node = malloc(sizeof(*node));
        node->type = VARIABLE;
        node->value = extract_variable(exp, position);
        return node;
    }
    else
    {
        printf("Warning: unexpected character %c in location %d\n", exp[*position], *position);
        return NULL;
    }
}

在extract_int和extract_variable两函数,对它的立场表达,继续当他们看到一个数(或在extract_variable功能信)他们建造的数(变量)的表达式字符串并返回它的位置,设置后,在他们完成。

注意:这不是复制粘贴的代码。它是不完整的,缺乏足够的错误检查。一些细节被省略,并提供了一个解决方案,教简单的解析是如何做,而不是最简单的解决方案。

answer2: 回答2:

You probably need to tokenize the expression and then apply rules to decide if the expression is valid or not.

你可能需要标记的表达和运用规则来决定是否是有效的或不表达。

answer3: 回答3:
char * raw_input;
scanf("%s",raw_input);

This is definitely not correct. raw_input is pointer that can hold an address. It isn't initialized and so it is pointing to garbage or to the worst it seems to point to a valid memory location. You cannot take input to it with actually pointing it to a valid memory location.

You need to malloc the bytes required and make the raw_input point to it. And then perform operation(s) on these memory locations.

char * raw_input;
scanf("%s",raw_input);

这绝对不正确。raw_input是指针,可以容纳一个地址。它没有初始化,所以它指向垃圾或最坏的,它似乎指向一个有效的内存位置。你不能把它输入到实际指向一个有效的内存位置。

你需要malloc字节需要使raw_input指向它。然后在这些内存位置执行操作。

answer4: 回答4:

You need a lexical analyzer and a parser. You may try lex and yacc, or their newer counterparts flex and bison.

您需要词法分析器和语法分析器。你可以试试lex和yacc,或他们的新同行flex和bison。

answer5: 回答5:

You could use:

  • flex, the free lexer generator.
  • Per-string iterator. Just traverse all string and pick all the items you want. strtok() may be helpful here. Or make a big loop and just read things per-char until you have the whole token.
  • Regexes via re2c (that's what PHP use)

After you split the string into tokens, you will need to parse it. You will need yacc or a hand-made parser (those are usually recursive descent).

你可以用:

  • flex, the free lexer generator.
  • Per-string iterator. Just traverse all string and pick all the items you want. strtok() may be helpful here. Or make a big loop and just read things per-char until you have the whole token.
  • Regexes via re2c (that's what PHP use)

将字符串拆分为令牌后,将需要解析。你将需要yacc或手工制作的解析器(那些通常是递归下降)。

answer6: 回答6:

Don't use scanf. Use getchar and apply the Shunting Yard Algorithm.

不要使用scanf。使用getchar和运用调车场算法。

answer7: 回答7:

Use array and not pointers. If you cant use other libraries you can to look in side cstring

But it will be too long in your case

使用数组而不是指针。如果你不能使用其他的库,你可以看看身边的原

但你的情况太长了

c  scanf