• Solidity两个string的比较


    有三种比较方法

    方法一:比较string的哈希值
    方法二:先比较string的长度,再比较每个对应位置的字母是否相同
    方法三:先比较string的长度,再比较string的哈希值
    一.比较string的哈希值

    function hashCompareInternal(string a, string b) internal returns (bool) {
       return keccak256(a) == keccak256(b);
    }

    二.先比较string的长度,再比较每个对应位置的字母是否相同

    function utilCompareInternal(string a, string b) internal returns (bool) {
        if (bytes(a).length != bytes(b).length) {
            return false;
        }
        for (uint i = 0; i < bytes(a).length; i ++) {
            if(bytes(a)[i] != bytes(b)[i]) {
                return false;
            }
        }
        return true;
    }

    三.先比较string的长度,再比较string的哈希值

    function hashCompareWithLengthCheckInternal(string a, string b) internal returns (bool) {
        if (bytes(a).length != bytes(b).length) {
            return false;
        } else {
            return keccak256(a) == keccak256(b);
        }
    }

    四.三种比较方法的gas分析

          在remix上执行也可以看到gas情况,但感觉不准,这里的统计参考:https://blog.csdn.net/xiaomei1xiake2/article/details/81868317

    由以上的测试可知:
          1.当超过两个字母需要比较的时候,哈希方法(方法一和方法三)消耗的gas比较少;
          2.当这两个string的长度不同时,先进行长度比较(方法二和方法三)可以节省将近40%的gas。
          3.先进行长度比较只是多花了3%的gas,但可能可以节省40%的gas。
          4.与使用字母比较(方法二)的方法相比,使用哈希方法(方法一和方法三)gas的消耗比较稳定。使用字母比较的方法消耗gas的数量呈线性增长。

    五.在实际应用中,可以AOP方式,也可以在函数中直接判断

    pragma solidity ^0.4.24;
     
    contract StringComp {
         
        mapping (address => bool) public compareRecord;
         
        bool public checkResult = false;
         
        modifier check(string _str1,string _str2) {
            require(keccak256(abi.encodePacked(_str1)) == keccak256(abi.encodePacked(_str2)));
            _;
        }
         
        // 使用AOP方式check比较两个字符串
        function func1 (string __str1, string __str2) public check(__str1,__str2)  returns(bool)  {
            //  保存调用者的比较结果
            compareRecord[msg.sender] = true;
        } 
         
        // 函数中直接判断
        function compareStr (string _str1, string _str2) public returns(bool) {
            if(keccak256(abi.encodePacked(_str1)) == keccak256(abi.encodePacked(_str2))) {
                // 如果二者相等,使checkResult为true
                checkResult = true;
            }else {
                checkResult = false;
            }
            // 返回checkResult
            return checkResult;
        }
    }

            在这里,有直接用abi.encodePacked进行打包,关于abi.encodePacked方法说明,详见如下:

            详见:https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html

    五.特别说明

            keccak256方法在0.4.2及其下版本不支持,至少需0.4.3版本。 

    附:在remix上运行截图

    1.StrComp.sol

    pragma solidity ^0.4.24;
     
    contract StrComp {
        
        function hashCompareInternal(string a, string b) public returns (bool) {
            return keccak256(a) == keccak256(b);
        }
        
        function utilCompareInternal(string a, string b) public returns (bool) {
            if (bytes(a).length != bytes(b).length) {
                return false;
            }
            for (uint i = 0; i < bytes(a).length; i ++) {
                if(bytes(a)[i] != bytes(b)[i]) {
                    return false;
                }
            }
            return true;
        }
         
         function hashCompareWithLengthCheckInternal(string a, string b) public returns (bool) {
            if (bytes(a).length != bytes(b).length) {
                return false;
            } else {
                return keccak256(a) == keccak256(b);
            }
        }
    }

     2.StringComp.sol

    pragma solidity ^0.4.24;
     
    contract StringComp {
         
        mapping (address => bool) public compareRecord;
         
        bool public checkResult = false;
         
        modifier check(string _str1,string _str2) {
            require(keccak256(abi.encodePacked(_str1)) == keccak256(abi.encodePacked(_str2)));
            _;
        }
         
        // 使用AOP方式check比较两个字符串
        function func1 (string __str1, string __str2) public check(__str1,__str2)  returns(bool)  {
            //  保存调用者的比较结果
            compareRecord[msg.sender] = true;
        } 
         
        // 函数中直接判断
        function compareStr (string _str1, string _str2) public returns(bool) {
            if(keccak256(abi.encodePacked(_str1)) == keccak256(abi.encodePacked(_str2))) {
                // 如果二者相等,使checkResult为true
                checkResult = true;
            }else {
                checkResult = false;
            }
            // 返回checkResult
            return checkResult;
        }
    }

    参考文章:https://blog.csdn.net/xiaomei1xiake2/article/details/81868317

    https://www.liankexing.com/index.php/Question/question_page.html?id=1249

    https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html

    String Equality Comparison

    String patterns github

    remix地址:https://remix.ethereum.org/

  • 相关阅读:
    09-JS的事件流的概念(重点)
    08-jQuery的位置信息
    07-小米导航案例
    python-selector模块
    python--day9--异步IO、数据库、队列、缓存
    python--select多路复用socket
    python--gevent高并发socket
    python--协程
    python--进程锁、进程池
    python--多进程
  • 原文地址:https://www.cnblogs.com/flyingeagle/p/10115287.html
Copyright © 2020-2023  润新知