TypeError: Type address is not implicitly convertible to expected type uint256 [closed] - blockchain

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I am beginner in solidity and I have to complete this smart contract but my mind is stuck while coding. Please help...
```
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
contract Farmer {
uint public f_index = 0;
struct far{
uint id;
string name;
string phone;
string gender;
string dob;
string bloodgroup;
address addr;
Records[] records;
}
struct Records{
string cropName;
string useableLand;
string seedCost;
string seedQuantity;
string fertilizerCost;
string fertilizerQuantity;
string sprayCost;
string sprayQuantity;
string harvestCost;
string laborCost;
}
address[] private farmerList;
mapping(address => mapping(address => bool)) isAuth;
mapping(address => far) farmers;
mapping(address => bool) isFarmer;
function addRecord(address _addr, Records memory record) public{
far memory Far = farmerList[_addr];
}
}
```

farmerList is an array of address type. To access an array you need to put in the index of the array which is a number/uint type. So you can not access the farmer array with an address type which is why you are getting the error. Instead of
far memory Far = farmerList[_addr];
Would be something like:
function addRecord(Records memory recordm, uint256 index) public{
address farmerAddress = farmerList[index];
far memory Far = farmers[farmerAddress];
}

As #Tahlil say "To access an array you need to put in the index". In addition, a few more suggestions to help you get out of the stuck:
Normally mapping is more recommended, however if you need to iterate over elements or return a list then you need to consider using enclosing array, like this:
mapping(address => far) farmers;
address[] private farmerList;
So, in functions you can access a farmer in mapping by put in address _addr
far memory Far = farmers[_addr];
And loop throught farmers like this
uint length = farmerList.length;
for(uint i; i<length; i++) {
far memory Far = farmers[farmerList[i]];
//...
}

Related

How a struct is taking an empty array and later how an address is going to be put there?

As far I know, new address[](number) creates an fixed sized array of that number initialized with zero. But how in this line Room memory room = Room(new address[](0), 0, 0); Room struct is taking an empty array and later how an address is going to be put there?
pragma solidity ^0.4.18;
contract StructArrayInit {
event OnCreateRoom(address indexed _from, uint256 _value);
struct Room {
address[] players;
uint256 whosTurnId;
uint256 roomState;
}
Room[] public rooms;
function createRoom() public {
Room memory room = Room(new address[](0), 0, 0);
rooms.push(room);
rooms[rooms.length-1].players.push(msg.sender);
OnCreateRoom(msg.sender, 0);
}
function getRoomPlayers(uint i) public view returns (address[]){
return rooms[i].players;
}
}
In this statement:
Room memory room = Room(new address[](0), 0, 0);
rooms.push(room);
In the first line, he declared a Room struct variable with the following value: 0,0 and 0.
This means that players, whosTurnId, roomState struct variable have zero values.
With the second line, he pushed inside rooms array, Room struct variable created previously.
With this statement:
rooms[rooms.length-1].players.push(msg.sender);
he took the last element of array (what he has entered) then push inside players array inside Room struct the msg.sender value.
If you want to insert more address inside players array, you can use this statement:
rooms[rooms.length-1].players.push([address]);

Called function suddenly needs to be payable

