0

For the function getAllcars, I wanted to return a struct array. However, it seems this cannot be done (yet). I attempted a workaround by using a recursive function which returns the details of each Customer one by one; the uint getCarsID starts at zero and is incremented with each loop until it is greater than the number of customers in the array (CarOwnerID), at which point it resets the value of getCarsID to zero so that it can be used again later.

Remix accepts this code when compiled and doesn't raise any issues when I execute it, but it doesn't actually return anything. I half-expected this not to work anyways, but I can't put my finger on why. Did I miss something? And if this cannot be done, is there another way to return all of the information in a struct array at once?

// <----------------------- END MEMBERS ----------------------->

struct Customer {

address addr;
string custname;
string color;
string make;
uint16 year;
string license;

}


// < -------------------------- CARS -------------------------- >



uint8 CarOwnerID;
Customer[] public carowners;
mapping(address => uint8) addressIndex;
mapping(string => uint8) licenseIndex;


function newCarOwner(address _address, string _custname, string _color, string _make, uint16 _year, string _license) onlyMember public {

carowners.push(Customer(_address, _custname, _color, _make, _year, _license));  

addressIndex[_address] = CarOwnerID;        //Testing to see if we can switch what
CarOwnerID = licenseIndex[_license];        //is on each side of the equation.

CarOwnerID ++;

}


function getCarByAdd(address _address) public view returns(address, string, string, string, uint16, string) {     // We must return each element in the struct 
    return (                                                                                                      // because we cannot return an entire struct (for now)
        carowners[addressIndex[_address]].addr,              // Notice - when returning elements of an array, use "," after each
        carowners[addressIndex[_address]].custname,          // element instead of ";", and put nothing after the last element.
        carowners[addressIndex[_address]].color,
        carowners[addressIndex[_address]].make,
        carowners[addressIndex[_address]].year,
        carowners[addressIndex[_address]].license
        );
}


function getCarByLic(string _license) public view returns(address, string, string, string, uint16, string) {
    return (
        carowners[licenseIndex[_license]].addr,             // While we can return whole arrays (ex. return carowners[];), and we can return specific indexed items
        carowners[licenseIndex[_license]].custname,         // such as uint returning array[3], array[4], etc., we cannot return a specific item if it is a struct.
        carowners[licenseIndex[_license]].color,            // AKA if array[3] is a struct, we cannot say return array[3], but must say "return array[3].param1, array{3].param2, etc.
        carowners[licenseIndex[_license]].make,             // See DOC1 in NOTES
        carowners[licenseIndex[_license]].year,
        carowners[licenseIndex[_license]].license
        );

}                                                           



 uint8 public getCarsID;

function getAllCars() public returns(address, string, string, string, uint16, string) {
    return (
        carowners[getCarsID].addr,
        carowners[getCarsID].custname,
        carowners[getCarsID].color,
        carowners[getCarsID].make,
        carowners[getCarsID].year,
        carowners[getCarsID].license
        );

        getCarsID ++;

        if (getCarsID <= CarOwnerID) getAllCars;
        else (getCarsID = 0);
}


function countCars() public view returns (uint) {
    return carowners.length;
} 
  • Everything after the return statement is unreachable. Also, you do not want to use, what will default to a storage variable (getCarsID), as your way to index a loop. That is very costly gas wise. – ReyHaynes Jun 3 '18 at 5:26
  • Also, you do not want to use recursion in Solidity, as the stack is very limited and you will reach a stack overflow sooner than later. – goodvibration Jun 3 '18 at 5:39
  • Ahh okay. Good to know. I think I've always heard it discussed in Javascript notes, but assumed it could just as well be done in Solidity. – CreatedAMadman Jun 3 '18 at 20:44
0
function getAllCars() public returns(address, string, string, string, uint16, string) {
return (
    carowners[getCarsID].addr,
    carowners[getCarsID].custname,
    carowners[getCarsID].color,
    carowners[getCarsID].make,
    carowners[getCarsID].year,
    carowners[getCarsID].license
    );

    getCarsID ++;

    if (getCarsID <= CarOwnerID) getAllCars;
    else (getCarsID = 0);

}

This function always returns you the zeroth indexed carowner. The statements after return are not reachable.

You can handle this on your front end or application side. The idea is to call the getCar function one by one. Since you already have countCars() function, call this function and iterate over to get each car owners, append to a list on your front end to perform rest of the task.

function getCar(uint8 index) returns (address, string,string,string,uint16,string){ return ( carowners[index].addr, carowners[index].custname, carowners[index].color, carowners[index].make, carowners[index].year, carowners[index].license ); }

And iterate over this getCar function in your front end.

for(int i=0;i<contractInstance.countCars();i++){
   contractInstance.getCar(i);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.