solidity精细化入门 - 字符串类型学习

字符串类型

关键字: string

字符串是UTF-8编码的字节序列,因此它们可以包含任何UTF-8字符。string类型在Solidity中是动态大小的,这意味着它们可以存储任意长度的字符串,但这也意味着处理字符串通常比处理固定大小的数据类型更昂贵,特别是在需要存储到Ethereum区块链上时。

使用方式

声明和初始化字符串变量的基本语法如下: 基本上和大多数语言一样

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract StringExample {

    // 定义字符串
    string public greeting = "Hello, World!";

  
    // 补充一下代码注释部分

    // 这是一个单行注释
    // uint256 public count = 10;
    uint256 public count = 10; // 这也是单行注释,位于代码行的末尾

    /*
        这是一个多行注释它
        可以跨越多行
        你可以用它来临时注释掉一段代码
        uint256 public count = 10;
    */
}

字符串操作

Solidity本身对字符串的内置操作非常有限

比如字符串拼接,下表总结了不同编程语言中字符串拼接的常用方法:

语言

拼接方法

Python

+''.join([str1, str2])

JavaScript

+或 模板字符串${str1}${str2}

Java

+StringBuilder.append()

C#

+String.Concat(str1, str2)

Ruby

+"#{str1}#{str2}"

Swift

+或 字符串插值\()

Go

+fmt.Sprintf

Kotlin

+或 字符串模板$

solidity

使用abi.encodePacked(str1, str2)bytes类型操作,新版可以使用string.concat


可以例如,最简单的字符串操作,将 2 个字符串合并,在Solidity 中都没办法直接通过+号合并,甚至你都不能直接获取字符串的长度。

如果需要进行这些操作,通常需要将字符串转换为bytes类型,或者在合约外部处理字符串逻辑。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


// 字符串例子
contract StringConcatenation {
    // 示例字符串
    string public exampleString = "Hello, World!";

    string public exampleString1 = unicode"Hello, World!哈哈";


    // 获取字符串长度的函数
    // 首先将exampleString转换为bytes类型,这是通过简单地使用bytes(exampleString)实现的。
    // 然后,它返回这个字节序列的.length属性,这就是原始字符串的长度。
  
    // 注意这个计算,不一定就是准确的,对于中文来说
    // 因为这种方法计算的是字符串的字节长度,而不是字符长度。
    // 对于纯ASCII字符串(如示例中的"Hello, World!"),字节长度与字符长度相同。
    // 但是,对于包含多字节字符的UTF-8字符串,字节长度可能会大于字符数量。
    // 例如,一个包含某些表情符号或其他非ASCII字符的字符串可能会占用更多的字节。
    function getStringLength() public view returns (uint256) {
        // 将字符串转换为bytes类型,然后获取其长度

        // 返回13
        // return bytes(exampleString).length;
        // 返回20 , 实际15
        return bytes(exampleString1).length;

    }

    // 拼接两个字符串
    // 使用abi.encodePacked来拼接两个字符串。
    // abi.encodePacked可以接受任意数量的参数,并将它们紧密打包成一个字节序列。
    // 然后,我们通过string()构造函数将结果转换回字符串。

    // 使用string.concat也可以连接字符串
    // 但是需要在Solidity 0.8.11及更高版本中,
    // 以上版本引入了全局string库,其中包含了一个concat函数,
    // 可以用来连接字符串。这是一个内置的、gas效率更高的方法来连接字符串。
  
    // 目前我们还是0.8.0版本没有这个函数
    function concatenate(string memory str1, string memory str2) public pure returns (string memory) {
        return string(abi.encodePacked(str1, str2));
    }

     // 比较两个字符串是否相等
     // 如果散列值相同,那么可以认为字符串相等(尽管理论上存在极小的碰撞概率)
    function isEqual(string memory str1, string memory str2) public pure returns (bool) {
        return keccak256(abi.encodePacked(str1)) == keccak256(abi.encodePacked(str2));
    }
   
}

由于字符串是动态大小的数据类型,处理它们(比如拼接、切片或比较)通常比处理固定大小的数据类型更复杂和更昂贵。

例如: 字符串拼接需要创建一个新的动态数组来存储结果,这个过程涉及到内存分配和多次复制操作,每一步都会消耗gas。

通过以上例子可见在寸土寸金的以太坊网络,处理字符串是多么昂贵

优化建议

  • 对于复杂的字符串操作,考虑在应用层(比如使用JavaScript、Python等)而不是在智能合约中处理。
  • 对于不需要永久存储在区块链上的数据,使用memorycalldata类型来减少存储成本。
  • 在Ethereum智能合约中处理字符串可能会消耗较多的gas,特别是当字符串作为函数参数或者需要在区块链上存储时。

总的来说,虽然字符串操作在Solidity中是可行的,但应该谨慎使用,以避免不必要的高成本。

PS: string 并不是值类型, 他是属于数组后面数组哪里我们也会在讲、

放在这里讲,是为了认识 solidity 与其他语言的区别, 方便更好的学习

注意事项

  • 在Ethereum智能合约中处理字符串可能会消耗较多的gas,特别是当字符串作为函数参数或者需要在区块链上存储时。
  • Solidity中的字符串是不可变的,这意味着一旦字符串被创建,你就不能修改它的内容。如果需要修改字符串,通常的做法是创建一个新的字符串变量。
  • 对于复杂的字符串操作,考虑在应用层(比如使用JavaScript、Python等)而不是在智能合约中处理。

通过了解这些基本概念和限制,你可以更有效地在Solidity合约中使用字符串类型。

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值