I have a public uint variable denoting 'which round' it is and a function that advances rounds and does processing alongside the round advancement:
uint public round;
function completeRound() public inPaused() inRound() {
if (round == 6) {
// win
} else {
reduceByHalf();
round.add(1);
}
}
If i run this in remix, it runs 4 times and then consistently fails on the 5th, indicating that a function suddenly needs to be payable:
transact to Playingwithsmartcontracts.completeRound errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.
If I comment out round.add(1) right under where reduceByHalf is called, the code works all day long. I can click it indefinitely with no errors in Remix.
Strangely, this started as an Enum to track the rounds and that had the same exact problem. While advancing the enum, i could do it 5 times before the above failure and commenting it out made everything work.
reduceByHalf code doesnt seem to be the offender, but it is shown below in case it has a bearing on the problem:
struct Foo {
address owner;
uint mintedRound;
uint winningRound;
}
struct FooOwner {
uint[] foos;
uint totalWinningFoos;
}
uint[][5] roundFoos;
uint[][5] roundWinners;
mapping(uint => Foo) public winningFoos;
mapping(address => FooOwner) public fooOwners;
uint totalWinningFoos;
function shuffleFoos (uint256[] memory _array) internal view returns(uint[] memory){
uint[] memory clone = cloneArray(_array, _array.length);
for (uint256 i = 0; i < clone.length; i++) {
uint256 n = i + uint256(keccak256(abi.encodePacked(msg.sender, block.timestamp))) % (clone.length - i);
uint256 temp = clone[n];
clone[n] = clone[i];
clone[i] = temp;
}
return clone;
}
function cloneArray(uint256[] memory _array, uint256 _length) internal pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](_length);
for (uint256 i = 0; i < _length; i++) {
array[i] = _array[i];
}
return array;
}
function reduceByHalf() internal {
uint[] memory clone = shuffleFoos(roundFoos[round]);
uint halfLength = 0;
halfLength = roundFoos[round].length.div(2);
for (uint w = 0; w < halfLength; w++) {
uint fooId = clone[w];
roundWinners[round].push(fooId);
winningFoos[round].winningRound = round;
address fooOwner = winningFoos[fooId].owner;
fooOwners[fooOwner].totalWinningFoos = fooOwners[fooOwner].totalWinningFoos.add(1);
}
totalWinningFoos = totalWinningFoos.add(halfLength);
}
As far as I know, I am not sending value, and not sure why it only thinks im sending value on transaction execution 5.
Would anyone be able to help me understand what Remix/Solidity is mad about?
I totally must not be understanding somehthing but it looks like it's something about the number 5... I can advance the round to 6, but as soon as I set the uint value to 5 is when I start seeing these problems.... so wierd....
The transaction has been reverted to the initial state.
This is the important part of the error message in your case.
Note: The called function should be payable if you send value
This is just a note, possibly because this combination often happens. But since your function and transaction doesn't send any value, it doesn't apply to your case.
round.add(1);
This (failing) snippet suggests, that there's supposed to be a library used for uint, but it's not defined. I'm gonna go with the SameMath library, because of the .add() function name and the use on uint. But in theory, it could be any library, SafeMath is just the most probable option in this context.
Mind that round.add(1); (using SafeMath) returns the value of round incremented by 1, but it doesn't store the (incremented) value anywhere. This looks like a typo and the real usage should be round = round.add(1);
Your code doesn't show any usage of the SafeMath library, but also doesn't show the Solidity version, so I'm going to divide my answer into 3 parts.
You're using Solidity 0.8+.
SameMath is not needed, because integer overflow is handled on a lower level, and you can safely replace
// even with correctly imported SafeMath, it doesn't update the stored value
round.add(1);
to
// updates the stored value
round++;
You're using Solidity 0.7 or older, and SafeMath for uint256 (not uint)
Change the definition
uint public round;
to
uint256 public round;
This way, SafeMath will be used for round and it will allow to use the function .add().
Mind that you might want to also store the incremented value, see the bold paragraph with example above.
You're using Solidity 0.7 or older, and not using SafeMath at all.
You need to import the SafeMath library and then make changes described in the point 2.

