Имея два контракта следующим образом, контракт TestData
вызывает контракт Reg
для извлечения данных, которые уже были сохранены в его карте, с помощью get_attributes
функции.
pragma solidity ^0.4.21;
contract Reg {
mapping (address=>bytes32[5]) Map;
//Filling the map
function fill_map(bytes32[5] _attributes) public {
Map[msg.sender] = _attributes;
}
//Returns data in the map corresponding to an address
function get_attributes(address _id) view public returns (bytes32[5]){
return Map[_id];
}
}
contract TestData {
address Address;
function get_address (address _Address) public{
Address = _Address;
}
//Retreive data from Reg contract
bytes32[5] fetched;
function fetch(address _reg_Adress) public view returns (bytes32[5]) {
Reg r = Reg(_reg_Adress);
fetched = r.get_attributes(Address);
return (fetched);
}
//Retreive input data from user
bytes32[5] inputs;
function getInputs(bytes32[5] _inputs) public view returns (bytes32[5]){
inputs = _inputs;
return (inputs);
}
//Compare input data with fetched data
bool[5] a = [false,false,false,false,false];
function compare() public view returns(bool[5]){
for(uint i=0;i<5;i++){
for(uint j=0;j<5;j++){
if(inputs[i] == fetched[j]){
a[i] = true;
}
}
}
return (a);
}
}
Вот как я это тестирую:
Заполните карту["0x0","0x1","0x2","0x3","0x4"]
Для пользовательского ввода я также ввожу["0x0","0x1","0x2","0x3","0x4"]
Выход правильный return [true,true,true,true,true]
.
Однако, если я изменю ввод, скажем, ["0xA","0x1","0x2","0x3","0x4"]
, вывод останется, [true,true,true,true,true]
хотя он должен быть [false,true,true,true,true]
.
Что-то происходит с данными, когда они извлекаются из контракта Reg? Когда я пытаюсь протестировать тот же код, но с двумя входными массивами, а не с выборкой данных, он работает нормально.
Кроме того, я искал другие способы сделать сравнения. Есть ли другой эффективный способ, кроме цикла?
Функция compare
почти правильная, ошибки в другом месте
function fetch(address _reg_Adress) public view returns (bytes32[5])
надо удалить view
отсюда
function getInputs(bytes32[5] _inputs) public view returns (bytes32[5])
тоже отсюда.
Затем переместите свой массив в функцию и определите его как память.
//Compare input data with fetched data
function compare() public view returns(bool[5]){
bool[5] memory a = [false,false,false,false,false];
for(uint i=0;i<5;i++){
for(uint j=0;j<5;j++){
if(inputs[i] == fetched[j]){
a[i] = true;
}
}
}
return (a);
}
если нет, вы должны удалить view
также из метода compare
, чтобы он работал
после этого изменения результат будет false,true,true,true,true
таким, как ожидалось.
Есть несколько проблем:
Сначала ваш for
цикл останавливается рано, в 3, когда предел должен быть i<5.
И твой второй for
не нужен. Ваша функция может быть:
function compare() public view returns(bool[5]){
bool[5] memory a;
for(uint i=0;i<5;i++){
for(uint j=0;j<5;j++){
if(inputs[i] == fetched[j]){
a[i] = true;
}
}
}
return (a);
}
Вы также можете сделать следующее, чтобы убедиться, a
что оно обновляется, когда значения истинны или ложны:
function compare() public view returns(bool[5]){
bool[5] memory a;
for(uint i=0;i<5;i++){
for(uint j=0;j<5;j++){
a[i] = (inputs[i] == fetched[j]);
}
}
return (a);
}
наконец, ваши функции изменяют переменные состояния, поэтому их нельзя просмотреть.
Надеюсь это поможет
ОБНОВЛЕНИЕ: Полный код.
pragma solidity ^0.4.21;
contract Reg {
mapping (address=>bytes32[5]) public Map;
//Filling the map
function fill_map(bytes32[5] _attributes) public {
Map[msg.sender] = _attributes;
}
//Returns data in the map corresponding to an address
function get_attributes(address _id) view public returns (bytes32[5]){
return Map[_id];
}
}
contract TestData {
address Address;
function get_address (address _Address) public{
Address = _Address;
}
//Retreive data from Reg contract
bytes32[5] public fetched;
function fetch(address _reg_Adress) public returns (bytes32[5]) {
Reg r = Reg(_reg_Adress);
fetched = r.get_attributes(Address);
return (fetched);
}
//Retreive input data from user
bytes32[5] public inputs;
function getInputs(bytes32[5] _inputs) public returns (bytes32[5]){
inputs = _inputs;
return (inputs);
}
//Compare input data with fetched data
function compare() public view returns(bool[5]){
bool[5] memory a;
for(uint i=0;i<5;i++){
for(uint j=0;j<5;j++){
if(inputs[i] == fetched[j]){
a[i] = true;
}
}
}
return (a);
}
}
a
все верно. Затем вы попробовали что-то, что дает false
, но ваш код обновляется только a
тогда, когда истинно, поэтому истинное значение не изменяется. Поместив его внутрь, инициализируйте значение false при выполнении функции. Дайте мне знать
пользователь19510
i<5
иj<5
? Вы останавливаетесь после сравнения 3 элементов.блокчейнент
пользователь19510
пользователь19510
compare
как транзакция? Если это так, он будет постоянно изменятьa
, и последующие вызовы будут наследовать значения там. (Как только для элемента установлено значениеtrue
, он никогда не вернется назад.) Вероятно, вам все равно следует просто переместить объявлениеa
внутрьcompare()
.пользователь19510
input
соответствует ли каждый элемент любому элементуfetched
. Если вы хотите сопоставить только соответствующие элементы, вам нужно отказаться от внутреннего цикла, как это предлагается в этом ответе.блокчейнент