You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ std::map键值对二次调用函数后丢失问题求助

问题分析与解决方案

你遇到的问题核心是错误地传递了要赋值的目标变量名,再加上std::map的operator[]特性导致了键值对的“丢失”(其实是根本没存到正确的键上)。让我一步步拆解问题:

1. 关键错误:目标变量名传递错误

在convertToPostFixAndPrint函数中,你传递给romanCalc的infixVector是表达式部分的tokens(也就是assignmentStatement从第3个元素开始的内容),比如第一次调用时infixVector是[XII],这是罗马数字token,不是变量名b。但你在romanCalc里却用infixVector[0]->variable()来获取要赋值的变量名——罗马数字token的variable()方法返回的肯定不是b(要么是未定义的垃圾值,要么是空字符),这就导致你把计算结果存到了一个错误的键上,而真正的变量b从未被存入symTable。

2. 次要错误:std::map::operator[]的“隐式插入”特性

当你在处理变量b时,使用了symTable[roman->variable()]——如果symTable里没有这个键,operator[]会自动插入一个默认值(int的默认值是0),然后返回这个值。这就是为什么你看到“Value retrieved from b is 0”:因为b根本不在symTable里,是你用operator[]的时候自动加进去的,值为0。


修正方案

步骤1:传递正确的目标变量名给romanCalc

修改convertToPostFixAndPrint中调用romanCalc的代码,把真正的目标变量名(也就是assignmentStatement[0]对应的变量)传进去:

// 在convertToPostFixAndPrint函数里,替换原来的romanCalc调用
char targetVariable = assignmentStatement[0]->variable();
romanCalc(postfixTokens, targetVariable, symTable);

步骤2:修改romanCalc的函数签名和逻辑

更新romanCalc的参数,去掉无用的infixVector,改用传入的targetVariable,同时修正变量查找逻辑:

void romanCalc(const std::vector<Token *> &postfixVector, char targetVar, std::map<char, int> &symTable) {
    std::stack<int> romanStack;
    for(auto roman: postfixVector) {
        if(roman->isValidRomanNumeral()) {
            RomanNumeral * romans = new RomanNumeral(roman->romanNumber());
            romanStack.push(romans->convertRomanToInt());
            delete romans; // 别忘了释放内存,避免内存泄漏!
        }
        else if(roman->isAVariable()) {
            char var = roman->variable();
            std::cout << "Variable: " << var << std::endl;
            // 先查找,避免operator[]隐式插入
            auto it = symTable.find(var);
            if(it != symTable.end()){
                std::cout << "Value retrieved from " << var << " is " << it->second << std::endl;
                romanStack.push(it->second);
            } else {
                std::cout << "Error: Undefined variable '" << var << "'" << std::endl;
                exit(1);
            }
        }
        else {
            // 运算符处理逻辑保持不变,但新增栈空检查避免崩溃
            if(romanStack.size() < 2) {
                std::cout << "Error: Insufficient operands for operator" << std::endl;
                exit(1);
            }
            int second = romanStack.top();
            romanStack.pop();
            std::cout << second << " second\n";
            int first = romanStack.top();
            romanStack.pop();
            std::cout << first << " first\n";
            if(roman->isAdditionOperator())
                romanStack.push(first + second);
            else if(roman->isSubtractionOperator())
                romanStack.push(first - second);
            else if(roman->isMultiplicationOperator())
                romanStack.push(first * second);
            else if(roman->isDivisionOperator())
                romanStack.push(first / second);
            else if(roman->isModuloOperator())
                romanStack.push(first % second);
            else {
                std::cout << "Expected an arithmetic operator instead found the following token \n";
                roman->print();
                exit(1);
            }
        }
    }
    // 把计算结果存入正确的目标变量
    symTable[targetVar] = romanStack.top();
    std::cout << "Testing Retrieve from map: " << symTable[targetVar] << std::endl;
    std::cout << romanStack.top() << std::endl;
}

步骤3:额外优化:避免内存泄漏

注意你在原代码里用了new RomanNumeral(...)但没有delete,这会导致内存泄漏,上面的修正代码里已经加上了delete romans;来释放内存。


修正后的效果

第一次调用时,symTable['b']会被正确赋值为12;第二次调用处理c = MMDCCCLXXXVIII + b时,查找b会直接找到已存在的键,取出值12参与计算,最终symTable['c']会被设置为正确的结果(2888 + 12 = 2900)。

内容的提问来源于stack exchange,提问作者Debug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:12:42