Warning to use encapsulated functions [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have problem to sort array with objects which are private and they are encapsulated(have getter and setters).I am using my own bubble sort function.
void BubbleSort(apvector <int> &num)
{
int i, j, flag = 1;
int temp;
int numLength = num.length( );
for(i = 1; (i <= numLength) && flag; i++)
{
flag = 0;
for (j=0; j < (numLength -1); j++)
{
if (num[j+1] > num[j])
{
temp = num[j];
num[j] = num[j+1];
num[j+1] = temp;
flag = 1;
}
}
}
The problem is there that eclipse IDE sends me warning to use getters and setter in declaration of my class.
Why is better to use getters and setters?
P.S
Sorry for my bad asked question(this was one of my first questions) :)
void bubbleSort(Student* student, int size)
{ [...] }
Variable student is a pointer to an array.
You must also specific the size of the array.
To call it:
Student* myClass=new Student[5];
bubbleSort(myClass, 5); // Pass the array, and the size of the array both.
You need to create the said array before sending it as a parameter to the function. Alternatively you can create it inside the function but I think it's not what you want to go for here.
Student* students = new Student[5];
You should have written this somewhere before calling your function. Then, your function signature will have to turn to the following:
void bubbleSort(Student* student)
A logical thing to do would be to use a std::vector here though, it's much better than the method you're going for. See: http://en.cppreference.com/w/cpp/container/vector

pointers and references, room "has-a" key [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I basically want to say, if the current room contains a key, which I have assigned below, then tell the user, the room has a key and I'll figure the rest out.
int main()
{
Room mainHall;
Room sittingRoom;
mainHall.setNorthExit(&sittingRoom);
mainHall.setEastExit(&playRoom);
mainHall.setDescription("The main hall has 2 exits, one to the north, one to the east");
mainHall.setName("Main Hall");
sittingRoom.setEastExit(&kitchen);
sittingRoom.setSouthExit(&mainHall);
sittingRoom.setDescription("The sitting room has 2 exits, one to the east and one to the south");
sittingRoom.setName("Sitting Room");
string userInput;
Room* currentRoom;
currentRoom = &mainHall;
Keys& key1 = playRoom.getKey();
key1.setName("Sitting Room");
Keys& key2 = sittingRoom.getKey();
key2.setName("Play Room");
if(////need code here) ///I want it to be something like...if(currentRoom "has a key"
{
string takeKey;
cout << "There is still a key in this room, would you like to take it? " << endl;
cin >> takeKey;
if(takeKey == "yes")
{
//Havent assigned anything yet
}
}
This is just the cpp file of my keye class just in case you need it
#include"Keys.h"
#include<iostream>
Keys::Keys()
{
name = "";
}
Keys::Keys(string nameParam)
{
name = nameParam;
}
void Keys::setName(string nameParam)
{
name = nameParam;
}
string Keys::getName() const
{
return name;
}
void Keys::setKey(string keyParam)
{
key = keyParam;
}
string Keys::getKey() const
{
return key;
}
As well as a getter method in my rooms class
Keys& Room::getKey()
{
return key;
}
I'd appreciate any help
How about a 'HasKey()' method on the room class, then use
if( sittingRoom.HasKey()) { ... }
Use a boolean in the room class to determine if the room has a key.

Passing a Structure containing an array of String and an array of Integer into a C++ DLL

I'm having problems with marshaling in VB.NET to C++, here's the code :
In the C++ DLL :
struct APP_PARAM
{
int numData;
LPCSTR *text;
int *values;
};
int App::StartApp(APP_PARAM params)
{
for (int i = 0; i < numLines; i++)
{
OutputDebugString(params.text[i]);
}
}
In VB.NET :
<StructLayoutAttribute(LayoutKind.Sequential)> _
Public Structure APP_PARAM
Public numData As Integer
Public text As System.IntPtr
Public values As System.IntPtr
End Structure
Declare Function StartApp Lib "AppSupport.dll" (ByVal params As APP_PARAM) As Integer
Sub Main()
Dim params As APP_PARAM
params.numData = 3
Dim text As String() = {"A", "B", "C"}
Dim textHandle As GCHandle = GCHandle.Alloc(text)
params.text = GCHandle.ToIntPtr(textHandle)
Dim values As Integer() = {10, 20, 30}
Dim valuesHandle As GCHandle = GCHandle.Alloc(values)
params.values = GCHandle.ToIntPtr(heightHandle)
StartApp(params)
textHandle.Free()
valuesHandle.Free()
End Sub
I checked the C++ side, the output from the OutputDebugString is garbage, the text array contains random characters. What is the correct way to do this?
GCHandle.Alloc "Allocates a Normal handle for the specified object", which "creates a handle to a managed object ... which prevents the managed object from being collected".
What you're looking for is the methods from System.Runtime.InteropServices.Marshal, which allow you to do things like copy managed objects to memory accessible by unmanaged code. Unfortunately, according to this, the pointers in your struct make it a little harder to marshal than many other things (in the sense that many other things can be automatically marshalled using the appropriate P/Invoke attributes), but it's still possible. I've tried this out and it works:
APP_PARAM param = new APP_PARAM();
string[] text = new string[] { "A", "B", "C" };
param.numData = text.Length;
// Manually allocate an array of pointers, one for each string. arr holds the array's address.
IntPtr arr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * text.Length);
try
{
param.text = arr;
IntPtr[] unmanagedText = new IntPtr[text.Length];
try
{
// Create a null-terminated ANSI string in unmanaged memory for each element in text.
for (int i = 0; i < text.Length; i++)
unmanagedText[i] = Marshal.StringToHGlobalAnsi(text[i]);
// Copy the addresses of the unmanaged strings into the manually allocated array.
// I don't know of any way to make an unmanaged copy of a managed array in one call.
Marshal.Copy(unmanagedText, 0, arr, unmanagedText.Length);
// param now looks like what the C++ code is expecting (except for the array of int).
StartApp(param);
}
finally
{
foreach (IntPtr str in unmanagedText)
Marshal.FreeHGlobal(str);
}
}
finally
{
Marshal.FreeHGlobal(arr);
}
You'll have to have similar allocation/free code for your array of int values, with its own try/finally blocks to make sure FreeHGlobal is called.
You need to use one of the methods from the Marshal class.
Dim str As String = "Hello World"
Dim ptr as IntPtr = Marshal.StringToHGlobalAnsi(str)
Try
SomePInvokeCall(ptr)
Finally
Marshal.FreeHGlobal(ptr)
End Try