How to save structs in array in Solidity? - struct

I wrote a very simple smart contract which does the following:
Declares a struct named Player which has 2 fields: name and goals
Defines a function which takes as inputs names and goals to create a new instance of the structure
Stores the new player into an array of players
Here is the code:
pragma solidity ^0.8.0;
contract MyContract {
// Declare struct
struct Player {
string name;
uint goals;
}
// Declare array
Player[] player;
function addPlayer(string calldata _name, uint _goals) external pure{
Player memory player = Player({name:_name, goals:_goals}); // This declaration shadows an existing declaration.
players.push(player); // Member "push" not found or not visible after argument-dependent lookup in struct MyContract.Player memory.
}
}
My goal is to use the addPlayer() function to add players to the players array
However the VisualStudio Editor returns an error since it gets confused by the declaration of the Player variable which appears to be twice.
Could you please provide a smart and elegant way to achieve my goal please?

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyContract {
// Declare struct
struct Player {
string name;
uint goals;
}
// Declare array
Player[] players;
function addPlayer(string calldata _name, uint _goals) external {
Player memory player = Player(_name,_goals); // This declaration shadows an existing declaration.
players.push(player); // Member "push" not found or not visible after argument-dependent lookup in struct MyContract.Player memory.
}
}

Thanks to Chíp Thảo for leaving the answer with not complete explain :)
Here is continue of explain:
In line 12 you declared an array, Player[] player, with name player and also in line 16 you declared a variable again with name player! better change line 12 into players.

Related

Solidity: problem creating a struct containing mappings inside a mapping

This is my code where i am trying to create a struct containing two mappings and insert the structs into a mapping:
pragma solidity ^0.7.2;
contract Campaign {
struct Usuario {
string id;
mapping(string => uint) debe;
mapping(string => uint) leDebe;
}
Usuario[] public usuarios;
uint numUsuarios;
mapping(string => Usuario) public circulo;
constructor () {
}
function usuarioPrueba(string memory id, string memory idDebe, uint valDebe, string memory idLeDebe, uint valLedebe) public {
usuarios.push();
Usuario storage newUsuario = usuarios[numUsuarios];
numUsuarios++;
newUsuario.id = id;
newUsuario.debe[idDebe] = valDebe;
newUsuario.leDebe[idLeDebe] = valLedebe;
circulo[id] = newUsuario;
}
}
but I am getting the following error at line 28 (circulo[id] = newUsuario;) on Remix:
TypeError: Types in storage containing (nested) mappings cannot be
assigned to. circulo[id] = newUsuario;
Thank you so much for the help beforehand and I am sorry for my english, I am from Spain and if the solution its just to obvious, I am kind of new to solidity and smart contracts.
Since v 0.7.0 you cannot assign structs containing nested mappings. What you can do instead is to create new instances like this one and then asign the values to the properties of the struct!
Usuario storage newUsuario = circulo[id];
numUsuarios++;
newUsuario.id = id;
newUsuario.debe[idDebe] = valDebe;
newUsuario.leDebe[idLeDebe] = valLedebe;

How to get an overview of created structs in a mapping for a specific address in solidity?

