Ich weiß, dass ich dynamische Byte-Arrays in Solidity zurückgeben kann, wie im folgenden Code:
function createMemoryArray(uint size) returns (bytes) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
b[i] = byte(i);
return b;
}
Aber gibt es eine Möglichkeit, so etwas wie ein dynamisches Array von Zeichenfolgen zurückzugeben? Ich habe das Gefühl, dass dies nur ein Implementierungsdetail in Solidity ist, aber es wäre großartig, wenn es einfach alles schön für mich serialisieren würde.
Noch nicht, da dies zwei Ebenen dynamischer Arrays erfordert (String ist selbst ein dynamisches Array). Dok
Sie können jedoch ein Array of Bytes32 (feste Größe von 32 Byte) zurückgeben. Sie können also versuchen, so etwas zu tun (Sie können Remix kopieren und einfügen , um es zu testen) .
pragma solidity ^0.4.11;
contract ArrayOfBytes32 {
address creator;
bytes32[10] bytesArray; // size must be fixed
function ArrayRR()
{
creator = msg.sender;
uint8 x = 0;
while(x < bytesArray.length)
{
bytesArray[x] = "myString";
x++;
}
}
function getArray() constant returns (bytes32[10])
{
return bytesArray;
}
function getValue(uint8 x) constant returns (bytes32)
{
return bytesArray[x];
}
}
Beachten Sie, dass Sie web3.toAcsii()
doc verwenden müssen , um das Ergebnis zu konvertieren, wenn Sie web3 verwenden, um mit Ihrem Vertrag zu interagieren
Es ist ein altes Problem ... Aber für Neulinge und der Vollständigkeit halber gibt es in Solidity keine Probleme, dynamische Arrays von Paaren oder dynamische Arrays von Strings zurückzugeben, wenn man den modernen Compiler (getestet mit 0.5.6
) und das experimentelle ABI-Pragma verwendet :
pragma experimental ABIEncoderV2;
...
function createMemoryArray(uint size) public pure returns (uint[2][] memory) {
uint[2][] memory b = new uint[2][](size);
for (uint i=0; i < b.length; i++) {
b[i][0] = i;
b[i][1] = i * 2;
}
return b;
}
function createStringArray(uint size) public pure returns (string[] memory) {
string[] memory b = new string[](size);
for (uint i=0; i < b.length; i++) {
b[i] = "test";
}
return b;
}
Gibt dynamische Arrays der Struktur in einer Funktion zurück
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
contract Money {
struct People{
uint id;
string name;
uint amount;
}
mapping (uint => People) public peoples;
event votedEvent(uint indexed _candidateId);
uint public candidateConut;
constructor() public {
candidateConut = 0;
addCandidate("Holder 1");
addCandidate("Holder 2");
}
function addCandidate(string memory _name) public {
peoples[candidateConut] = People(candidateConut,_name,0);
candidateConut++;
}
//return Single structure
function get(uint _candidateId) public view returns(People memory) {
return peoples[_candidateId];
}
//return Array of structure Value
function getPeople() public view returns (uint[] memory, string[] memory,uint[] memory){
uint[] memory id = new uint[](candidateConut);
string[] memory name = new string[](candidateConut);
uint[] memory amount = new uint[](candidateConut);
for (uint i = 0; i < candidateConut; i++) {
People storage people = peoples[i];
id[i] = people.id;
name[i] = people.name;
amount[i] = people.amount;
}
return (id, name,amount);
}
//return Array of structure
function getPeoples() public view returns (People[] memory){
People[] memory id = new People[](candidateConut);
for (uint i = 0; i < candidateConut; i++) {
People storage people = peoples[i];
id[i] = people;
}
return id;
}
}
Ist es möglich, ein dynamisches Array von Zeichenfolgen ( string[] ) von einer Solidity-Funktion zurückzugeben?
Ja, Sie können es in Bytes serialisieren und wieder in string[] deserialisieren.
In Ihrem Smart Contract:
function toBytes(string[] strArray)
private
pure
returns(bytes serialized) {
uint startindex = 0;
uint endindex = strArray.length - 1;
require(endindex >= startindex);
if (endindex > (strArray.length - 1)) {
endindex = strArray.length - 1;
}
//64 byte is needed for safe storage of a single string.
//((endindex - startindex) + 1) is the number of strings we want to pull out.
uint offset = 64 * ((endindex - startindex) + 1);
bytes memory buffer = new bytes(offset);
string memory out1 = new string(32);
for (uint i = startindex; i <= endindex; i++) {
out1 = strArray[i];
stringToBytes(offset, bytes(out1), buffer);
offset -= sizeOfString(out1);
}
return (buffer);
}
function stringToBytes(uint _offst, bytes memory _input, bytes memory _output)
private
pure {
uint256 stack_size = _input.length / 32;
if (_input.length % 32 > 0) stack_size++;
assembly {
stack_size: = add(stack_size, 1) //adding because of 32 first bytes memory as the length
for {
let index: = 0
}
lt(index, stack_size) {
index: = add(index, 1)
} {
mstore(add(_output, _offst), mload(add(_input, mul(index, 32))))
_offst: = sub(_offst, 32)
}
}
}
function sizeOfString(string memory _in)
private
pure
returns(uint _size) {
_size = bytes(_in).length / 32;
if (bytes(_in).length % 32 != 0)
_size++;
_size++; // first 32 bytes is reserved for the size of the string
_size *= 32;
}
}
Verwenden Sie dann die folgende Funktion, um es zurück zu string[] (mit js) zu deserialisieren:
function hexBytesToStr(hex) {
let str = '';
for (let i = 0; i < hex.length; i += 2) {
let v = parseInt(hex.substr(i, 2), 16);
if (v) str += String.fromCharCode(v);
}
let params = [];
let res = "";
for (let i = 0; i <= str.length; i++) {
if (str.charCodeAt(i) > 31) {
res = res + str[i];
}
else {
params.push(res);
res = "";
}
}
params.pop();
return params;
}
Benutzer9402
Robert Zaremba
bytes32[]
) zurückgeben?Robert Zaremba
bytes32[]
) zurückgeben. Was Sie nicht können, ist ein Objekt zurückzugeben, das zwei Ebenen dynamischer Arrays kombiniert.Andrej
Oliver Rydzi
Zeeshan Ahmad Khalil
0x00000000.... ,0x0000000....., ....
in Solidität zurück. Außerdem müssen wir in der neueren Versionmemory
Schlüsselwörter im Rückgabetyp hinzufügen, was meiner Meinung nach das Problem für mich verursacht.