Wenn ich function verwende setDailyAssessmentInfo
, wird ein Fehler ausgelöst:
Fehlerhafte Gasschätzung mit folgender Meldung (siehe unten). Die Ausführung der Transaktion wird wahrscheinlich fehlschlagen. Möchten Sie das Senden erzwingen? VM-Ausnahme während der Verarbeitung der Transaktion: ungültiger Opcode
Hier ist mein Code:
pragma solidity ^0.4.21;
contract DailyAssessmentScoreContract {
struct dailyAssessment{
string dailyAssessmentId;
string[] period;
uint[] score;
}
dailyAssessment[] daily_assessment;
function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
bytes storage a = bytes(_a);
bytes memory b = bytes(_b);
if (a.length != b.length)
return false;
// @todo unroll this loop
for (uint i = 0; i < a.length; i ++)
if (a[i] != b[i])
return false;
return true;
}
function stringToUint(string s) constant returns (uint result) {
bytes memory b = bytes(s);
uint i;
result = 0;
for (i = 0; i < b.length; i++) {
uint c = uint(b[i]);
if (c >= 48 && c <= 57) {
result = result * 10 + (c - 48);
}
}
}
function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, string _score) public {
bool write = false;
uint score = stringToUint(_score);
for(uint i=0; i<=daily_assessment.length; i++)
{
if(stringsEqual(daily_assessment[i].dailyAssessmentId, _dailyAssessmentId))
{
daily_assessment[i].period.push(_period);
daily_assessment[i].score.push(score);
write = true;
}
}
if(write==false)
{
daily_assessment[i].dailyAssessmentId=_dailyAssessmentId;
daily_assessment[i].period.push(_period);
daily_assessment[i].score.push(score);
}
}
function getDailyAssessmentInfo(string _dailyAssessmentId) public constant returns (uint) {
uint score;
for(uint i=0;i<=daily_assessment.length;i++)
{
if(stringsEqual(daily_assessment[i].dailyAssessmentId, _dailyAssessmentId))
{
uint sum = 0;
uint scoreLength = daily_assessment[i].score.length;
for(uint j=0;j<=scoreLength;j++)
{
sum = sum + daily_assessment[i].score[j];
}
score = sum / scoreLength;
}
}
return (score);
}
}
Das Problem liegt darin
for(uint i=0; i<=daily_assessment.length; i++)
Das Iterieren über das Array, wenn es zu groß wird, kann einen Gasfehler verursachen, und da es sich um ein Array mit variabler Länge handelt, verursacht es einen Gasschätzungsfehler.
Sie können Ihr Design so ändern, dass es mapping
anstelle von Array verwendet wird.
mapping(string => dailyAssessment) daily_assessment;
Verwenden Sie a map
, wobei key
das daily assessment id
und value
das struct sein wird dailyAssessment
.
function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, string _score) public {
bool write = false;
uint score = stringToUint(_score);
dailyAssessment storage assessment = daily_assesment[_dailyAssesmentId];
if(assesment.dailyAssesmentId == _dailyAssesmentId)
{
assessment.period.push(_period);
assessment.score.push(score);
write = true;
}
In Bezug auf Ihren Kommentar: „Hier ist ein weiteres Problem, das ich mit „getDailyAssessmentInfo“ verwenden möchte, um die Summe des Score-Arrays abzurufen. Anscheinend berechnen Sie den Durchschnitt der Ergebnisse in dieser getDailyAssessmentInfo
Funktion. Es beinhaltet die Verwendung einer Schleife über alle Punkte und die Berechnung des Durchschnitts. Die ideale Lösung wäre also die Berechnung des Durchschnitts ohne Verwendung von Schleifen.
Ich schlage vor, dass Sie beim Einfügen der Daten (in setDailyAssessmentInfo
) den Durchschnitt berechnen, ihn speichern und diesen Durchschnittswert einfach mit einer Get-Funktion abrufen. Denken Sie jedoch daran, dass die Berechnung keine Schleife verwenden sollte. Ich habe dazu eine einfache Idee im folgenden Code verwendet.
struct dailyAssessment{
string dailyAssessmentId;
string[] period;
uint[] score;
uint averageScore;
}
function getDailyAssessmentInfo(string _id) returns (uint){
return daily_assessment[_id].averageScore;
}
function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, uint _score) public {
uint average = daily_assessment[_dailyAssessmentId].averageScore;
uint N = daily_assessment[_dailyAssessmentId].score.length;
uint newAverage = (average * N + _score) / (N + 1);
daily_assessment[_dailyAssessmentId].averageScore = newAverage;
Hoffe es hat geholfen.
Kyrie
Kyrie
biplavo