After I created some structs which belong to specific addresses I want to get an overview of structs with associated parameters regarding an address.
So what could I do for solving this problem?
If I am running my code inside remix, I get back only my first stored struct for an address. But I want to get back all stored structs for one address. I know that we can not iterate through a mapping, but maybe it is possible to make some index-counter for the array of structs to solve it? - So is it also possible to store the index of array in a variable?
pragma solidity ^0.4.17;
contract Prescribe {
struct Prescription {
address patients_address;
string medicament;
string dosage_form;
uint amount;
uint date;
//uint index_counter;
}
mapping (address => Prescription[]) public ownerOfPrescription;
address [] public patients;
function createPrescription(address patients_address, string
medicament, string dosage_form, uint amount, uint date) public
restricted {
ownerOfPrescription[patients_address].push(Prescription({
patients_address: patients_address,
medicament: medicament,
dosage_form: dosage_form,
amount: amount,
date: date
}));
patients.push(patients_address);
}
function getOverview(address patient) public view restricted
returns(string, string, uint, uint) {
for(uint i = 0; i < ownerOfPrescription[patient].length; i++) {
if(ownerOfPrescription[patient][i].patients_address == patient) {
return(ownerOfPrescription[patient][i].medicament,
ownerOfPrescription[patient][i].dosage_form,
ownerOfPrescription[patient][i].amount,
ownerOfPrescription[patient][i].date);
}
}
}
So I want to have the return-values of all separate structs of one address as in the function getOverview on the screen, but it gives me back only the first struct of an address
Well, it's returning only the first one, because after the statement
if(ownerOfPrescription[patient][i].patients_address == patient)
return true, your code is executing the return statement which will make the control to exit from the function, and no further statement will be executed.
Ok after a research I made the conclusion that it is still not possible to get an array of structs as a return value. One has only the possibility to access individual elements of the array right? - If there are any updates on this topic, I would be very grateful for a hint.
There is a way to return array of struct but it will cost a little bit more gas fees.
Below is an example
contract Test {
struct FlexiblePlan {
string token;
address _address;
}
struct Plans {
FlexiblePlan[] flexiblePlans;
}
Plans plans;
function createPlan(string memory _token, address _address) external {
plans.flexiblePlans.push(FlexiblePlan(_token, _address));
}
function getAllPlans() external view returns(Plans memory){
return plans;
}
}

Why is the struct unknown at compiletime in the code?

I was wondering how I could change the code below such the bmBc is computed at compile time . The one below works for runtime but it is not ideal since I need to know the bmBc table at compile-time . I could appreciate advice on how I could improve on this.
import std.conv:to;
import std.stdio;
int [string] bmBc;
immutable string pattern = "GCAGAGAG";
const int size = to!int(pattern.length);
struct king {
void calculatebmBc(int i)()
{
static if ( i < size -1 )
bmBc[to!string(pattern[i])]=to!int(size-i-1);
// bmBc[pattern[i]] ~= i-1;
calculatebmBc!(i+1)();
}
void calculatebmBc(int i: size-1)() {
}
}
void main(){
king myKing;
const int start = 0;
myKing.calculatebmBc!(start)();
//1. enum bmBcTable = bmBc;
}
The variables bmBc and bmh can't be read at compile time because you define them as regular runtime variables.
You need to define them as enums, or possibly immutable, to read them at compile time, but that also means that you cannot modify them after initialization. You need to refactor your code to return values instead of using out parameters.
Alternatively, you can initialize them at runtime inside of a module constructor.

Mutating in Structure Swift Same function Name

Still trying out swift, and I came across this problem (not sure if it really classifies as one)
So we have a protocol, and a structure that inherits it.
protocol ExampleProtocol {
var simpleDescription: String { get }
func adjust()
}
struct SimpleStructure : ExampleProtocol{
var simpleDescription = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
func adjust() { //I created this second method just to conform to the protocol
}
}
var b = SimpleStructure()
b.adjust() //This generates a compiler error mentioning Ambiguity (Correct)
Question is how do I call the mutating adjust() not the adjust from the protocol. i.e. I know if I declare b as a protocol and initialized it to the struct it will call adjust from protocol, but how do I call the first adjust ? or is it not possible? Or Am I using it wrongly ?
Cheers,
Your code doesn't compile, but the error is in redefining the adjust method by adding the mutating attribute - that doesn't create an overloaded version of adjust.
In my opinion this is the correct code:
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
struct SimpleStructure : ExampleProtocol{
var simpleDescription = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
which means: you have to define the adjust function as mutating in the protocol.

How to use stdext::hash_map?

I would like to see a simple example of how to override stdext::hash_compare properly, in order to define a new hash function and comparison operator for my own user-defined type. I'm using Visual C++ (2008).
This is how you can do it
class MyClass_Hasher {
const size_t bucket_size = 10; // mean bucket size that the container should try not to exceed
const size_t min_buckets = (1 << 10); // minimum number of buckets, power of 2, >0
MyClass_Hasher() {
// should be default-constructible
}
size_t operator()(const MyClass &key) {
size_t hash_value;
// do fancy stuff here with hash_value
// to create the hash value. There's no specific
// requirement on the value.
return hash_value;
}
bool operator()(const MyClass &left, const MyClass &right) {
// this should implement a total ordering on MyClass, that is
// it should return true if "left" precedes "right" in the ordering
}
};
Then, you can just use
stdext::hash_map my_map<MyClass, MyValue, MyClass_Hasher>
Here you go, example from MSDN
I prefer using a non-member function.
The method expained in the Boost documentation article Extending boost::hash for a custom data type seems to work.

Resources