【问题标题】:String concatenation in solidity?Solidity中的字符串连接?
【发布时间】:2015-11-16 10:06:53
【问题描述】:

如何在solidity中连接字符串?

var str = 'asdf'
var b = str + 'sdf'

好像不行..

我查阅了文档 (https://github.com/ethereum/wiki/wiki/Solidity-Tutorial#elementary-types-value-types),没有太多关于字符串连接的提及。 但据说它与点 ('.') 一起使用?

"[...] a mapping key k is located at sha3(k . p) where . is concatenation."

对我也没有用.. :/

【问题讨论】:

  • 作为一般建议,通常(并非总是)你可以设计你的程序,这样你就不需要在 Solidity 中进行字符串连接或任何字符串操作。智能合约和区块链虚拟机不适用于字符串操作,因此使用更智能的架构可以避免这种情况。

标签: ethereum solidity


【解决方案1】:

Ethereum Stack Exchange:的回答

可以使用library,例如:

import "github.com/Arachnid/solidity-stringutils/strings.sol";

contract C {
  using strings for *;
  string public s;

  function foo(string s1, string s2) {
    s = s1.toSlice().concat(s2.toSlice());
  }
}

将上述内容用于quick test,您可以根据需要进行修改。


由于concatenating strings needs to be done manually for now,并且在合约中这样做可能会消耗不必要的gas(必须分配新字符串,然后写入每个字符),值得考虑什么用例需要字符串连接?

如果 DApp 可以编写成前端连接字符串,然后将其传递给合约进行处理,这可能是一个更好的设计。

或者,如果合约想要散列单个长字符串,请注意 Solidity 中的所有内置散列函数(sha256、ripemd160、sha3)采用可变数量的参数,并将执行在计算哈希之前连接。

【讨论】:

  • 我用s字符串部署了智能合约,如何读取字符串?
  • @TomaszWaszczyk 如果字符串是public,则使用它的访问器,否则合约需要一个返回字符串的函数。如果您正在“调用”智能合约功能,这可能会有所帮助ethereum.stackexchange.com/questions/765/…,因为“调用”智能合约有不同的方式。
【解决方案2】:

您不能连接字符串。你也不能检查等于(str0 == str1)。字符串类型是最近才重新添加到语言中的,因此可能需要一段时间才能完成所有这些工作。您可以做的(他们最近添加的)是使用字符串作为映射的键。

您指向的连接是如何根据字段类型等计算存储地址,但这由编译器处理。

【讨论】:

  • 此答案不再是最新的。看看其他的。
【解决方案3】:

这是在 Solidity 中连接字符串的另一种方法。在这个tutorial中也有显示:

pragma solidity ^0.4.19;

library Strings {

    function concat(string _base, string _value) internal returns (string) {
        bytes memory _baseBytes = bytes(_base);
        bytes memory _valueBytes = bytes(_value);

        string memory _tmpValue = new string(_baseBytes.length + _valueBytes.length);
        bytes memory _newValue = bytes(_tmpValue);

        uint i;
        uint j;

        for(i=0; i<_baseBytes.length; i++) {
            _newValue[j++] = _baseBytes[i];
        }

        for(i=0; i<_valueBytes.length; i++) {
            _newValue[j++] = _valueBytes[i];
        }

        return string(_newValue);
    }

}

contract TestString {

    using Strings for string;

    function testConcat(string _base) returns (string) {
        return _base.concat("_Peter");
    }
}

【讨论】:

  • 第二个for循环有错误,应该是_newValue[j++] = _valueBytes[i];
【解决方案4】:

You have to do it manually for now

Solidity 不提供内置的字符串连接和字符串比较。
但是,您可以找到实现字符串连接和比较的库和协定。

StringUtils.sol 库实现字符串比较。
Oraclize contract srtConcat function 实现字符串连接。

如果您需要连接以获取结果字符串的哈希,请注意 Solidity 中有内置的哈希函数:sha256、ripemd160、sha3。它们采用可变数量的参数并在计算哈希之前执行连接。

【讨论】:

    【解决方案5】:

    您可以利用abi.encodePacked:

    bytes memory b;
    
    b = abi.encodePacked("hello");
    b = abi.encodePacked(b, " world");
    
    string memory s = string(b);
    // s == "hello world"
    

    【讨论】:

      【解决方案6】:

      您可以使用solidity 的低级功能非常轻松地做到这一点 abi.encodePacked(str,b)

      要记住的重要一点是,首先将其类型转换为字符串,即: string(abi.encodePacked(str, b))

      你的函数会返回

      return string(abi.encodePacked(str, b));
      

      它既简单又省油:)

      【讨论】:

        【解决方案7】:

        我使用这种方法来连接字符串。希望对您有所帮助

        function cancat(string memory a, string memory b) public view returns(string memory){
                return(string(abi.encodePacked(a,"/",b)));
            }
        

        【讨论】:

          【解决方案8】:

          上面的例子并不完美。 例如,尝试连接这些值

          ["10","11","12","13","133"] 你会得到 ["1","1","1","1","13"]

          有一些错误。

          而且你也不需要使用图书馆。因为图书馆对它来说非常庞大。

          使用这个方法:

          function concat(string _a, string _b) constant returns (string){
              bytes memory bytes_a = bytes(_a);
              bytes memory bytes_b = bytes(_b);
              string memory length_ab = new string(bytes_a.length + bytes_b.length);
              bytes memory bytes_c = bytes(length_ab);
              uint k = 0;
              for (uint i = 0; i < bytes_a.length; i++) bytes_c[k++] = bytes_a[i];
              for (i = 0; i < bytes_b.length; i++) bytes_c[k++] = bytes_b[i];
              return string(bytes_c);
          }
          

          【讨论】:

            【解决方案9】:

            您可以使用 ABI 编码器执行此操作。 Solidity 不能自然地连接字符串,因为它们是动态大小的。您必须将它们散列到 32 字节。

            pragma solidity 0.5.0;
            pragma experimental ABIEncoderV2;
            
            
            contract StringUtils {
            
                function conc( string memory tex) public payable returns(string 
                               memory result){
                    string memory _result = string(abi.encodePacked('-->', ": ", tex));
                    return _result;
                }
            
            }
            

            【讨论】:

              【解决方案10】:

              与 Python 和 JavaScript 等语言相比,在 Solidity 中没有直接的方法可以做到这一点。我会做类似下面的事情来连接两个字符串:

              //SPDX-License-Identifier: GPL-3.0
               
              pragma solidity >=0.7.0 < 0.9.0;
              
              contract test {
                  function appendStrings(string memory string1, string memory string2) public pure returns(string memory) {
                      return string(abi.encodePacked(string1, string2));
                  }
              }
              

              请查看下面的屏幕截图,了解在 Remix Ethereum IDE 中连接两个字符串('asdf' 和 'sdf')的结果。

              【讨论】:

                【解决方案11】:

                Solidity 不提供连接字符串的本地方式,因此我们可以使用 abi.encodePacked()。更多信息请参考Doc Link

                // SPDX-License-Identifier: GPL-3.0
                
                    pragma solidity >=0.5.0 <0.9.0;
                
                
                   contract AX{
                      string public s1 = "aaa";
                      string public s2 = "bbb";
                      string public new_str;
                 
                      function concatenate() public {
                         new_str = string(abi.encodePacked(s1, s2));
                       } 
                    }
                

                【讨论】:

                  猜你喜欢
                  • 2021-07-22
                  • 2017-07-31
                  • 1970-01-01
                  • 2014-03-31
                  • 2017-04-24
                  • 1970-01-01
                  • 2018-03-06
                  • 2013-12-14
                  • 2023-03-09
                  相关资源
                  最近更新 更多