Wie speichert man ein Array von Strukturen, das ein Array von Strukturen enthält?

Ich versuche, ein Array von Strukturen zu erstellen, die ein Array von Strukturen enthalten.

https://gist.github.com/anonymous/65260d973a5640741a7d6174bf8fe7e6

Aus verschiedenen Suchen geht hervor, dass es nicht möglich ist, eine Struktur mit einem Array von Strukturen zu initialisieren, die auf ein gespeichertes Array geschoben werden sollen, und dass der beste Weg scheint, einfach eine Nicht-Struktur-Array-Variable an einer bestimmten Position im äußeren Array zu setzen .

Leider bekomme ich das anscheinend nicht zum Laufen. Ich habe verschiedene Dinge ausprobiert, aber hauptsächlich um die oben genannten.

Wenn ich laufe truffle testbekomme ich:

Error: VM Exception while processing transaction: revert

Wenn ich versuche, die createBar-Funktion in der Konsole auszuführen, bekomme ich etwas anderes:

Error: VM Exception while processing transaction: invalid opcode

Ich bin mir nicht sicher, was ich falsch mache. Jeder Lichtschuppen oder Hinweise würden sehr geschätzt werden.

Antworten (2)

Ein Array hat eine Länge, Sie können nur Elemente zwischen 0 und der Länge des Arrays - 1 verwenden.

Wenn Sie ein neues Element hinzufügen möchten, müssen Sie die Arraygröße erhöhen.

function createBar(uint barNum)
  public
  returns (uint)
{
  uint barId = bars.length;
  bars.length += 1;
  bars[barId].barNum = barNum;
  return barId;
}
Wow - das funktioniert super. Macht absolut Sinn, ich weiß nicht, warum ich nicht daran gedacht habe, das Array so zu vergrößern, ich glaube, ich dachte, ich hätte irgendwo gelesen, dass Arrays auf magische Weise wachsen. Ich bin froh, dass in Solidität nicht so viel Magie steckt. Danke schön!
Wenn Sie nur anhängen möchten, würde ich empfehlen, das pushMitglied zu verwenden, da das manuelle Erhöhen der Länge keine sehr gute Programmiertechnik ist.

Das ist interessant.

Ich bin nicht davon überzeugt, dass diese Art der Verschachtelung für die meisten Fälle ideal ist, da ungeordnete Listen für den wahlfreien Zugriff nicht nützlich sind. Möglicherweise finden Sie zugeordnete Strukturen mit Indizes etwas flexibler.

Gibt es gut gelöste und einfache Speichermuster für Solidity?

Was Sie verlangen, ist praktikabel, also habe ich damit herumgespielt. Keine Garantie. ;-)

pragma solidity ^0.4.18;

contract ArrayOfStructsContainsArrayOfStructs {

  struct InnerStruct {
    uint x;
  }

  struct OuterStruct {
    InnerStruct[] innerStructs;
  }

  // This can't be public because the "free" getter is too complex for the compiler to work out a default
  OuterStruct[] outerStructs;

  event LogAppendedOuterStruct(address sender, uint outerStructRow);
  event LogAppendedInnerStruct(address sender, uint outerStructRow, uint innerStructRow);
  event LogSetInnerStructValue(address sender, uint outerStructRow, uint innerStructRow, uint value);

  function appendOuterStruct() public returns(uint row) {
    LogAppendedOuterStruct(msg.sender, outerStructs.length);
    outerStructs.length++;
    return outerStructs.length-1;
  }

  // The outer structs are in an array, so specify the outerStructRow
  function appendInnerStruct(uint outerStructRow) public returns(uint row) {
    LogAppendedInnerStruct(msg.sender, outerStructRow, outerStructs[outerStructRow].innerStructs.length);
    outerStructs[outerStructRow].innerStructs.length++;
    return outerStructs[outerStructRow].innerStructs.length-1;
  }

  function setInnerStructValue(uint outerStructRow, uint innerStructRow, uint value) public returns(bool success) {
    outerStructs[outerStructRow].innerStructs[innerStructRow].x = value;
    LogSetInnerStructValue(msg.sender, outerStructRow, innerStructRow, value);
    return true;
  }

  function getInnerStructValue(uint outerStructRow, uint innerStructRow) public view returns(uint value) {
    return outerStructs[outerStructRow].innerStructs[innerStructRow].x;
  }

}

Ich hoffe es hilft.

Vielen Dank für all das! Ich habe Ismaels unten ausprobiert und es macht den Trick. Ich habe mir bei dieser Lösung ein wenig Sorgen gemacht, dass die Wiederverwendung von InnerStruct und OuterStruct dazu führen würde, dass Dinge dupliziert werden.
Ismael hatte die richtige Idee, leere Strukturen an die Arrays anzuhängen. Ich habe das Beispiel aktualisiert. Es scheint jetzt besser zu sein.