web-dev-qa-db-ja.com

文字列連結を強固に?

文字列を確実に連結するにはどうすればよいですか?

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."

私もうまくいかなかった..:/

17
tObi

文字列を連結することはできません。また、等しい(str0 == str1)まだです。文字列型は最近言語に追加されたばかりなので、これがすべて機能するまでにはしばらく時間がかかるでしょう。 (最近追加された)できることは、マッピングのキーとして文字列を使用することです。

あなたが指している連結は、フィールドタイプなどに基づいてストレージアドレスが計算される方法ですが、それはコンパイラによって処理されます。

17

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());
  }
}

上記を クイックテスト に使用し、必要に応じて変更できます。


今のところ、文字列の連結は手動で行う必要があります であり、契約でそうすることは不要なガスを消費する可能性があるため(新しい文字列を割り当ててから各文字を書き込む必要があります)、ユースケースを検討する価値があります文字列の連結が必要ですか?

フロントエンドが文字列を連結し、それを処理のためにコントラクトに渡すような方法でDAppを記述できる場合、これはより良い設計になる可能性があります。

または、コントラクトで単一の長い文字列をハッシュしたい場合は、Solidity(sha256ripemd160sha3)可変数の引数を取り、ハッシュを計算する前に連結を実行します。

18
eth

今のところ手動で行う必要があります

Solidityは組み込みの文字列連結と文字列比較を提供しません。
ただし、文字列の連結と比較を実装するライブラリとコントラクトを見つけることができます。

StringUtils.sol ライブラリは文字列比較を実装します。
OraclizeコントラクトsrtConcat関数 は文字列連結を実装します。

結果の文字列のハッシュを取得するために連結が必要な場合は、Solidityに組み込みのハッシュ関数があることに注意してください:sha256ripemd160sha3。それらは可変数の引数を取り、ハッシュを計算する前に連結を実行します。

9

Solidityで文字列を連結する別の方法を次に示します。これもこの チュートリアル に示されています。

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");
    }
}
8
baermathias

abi.encodePacked

bytes memory b;

b = abi.encodePacked("hello");
b = abi.encodePacked(b, " world");

string memory s = string(b);
// s == "hello world"
1
Justin

上記の例は完全には機能しません。たとえば、これらの値を連結してみてください

["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);
}