简体   繁体   中英

How to split a string into different datatypes in C++

I have the following problem: I have an input string that looks something like this: string s ="87635+23754*ar+ar*var*0.895+(ar-var)+ar*ar+var*var";

I want to split this string and execute each operation ie I want to read in all the values, perform the mathematical operations and output the final answer in C++. How do I do it? getline command can split only one type of delimiter. How do I solve this problem?

Thanks

Nita

“正确”的答案是为您的迷你语言编写一个解析器,但使用string::find_first_of和/或string::find_first_not_of将其标记为数字,运算符和命名变量可能更简单

Take a look at std::stringstream . You can put a string into the stream and read from it just like from std::cin!

For example:

#include <iostream>
#include <sstream>

int main()
{
    std::stringstream stream(std::stringstream::in | std::stringstream::out);
    stream << "22+2";

    int operand1, operand2;
    char op;

    stream >> operand1;
    stream >> op;
    stream >> operand2;

    std::cout << operand1 << " " << op << " " << operand2 << std::endl;

    return 0;
}

For a more complex example look at the dc-clone I did a while ago: gist.github.com/ae6ebe58a286d6cfd847 . Especially look at the lines 467-522 (in main).

You must write a parser. Don't be scared of the "correct" solution, it's correct for a good reason; it works. The shortcuts offered by others won't make your task any easier.

I have included a basic solution that you can use as a starting point. You should build test cases to make sure it is correct and handle error cases more thoroughly.

Hopefully by studying this code you will get the general idea of a recursive decent parser. We split up the parsing problem by using separate functions for the different levels of operator precedence. These functions call each other in a top down fashion, making this type of parser easier to understand.

I have coded it in such a way as to be brief. If you believe 'goto' is evil, use a while loop instead. Furthermore, convert the parsing functions into a Parser class to get rid of the global variables.

Good luck and happy parsing :)

    #include <string>
    #include <map>
    #include <iostream>
    #include <sstream>
    using namespace std;

    stringstream ss;
    map<string,double> variables;
    string err_string = "";

    double parse_add_exp();

    int main()
    {
        // get the expression and variables
        ss << "87635+23754*ar+ar*var*0.895+(ar-var)+ar*ar+var*var";
        variables["ar"] = -4.5;
        variables["var"] = 141.26f;
        try
        {
            // calculate the result
            double result = parse_add_exp();
            if( result == INFINITY )
                cout<<"Runtime error: Division by zero"<<endl;
            else
                cout<<"Result = "<<result<<endl; // prints 'Result = 1.95143'
        }
        catch (const char * error)
        {
            cout<<"Invalid expression: "<<error<<endl;
        }
        return 0;
    }
    double parse_number()
    {
        double f;
        if( !(ss>>f) )
            throw "Expected number";
        return f;
    }
    double parse_operand()
    {
        string var("");
        while( isalpha(ss.peek()) )
            var += ss.get();
        if( !var.size() )
            return parse_number();
        if( variables.find(var) == variables.end() )
            throw "Variable is undefined";
        return variables[var];
    }
    double parse_parenthesis()
    {
        if( ss.peek() != '(' )
            return parse_operand();
        ss.get();
        double f = parse_add_exp();
        if( ss.get() != ')' )
            throw "Expected closing parenthesis";
        return f;
    }
    double parse_mul_exp()
    {
        double product = parse_parenthesis();
    PEEKOP:
        switch( ss.peek() )
        {
            case '*': ss.get(); product *= parse_parenthesis(); goto PEEKOP;
            case '/': ss.get(); product /= parse_parenthesis(); goto PEEKOP;
            default: return product;
        }
    }
    double parse_add_exp()
    {
        double sum = parse_mul_exp();
    PEEKOP:
        switch( ss.peek() )
        {
            case '+': ss.get(); sum += parse_mul_exp(); goto PEEKOP;
            case '-': ss.get(); sum -= parse_mul_exp(); goto PEEKOP;
            default: return sum;
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM