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

Solidity嵌套struct开发时addDrugs调用报Integer constant expected错误

错误产生原因
  • 直接触发编译报错的核心问题:你错误地将结构体类型名Drug作为数组/映射变量使用,写出了Drug[_id]这类非法语法。Solidity中类型名[整数常量]是固定长度数组的声明语法,要求方括号内必须是编译期就能确定值的整型常量;编译器看到Drug[_id]时,会判定你在尝试声明一个固定长度的Drug类型数组,但方括号内的_id是运行时才会赋值的循环变量,不是常量,因此抛出TypeError: Integer constant expected错误。
  • 代码附带的多处逻辑缺陷:
    • addDrugs函数第一行强制将传入的_id赋值为1,无论传入什么参数,最终都只会操作mapDrug中key为1的存储槽,循环调用时所有药品数据会互相覆盖,完全无法实现批量存药。
    • addPresc入参设计不合理:单个Drug memory _list只能接收1个药品实例,无法支持处方包含多个药品的需求;且处方ID硬编码为1,每次调用函数都会覆盖同一条处方记录,无法生成多个独立处方。
    • 数据关联缺失:存药品时没有将药品实例写入对应处方的drugs动态数组成员,处方和药品数据完全割裂,不符合最初的结构体设计目标。
    • 冗余参数风险:手动传入的_nbOfDrugs参数没有和实际药品数量做校验,很容易出现参数值和实际药品数不一致的逻辑bug。
修复方案

修复逻辑围绕「解决语法错误、补全数据关联、修正ID生成逻辑、移除冗余设计」四个核心点调整,修复后可直接编译运行的完整代码如下:

pragma solidity ^0.8.0;

contract Pharm {
    struct Presc {
        uint id;
        uint ref;
        uint nbOfDrugs;
        string Pname;
        Drug[] drugs; 
    }

    struct Drug {
        uint id; 
        string name;
        uint Qtt;
    }

    Drug[] drugss;
    mapping(uint=> Presc) public mapPresc;
    mapping(uint=> Drug) public mapDrug;
    // 全局自增ID,解决硬编码ID导致的数据覆盖问题
    uint public prescIdCounter = 1;
    uint public drugIdCounter = 1;
        
    // 仅允许合约内部调用,避免外部随意篡改药品数据
    function addDrugs(uint _belongPrescId, string memory _name, uint _Qtt) internal { 
        uint currentDrugId = drugIdCounter;
        Drug storage newDrug = mapDrug[currentDrugId];
        newDrug.id = currentDrugId;
        newDrug.name = _name;
        newDrug.Qtt = _Qtt;
        // 将新增药品关联到对应处方的drugs数组
        mapPresc[_belongPrescId].drugs.push(newDrug);
        drugIdCounter++;
    }

    // 入参改为Drug动态数组,支持批量传入任意数量的药品
    function addPresc(uint _ref, string memory _Pname, Drug[] memory _drugList) public { 
        uint currentPrescId = prescIdCounter;
        Presc storage presc = mapPresc[currentPrescId];

        presc.id = currentPrescId; 
        presc.ref = _ref;
        // 直接取传入药品数组的长度作为药品总数,避免手动传参的不一致问题
        presc.nbOfDrugs = _drugList.length;
        presc.Pname = _Pname;

        // 遍历传入的药品列表,逐个完成存证、关联
        for(uint i = 0; i < _drugList.length; i++){
            addDrugs(currentPrescId, _drugList[i].name, _drugList[i].Qtt);
        }

        prescIdCounter++;
    }
}

关键修改点说明:

  • 完全移除了非法的Drug[_id]写法,循环遍历时直接读取传入的内存药品数组的元素属性,从根源解决编译错误。
  • 删除addDrugs中强制将ID赋值为1的错误逻辑,改用全局自增ID生成药品、处方的唯一标识,避免数据互相覆盖。
  • 补全了药品和处方的关联逻辑,新增药品时自动推入对应处方的drugs动态数组,符合最初的结构体设计。
  • 调整函数可见性:将仅用于内部逻辑的addDrugs改为internal,避免外部非法调用;移除冗余的_nbOfDrugs入参,直接通过数组长度获取药品总数,降低参数传错的风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:45:38