es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo incluir una matriz (de una estructura) en una estructura en Solidity

Recientemente comencé a aprender Solidity y he visto dos videos de conferencias al respecto y he leído la documentación oficial, pero no logro encontrar una solución para esto. [También he revisado varios recursos en busca de ayuda pero no he encontrado ninguno]

Necesidad: Dos structs donde uno haga referencia al otro (el Reader struct tiene un Book struct books), y cuando se crea un reader, books está vacío hasta que recojan (función pickUp) un libro. [He creado una lista constante de libros disponibles].

Lo que he intentado:

pragma solidity ^0.6.0

contract School {
   struct Book {
      string name;
   }
   Book[2] public books = [Book("we1"), Book("uer")];

   struct Reader {
      string name;
      uint booksRead; //por cada libro agregado, esto se incrementa
      Book[] books;
   }

   Reader public readers;

   function _createReader(string memory _name) public returns (uint) {
      //alguna lógica
      readers.push(Reader("Freddie", 0, books[0])); 
      uint256 readerID = readers.length - 1;
      return readerID;
   }
}

Error (no se compila): TypeError: Tipo no válido para el argumento en la llamada a la función. Conversión implícita no válida desde struct School.Book storage ref a struct School.Book memory[] memory solicitado.

No logro entender este error.

Resultado esperado:

Reader 1 (al crearse): “Fred”, 0, [] //nombre Fred, booksRead 0, lista vacía de libros

Reader 1 (al actualizarse): “Fred”, 2, [Book(“SomeBookI”), (“SomeBookII”)]

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para arreglar el error, necesitamos hacer algunos cambios en el código.

    Primero, en la función _createReader, debemos inicializar el array books para la nueva instancia de Reader como un array vacío, de la siguiente manera:

    function _createReader(string memory _name) public returns (uint) {
      Reader memory newReader = Reader(_name, 0, new Book[](0));
      readers.push(newReader); 
      uint256 readerID = readers.length - 1;
      return readerID;
    }
    

    Esto crea una nueva instancia de Reader con un array books vacío.

    A continuación, necesitamos modificar la función pickUp para permitir que un lector recoja un libro. Esta función debe tomar el readerID y el bookIndex (el índice del libro que desean recoger en el array books), y luego agregar el libro al array books de la instancia de Reader.

    Aquí está el código actualizado:

    pragma solidity ^0.6.0;
    
    contract School {
       struct Book {
          string name;
       }
    
       Book[] public books = [Book("we1"), Book("uer")];
    
       struct Reader {
          string name;
          uint booksRead; //por cada libro agregado, esto se incrementa
          Book[] books;
       }
    
       Reader[] public readers;
    
       function _createReader(string memory _name) public returns (uint) {
          Reader memory newReader = Reader(_name, 0, new Book[](0));
          readers.push(newReader); 
          uint256 readerID = readers.length - 1;
          return readerID;
       }
    
       function pickUp(uint readerID, uint bookIndex) public {
          readers[readerID].books.push(books[bookIndex]);
          readers[readerID].booksRead += 1;
       }
    }
    

    Ahora, podemos llamar a la función _createReader para crear una nueva instancia de Reader, y utilizar la función pickUp para agregar libros a su array books. Aquí hay un ejemplo:

    School school = new School();
    
    uint readerID = school._createReader("Fred");
    
    // Verificar el estado inicial del lector
    Reader memory fred = school.readers(readerID);
    assert(fred.booksRead == 0);
    assert(fred.books.length == 0);
    
    // Hacer que Fred recoja un libro
    school.pickUp(readerID, 0);
    
    // Verificar el estado actualizado del lector
    fred = school.readers(readerID);
    assert(fred.booksRead == 1);
    assert(fred.books.length == 1);
    
    // Hacer que Fred recoja otro libro
    school.pickUp(readerID, 1);
    
    // Verificar el estado actualizado del lector
    fred = school.readers(readerID);
    assert(fred.booksRead == 2);
    assert(fred.books.length == 2);
    

    Esto debería crear una nueva instancia de Reader llamada “Fred”, con un array books vacío. Luego, utilizamos la función pickUp para agregar dos libros a su array books. Por último, verificamos que el estado de la instancia de Reader se haya actualizado correctamente.

Comments are closed.