开发者

Parsing strings of equations in c using scanf

开发者 https://www.devze.com 2023-04-04 08:56 出处:网络
I need to parse input from a user that could be any number of variations: 1+14(3-0) =x1*(3)-8 How do I do this using scanf to get the raw_input, then split out all of the different values and tell ei

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 ele开发者_JAVA百科ments. What is the best way of doing the input and (splitting and converting)

Thanks


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.


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


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.


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


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).


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消