【问题标题】:Segmentation fault caused by white space not caught in string from cin由 cin 的字符串中未捕获的空格导致的分段错误
【发布时间】:2020-02-18 10:43:50
【问题描述】:

我正在努力实现Shunting Yard Algorithm 来评估简单表达式。该代码似乎可以工作,但如果有空格则会崩溃。这是令人惊讶的,因为有一个特定的空白检查似乎根本没有抓住它。

using namespace std;


mpz_class exprToTokens(string expression);
int precedence(const char op);
mpz_class applyOperation(const mpz_class a, const mpz_class b, const char op);

int main() {



    try {
    while(true)
    {
            cout << "enter an expression: ";
            string expr;
            cin >> expr;
            if( expr == "e")
            {
        break;
            }
            cout << "output: " << exprToTokens(expr) << endl;
    }

    } catch( const std::exception & ex ) {
       cerr << "message: " << ex.what() << endl;
    }

    return 0;
}

mpz_class exprToTokens(string expression)
{

    stack<char> operators;
    stack<mpz_class> output;


    unsigned int i = 0;
    while(i < expression.length())
    {
        if(isspace(static_cast<unsigned char>(expression.at(i))))//skip white space
        {
            cout << "is space" << endl;//never happens
            i++;
            continue;
        }
        else if(isdigit(expression[i]))
        {
            unsigned int j = i;
            while(i < expression.length() && isdigit(expression[j]))
            {
                j++;
            }
            const string number = expression.substr(i, j-i);
            const mpz_class term(number);
            output.push(term);
            i = j;
            continue;
        }
        else//token is an operator
        {
            while(!operators.empty() && precedence(operators.top() >= precedence(expression[i])))
            {
                const mpz_class val1 = output.top();
                output.pop();

                const mpz_class val2 = output.top();
                output.pop();

                const char op = operators.top();
                operators.pop();

                output.push(applyOperation(val1, val2, op));
            }
            operators.push(expression[i]);
        }
        i++;
    }

    /*process remaining operations and values on stacks*/
    while(!operators.empty())
    {
        const mpz_class val2 = output.top();//something bad happens here when spaces are around operator
        output.pop();

        const mpz_class val1 = output.top();
        output.pop();

        const char op = operators.top();
        operators.pop();

        output.push(applyOperation(val1, val2, op));
    }

    return output.top();
}

int precedence(const char op)
{ 
    if(op == '+' || op == '-')
        return 1; 
    if(op == '*' || op == '/') 
        return 2; 
    return 3;
} 


mpz_class applyOperation(const mpz_class a, const mpz_class b, const char op)
{
    switch(op)
    { 
        case '+': return a + b; 
        case '-': return a - b; 
        case '*': return a * b; 
        case '/': return a / b;
        default: throw invalid_argument("syntax not recognized");
    } 
}

例如3+3 给出6 结果但3 + 3 导致分段错误。有什么想法吗?

题外话:Shunting Yard 算法将中缀转换为后缀表示法。所以严格来说,修改算法以实际评估表达式是很常见的,但它仍然是 Shutting Yard 算法吗?对于普通算法,是否还需要另一个算法来评估后缀表示法的表达式?

【问题讨论】:

    标签: c++ algorithm segmentation-fault


    【解决方案1】:

    cin &gt;&gt; expr; 在空格处拆分输入,因此读取三个单独的表达式:3+3。要阅读整个表达式,请使用std::getline()

    您的程序可能在解析第一个时崩溃,因为此循环不检查j

    while(i < expression.length() && isdigit(expression[j]))
    {
        j++;
    }
    

    【讨论】:

    • isdigit('\0') 是否为假? std::string 是否总是以 null 终止(自 C++11 起)?在这种情况下,这应该使第一个表达式无关紧要。
    • @Surt 是正确的,isdigit(0) 是错误的:en.cppreference.com/w/cpp/string/byte/isdigit
    猜你喜欢
    • 2023-03-10
    • 2019-09-25
    • 2012-11-13
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-08-09
    • 2017-08-02
    相关资源
    最近更新 更多