区块链-智能合约Solidity编程

文章目录

  • 一、ubuntu安装
  • 二、FISCO BCOS安装
  • 五、 WeBASE安装
    • 5.1 WeBASE简介
    • 5.2 节点前置服务搭建
    • 5.3 调用HelloWorld合约
  • 七、Solidity极简入门
    • 7.1. 值类型
    • 7.2. 变量数据存储和作用域
    • 7.3. 函数
    • 7.4 控制流
    • 7.5 数组&映射
    • 7.6 结构体
    • 7.7 修饰符
    • 7.8 事件
    • 7.9 面向对象
    • 7.10 抽象合约
    • 7.11接口合约
    • 7.12 库合约
  • 九、案例
    • 9.1 权限控制合约
    • 9.2 投票合约
    • 9.3 拍卖合约


一、ubuntu安装

# ubuntu系统下载
https://releases.ubuntu.com/18.04.6/
##虚拟机安装好后 root密码用普通用户登录
#sudo passwd初始化

在这里插入图片描述

# 替换镜像源
mv /etc/apt/sources.list /etc/apt/sources.list.backup
# 新建源 参考国内源文档
https://developer.aliyun.com/mirror/ubuntu/
# 操作如下
vim /etc/apt/aources.list
.........
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse 
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
.........
# 更新apt源表
apt update
apt upgrade

二、FISCO BCOS安装

FISCO BCOS 2.0 技术文档
https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/

环境安装:

# 不安装,则start.all会报错:Cannot open file:../crypto/rand/randfile
apt install -y openssl curl

# 不安装 bash console/start.sh 会报错Failed to connect to all the nodes!
apt install -y default-jdk

安装包下载

#借梯子下载好相关的包
#build_chain.sh
https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.11.0/build_chain.sh
# fisco-bcos build_chain.sh脚本中需要的二进制文件
https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.11.0/fisco-bcos.tar.gz 
# console  download_console.sh 脚本中需要的文件
https://github.com/FISCO-BCOS/console/releases/download/v2.9.2/console.tar.gz

执行

# 安装
bash build_chain.sh -l 127.0.0.1:3 -e ./fisco-bcos
bash nodes/127.0.0.1/start_all.sh
# 查看
tail -f nodes/127.0.0.1/node0/log/log_2024092819.29.log |grep +++
tail -f nodes/127.0.0.1/node0/log/log_2024092819.29.log |grep connect

# 控制台安装
tar -xf console.tar.gz
cp -r nodes/127.0.0.1/sdk/* console/conf/
cp -n console/conf/config-example.toml console/conf/config.toml
bash console/start.sh

五、 WeBASE安装

5.1 WeBASE简介

WeBASE(WeBank Blockchain Application Software Extension)是在区块链应用和FISCO-BCOS节点之间搭建的一套通用组件。围绕交易、合约、密钥管理,数据,可视化管理来设计各个模块,开发者可以根据业务所需,选择子系统进行部署。WeBASE屏蔽了区块链底层的复杂度,降低开发者的门槛,大幅提高区块链应用的开发效率,包含节点前置、节点管理、交易链路,数据导出,Web管理平台等子系统

5.2 节点前置服务搭建

vim ~/.bashrc
# 增加 JAVA_HOME 提示报错:java_home不存在
readlink -f $(which java)
.........
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
.........
source ~/.bashrc
echo $JAVA_HOME

## webase-front.zip
https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeBASE/releases/download/v1.5.5/webase-front.zip
unzip webase-front.zip
cd webase-front
cp ../nodes/127.0.0.1/sdk/* ./conf/
bash start.sh
bash status.sh
tail -f log/WeBASE-Front.log |grep success

http://localhost:5002/WeBASE-Front
在这里插入图片描述

也可以使用在线开发环境:
https://remix.ethereum.org/
在这里插入图片描述

5.3 调用HelloWorld合约

HelloWorld合约已经内置于控制台中,位于控制台目录contracts/solidity/HelloWorld.sol

pragma solidity>=0.4.24 <0.6.11;

contract HelloWorld {
    string name;

    constructor() public {
        name = "Hello, World!";
    }

    function get() public view returns (string memory) {
        return name;
    }

    function set(string memory n) public {
        name = n;
    }
}
# 在控制台输入以下指令 部署成功则返回合约地址
[group:1]> deploy HelloWorld
# 调用get接口获取name变量 此处的合约地址是deploy指令返回的地址
[group:1]>call HelloWorld 0xa2bf59b4ca0952464b393947990eaa2e25870587 get
# 调用set设置name
[group:1]>call HelloWorld 0xa2bf59b4ca0952464b393947990eaa2e25870587 set "Hello, FISCO BCOS"

七、Solidity极简入门

Solidity是一门为实现智能合约而创建的面向对象的高级编程语言。 智能合约是管理以太坊中账户行为的程序。

Solidity 是一种面向以太坊虚拟机 (EVM) 的 带花括号的语言。 它受 C++,Python 和 JavaScript 的影响。您可以在 语言的影响因素 部分中找到更多有关 Solidity 受哪些语言启发的细节

7.1. 值类型

pragma solidity 0.6.10;

contract ValueType {
    
    string  _string = "Hello Web3!";
    
    //布尔型
    bool  _bool = true;
    bool  _bool1 = !_bool;   // 取非
    bool  _bool2 = _bool && _bool1; //与
    bool  _bool3 = _bool || _bool1; //或
    bool  _bool4 = _bool == _bool1; //相等 
    bool  _bool5 = _bool != _bool1; //不相等
    
    //整数
    int _int = -1; // 整数
    uint  _uint = 1; // 正整数 uint=uint256
    uint  _num = 17;
    uint  _num1 = _num +2; // 加
    uint  _num2 = _num/3;  //除取整
    uint  _num3 = _num%5;  //取余
    uint  _num4 = _num*3;  //乘
    uint  _num5 = _num**2; //指数
    
    //地址
    address public _address = 0xfBbe31cb73D23Ae79771157c2Bb7C45Cce7C1E18;
    
    // 固定长度 Array
    uint[8] _array1;
    address[100] _array3;
   //定长字节数组
    //长度为1的字节类型
    bytes1 A = 0x01;
  //byte是bytes1的别名
    byte B =0x01;
  //长度为2的字节类型
    bytes2 C= 0xaabb;
    
    bytes1[32] _array2;
    bytes32 _bytes32 = "hellowold";
    bytes1  _bytes1 = _bytes32[0];
       
    // 可变长度 Array
    uint[] array4;
    address[] array6;
    //bytes比较特殊,是数组,不用加[]
   //可以使用bytes或bytes1[]。bytes 比 bytes1[] 省gas
    bytes1[] array5;
    bytes array7;  
    
    // 初始值 
    //如果你在变量声明后添加了public关键字,
    //那么这个变量将自动生成一个与变量名相同的函数,
    //该函数用于获取这个变量的值
    bool public _bool_c; // false
    string public _string_c; // ""
    int public _int_c; // 0
    uint public _uint_c; // 0
    address public _address_c; 
    // 0x0000000000000000000000000000000000000000 (或 address(0))
	//枚举 类比bool
    enum ActionSet { Buy, Hold, Sell}
    ActionSet public _enum_c; // 默认值第1个内容Buy的索引0

    function fi() internal{} // internal空白函数
    function fe() external{} // external空白函数  
}

常量

pragma solidity 0.6.10;
contract ConstantTest {
        // constant变量必须在声明的时候初始化,之后不能改变
    uint256 constant CONSTANT_NUM = 10;
    string constant CONSTANT_STRING = "0xAA";
    bytes constant CONSTANT_BYTES = "WTF";
    address constant CONSTANT_ADDRESS = 0x0000000000000000000000000000000000000000;
    
    // immutable变量可以在constructor里初始化,之后不能改变
    uint256 public immutable IMMUTABLE_NUM = 9999999999;
    address public immutable IMMUTABLE_ADDRESS;
    uint256 public immutable IMMUTABLE_TEST;
    
    // 利用constructor初始化immutable变量,因此可以利用
    constructor() public {
        IMMUTABLE_ADDRESS = address(this);
         IMMUTABLE_TEST = test();
    }
    
    //利用了test()函数给IMMUTABLE_TEST初始化为9
    function test() public pure returns(uint256){
        uint256 what = 9;
        return(what);
    }   
}

枚举和结构体

//可以理解bool的扩展。
pragma solidity 0.6.10;

contract Enum {
    enum Status{
        None,running,stopping,spendding
    }    
    struct Order{
        address buyer;
        Status status;
    }
    
    Status status = Status.running;
    //枚举可以显式地和 uint 相互转换
    function get() external returns(Status) {
       return status;//1
    }
    function set(Status _status) external{
        status = _status;
    }
}

7.2. 变量数据存储和作用域

引用类型(Reference Type):包括数组(array)和结构体(struct),由于这类变量比较复杂,占用存储空间大,我们在使用时必须要声明数据存储的位置。

Solidity数据存储位置有三类:storage,memory和calldata。不同存储位置的gas成本不同。storage类型的数据存在链上,类似计算机的硬盘,消耗gas多;memory和calldata类型的临时存在内存里,消耗gas少。大致用法:

storage:合约里的状态变量默认都是storage,存储在链上。

memory:函数里的参数和临时变量一般用memory,存储在内存中,不上链。尤其是如果返回数据类型是变长的情况下,必须加memory修饰,例如:string,
bytes, array和自定义结构。

calldata:和memory类似,存储在内存中,不上链。与memory的不同点在于calldata变量不能修改(immutable),一般用于函数的参数。

pragma solidity 0.6.10;

contract StorageScope{

    uint[] x = [1,2,3]; // 状态变量:数组 x
    
    function fStorage() public{
        //声明一个storage的变量 xStorage,指向x。修改xStorage也会影响x
        //storage存储
        uint[] storage xStorage = x;
        xStorage[0] = 100;
    }
    
    function get() public returns (uint){
        return x[0];
    }
    // memory存储
     function g(uint[3] memory _data) public pure {
        // ...
    }
}

Solidity中变量按作用域划分有三种,分别是状态变量(state variable),局部变量(local variable)和全局变量(global variable)
状态变量是数据存储在链上的变量,所有合约内函数都可以访问,gas消耗高。状态变量在合约内、函数外声明
局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存.储在内存里,不上链,gas低.
全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:

pragma solidity 0.6.10;

contract StorageScope{
    
    uint public m = 1;
    uint public y;
    string public z;
    
    function foo() external{
    // 可以在函数里更改状态变量的值
        m = 5;
        y = 2;
        z = "0xAA";
    }    
    //局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。
    //局部变量的数据存储在内存里,不上链,gas低。    
    function bar() external  returns(uint){
        uint xx = 1;
        uint yy = 3;
        uint zz = xx + yy;
        return(zz);
    }
    
    //全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:
    function global() external view returns(address, uint, bytes memory){
        address sender = msg.sender;
        uint blockNum = block.number;
        bytes memory data = msg.data;
        return(sender, blockNum, data);
    }
}

7.3. 函数

注意 1:合约中定义的函数需要明确指定可见性,它们没有默认值。

注意 2:public|private|internal也可用于修饰状态变量。public变量会自动生成同名的getter函数,用于查询数值。未标明可见性类型的状态变量,默认为internal

 function  //关键字开头
 //函数名 输入到函数的变量类型和名称
<function name> ( <parameter types>)
//public:内部和外部均可见。
//private:只能从本合约内部访问,继承的合约也不能使用。
//external:只能从合约外部访问(但内部可以通过 this.f() 来调用,f是函数名)。
//internal: 只能从合约内部访问,继承的合约可以用
{internal|external|public|private} 
//pure,中文意思是“纯”,这里可以理解为”纯打酱油的”。pure 函数既不能读取也不能写入链上的状态变量。
//view,“看”,这里可以理解为“看客”。view函数能读取但也不能写入状态变量。
//非 pure 或 view 的函数既可以读取也可以写入状态变量。
[pure|view|payable]
[returns(<return types>)]

在这里插入图片描述

函数返回值

returns:跟在函数名后面,用于声明返回的变量类型及变量名。 return:用于函数主体中,返回指定的变量。

pragma solidity 0.6.10 ;

contract FunctionTypes {
    
    int num = 99;
    //function <function name>(<parameter types>) {internal|external|public|private} 
   //[pure|view|payable] [returns (<return types>)] 方括号中的是可写可不写的关键字
   // pure: 纯纯牛马
    function addPure(uint256 _number) external pure returns(uint256 new_number){
        new_number = _number + 1;
    }
    
    function addView()  external view returns (int) {
        int newnum = num +1;
        return newnum;
    }
    
    function add()  external  returns (int) {
        int num = num +1;
        return num;
    }
    //需要读num值 view
    function viewFunc() external view returns(int){
        return num;
    }
    // 不需要读写num
    function pureFunc()  external pure returns (int){
        return 3+7;
    }
    // internal: 内部函数
    function minus() internal {
        num = num - 1;
    }

    // 合约内的函数可以调用内部函数
    function minusCall() external returns(int) {
        minus();
        return num;
    }
    
    // 返回多个变量
    function returnMultiple() public  returns(uint256, bool, uint256[3] memory,address,address){
        return(1, true, [uint256(1),2,5],address(this),address(0));
    }
    
    // 命名式返回
    function returnNamed() public  returns(uint256 _number, bool _bool, uint256[3] memory _array){
        _number = 2;
        _bool = false;
        _array = [uint256(3),2,1];
    }
    
    // 命名式返回,依然支持return
    function returnNamed2() public pure returns(uint256 _number, bool _bool, uint256[3] memory _array){
        return(1, true, [uint256(1),2,5]);
    }
}

例:计算合约

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.10;

contract Counter {
    int num ;
    
    function inc() external returns (int){
        num = num +1;
        return num;
        //return num +1;//num+1 是另一局部变量,会不自增。
    } 
    //如下 只加1 不更新的.
     function in+1() external returns (int x){
         x = num +1;
    }
    
    function dec() external returns (int){
        num = num -1;
        return num;
    }
}

例:地址变量使用

//声明solidity版本为0.6.10
pragma solidity 0.6.10;
//定义合约
contract AddrTest {
//定义address类型全局变量
    address addr;
//部署合约时设置addr值
    constructor() public{
        addr =0x018020B71d0cACB421483efa5104fD2a8DAe9728;
    }
    
    function getValue() public returns(address){
            return addr;
    }
    //合约地址 和 0
    function getAddress() public returns(address,address){
        return (address(this),address(0));       
    }   
}

7.4 控制流

条件选择

pragma solidity 0.6.10;
contract fenzhi{
    function test(bool condition)public returns(string memory){
//单个条件判断
        if(condition)
            {return "condition true";}
        return "condition false";
    }
    function test2(bool condition) public returns(string memory){
    //当条件不满足时,执行else语句
        if(condition){
            return "condition true";
        } else {
            return "condition false";
        }
    }
    function test3(bool condition, bool condition2) public returns (string memory){
    //else语句可以结合if连续判断
        if(condition){
            return "condition true";
        }
        else if(condition2){
            return"condition2 true";
        } else {
            return "all false";
        }
    }
    
    function test5(bool condition)public returns(string memory){
        //条件?条件为true时的返回:条件为false时的返回
        string memory x=condition ?"condition ture":"condition false";
        return x;
    }
    
    function test6(bool condition, bool condition2) public returns (string memory){
        //先判断condtion,condition为true执行大括号语句,否则执行else
        if(condition){
            //再判断condition2
            if(condition2){
                return "condition2 true";
            } else{
                return "condition2 false";
            } 
        } else {
                return "condition false";
        }        
    }
}

循环

pragma solidity 0.6.10;

contract  ForAndWhere {
   
   function forexam() external returns (int) {
        int sum;
        for (int condition =1; condition<=10;condition++){  
             //写在执行语句前面,跳过后面的语句
             if (condition ==5){
                 continue;
             }
             //写在执行语句前面,跳出循环
             if (condition ==9){
                 break;
             }
             sum+=condition;
        }
        return sum;//31=1+2+3+4+6+7+8
   }
   
   function where() external returns (int){
       int _n=1;
       where (_n <10){
           //code
           _n++;
       }
   }
}

7.5 数组&映射

数组

pragma solidity 0.6.10;

contract ArrayTest{
    //动态数组
    int[] public nums = [1,2,3];
    //定长数组
    int[3] public numsFix =[4,5,6];
    
    function example() external returns (uint[] memory,uint){
        nums.push(4);//[1,2,3,4]
        nums[2] = 66; // [1,2,66,4]
        delete nums[1];//[1,0,66,4] //位置没有删
        nums.pop();// [1,0,66]
        uint len = nums.length;
        
        //对于memory修饰的动态数组,可以用new操作符来创建,
        //但是必须声明长度,并且声明后长度不能改变
        uint[] memory a = new uint[](5);
        //如果创建的是动态数组,你需要一个一个元素的赋值。
        a[0] =1;
        return (a,len); 
    }
    
    // 查看数组
    function returnArray() external view returns( int[] memory){
        return nums;
    }
    
    // 删除元素
    function remove(uint _index) public {
       for (uint i = _index; i< nums.length-1;i++){
           nums[i] = nums[i+1];
       }
       nums.pop();
    }    
}

异常

require(_owners[tokenId] == msg.sender, "Transfer Not Owner");
assert(_owners[tokenId] == msg.sender);

数组方法

pragma solidity 0.6.10;
//定义Test6合约
contract Array_ {
    //个ages变量,类型为uint类型阳,并在声明时初始化值
    uint[] public ages =[10,11,12];
//在数组未尾添加空元素
    function pushEmpty() public {
        ages.push();      
    }
//在数组未尾添加指定元素
    function pushAge(uint age)public {
        ages.push(age);    
    }
//删除数组未尾元素
    function popAge() public {
        ages.pop();   
    }
//将指定索引的元素设置为0值
    function deleteAge(uint index) public {
        delete ages[index];  
    }
    function getAges() public returns(uint[] memory){
        return ages;       
    }
    function getLength() public returns(uint){
        return ages.length;        
    }
    
     // 查看数组
    function returnArray() external view returns(uint[] memory){
        return ages;
    }
      // 删除元素:1. 前面不变 后面往前移,删最后一个。
    function remove1(uint _index) public {
        require (_index < ages.length,"index out of band");
       
        for (uint i = _index; i< ages.length-1;i++){
            ages[i] = ages[i+1];
        }
        ages.pop();
    }
    
       // 删除元素:2.最后一个数替换后删。不考虑顺序。
    function remove2 (uint _index) external {
        require (_index<ages.length,"index out of band");
        ages[_index] = ages[ages.length-1];
        ages.pop();
    }
    //测试,当检查条件不成立的时候,就会抛出异常
    function test() external view {
        assert (ages.length==3);
        assert (ages[0]==1);
    }
}

字节数组

pragma solidity 0.6.10;
contract arry_char{
    //初始化A,类型为字节数组
    bytes public A;
    //初始化B,类型为字节数组
    bytes public B= "hellw";
    //初始化C,字符串
    string public c= "world";
//bytes类型使用push删除元素
    function pushA(byte b)public {
        A.push(b);
    }
//bvtes类型使用pop删除元素
    function popA()public {
        A.pop();
    }
//bytes类型修改指定索引元素
    function changeB()public {
        B[4]= "o";
    }
//string类型不能获取长度或修改指定索引元素
    function errFunc()public {
        //C.length;
        // C[0] = "a"
    }
}

映射

pragma solidity 0.6.10;
contract Test_mapping {
//声明全局变量users,类型为mapping键为uint类型,值为string类型
    mapping(uint=>string)public users;
// 设置用户名
    function setuser(uint userID, string memory name) public {
        users[userID]= name;
    }
// 获取用户名
    function getuser(uint userID)public returns(string memory){
        return users[userID];
    }
// 删除用户
    function deleteuser(uint userID)public {
        delete users[userID];
    }
}

数组和映射组合快速判断。

pragma solidity 0.6.10;

contract IterableMapping{
    
    mapping (address=>uint) balances;
    mapping (address=>bool) inserted;
    address[] keys;
    
    function set(address _key, uint _val) external {
        balances[_key]= _val;
        if (!inserted[_key]){
            inserted[_key] = true;//可以快速判断存在
            keys.push(_key);
        }
    }
    //数组长度
    function getSize() external view returns (uint){
        return keys.length;
    }
    // 第一个值
    function getFirst() external view returns (uint){
        return balances[keys[0]];
    }
}

7.6 结构体

pragma solidity 0.6.10;

contract Structs{
    
    struct Car{
        string model;
        uint  year;
        address owner;
    }
    Car c;
    Car[] cs;
    mapping (address=>Car[]) carbyown;

    function example() external  {
        //初始化
        Car memory benchi = Car("benchi",1984,msg.sender);
        Car memory baoma = Car({year:1999,model:"baoma",owner:msg.sender});
        Car memory aodi;
        aodi.model ="aodi";
        aodi.year = 2000;
        aodi.owner=msg.sender;
        
        cs.push(benchi);
        cs.push(baoma);
        cs.push(aodi);
        
        //使用storage指向cs修改
        Car storage c=cs[0];
        c.year = 1985;
        delete c.model;
    }
    // 返回第值
    function returnstruct(uint _i) external view returns(uint,string memory,address){
        return (cs[_i].year,cs[_i].model,cs[_i].owner);
    }
}
//声明soliditv版本为0.6.10
pragma solidity 0.6.10;
contract Test_struct{
    //定义枚举类型
    enum gender {
        male, female
    }
//定义结构体类型
    struct user {
        uint ID;// 用户ID
        string name; //用户名
        gender _gender;//用户性别
    }
//声明全局变量user,变量类型为
    user public _user;//创建用户
    function createUser(uint userID, string memory name, bool isFemale) public{
        _user =user(userID,name,gender.male);
        if(isFemale){
            _user._gender =gender.female;          
        }
    }
//更新用户名
    function updateUserName(string memory name) public {
        _user.name = name;
    }
    //获取用户性别
    function getUserGender() public returns(string memory){
        
        if(_user._gender == gender.male){
            return"男";
        }        
        return"女";
    }
}

7.7 修饰符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

pragma solidity 0.6.10;

contract ModifyTest {
    address public owner;
    // 创建合约时初始化owner变量
    uint x;
    constructor() public {
        owner = msg.sender;
    }
    modifier onlyOwner() {
        require (owner==msg.sender,"只允许合约创建者操作");
        _;
    }
    
    modifier compare(uint x,uint y) {
        // if(x>y){
        //     _;
        // }
        require (x>y,"小于Y");
        _;
 
    }
    // function test() public onlyOwner  returns(uint){
    //     return x+1;
    // }
    function test(uint x) public onlyOwner compare(x,9) returns(uint){
        return x+1;
    }
}

使用lihui部署并调用合约test()函数,输入9,提示错误。
在这里插入图片描述
使用lihui部署并调用合约test()函数,输入10,返回11。
在这里插入图片描述
使用lihui创建合约,使用test用户调用test(),提示“只允许“
在这里插入图片描述

7.8 事件

在这里插入图片描述

pragma solidity 0.6.10;

contract EventTest{
    
    event testLog(uint x,string y);
    function test(uint a, string memory b) public {
        emit testLog(a,b);
    }
    
    event message (address _from, address _to, string _message);
    function sendMessage(address _to, string memory _message) external {
       emit message(msg.sender,  _to,  _message);
    }
}

通过合约管理-在线工具-Event查看

在这里插入图片描述

7.9 面向对象

pragma solidity 0.6.10;

contract Object {
    
    string name;
    uint age;
    //构造函数,初始化
    constructor (string memory _name,uint _age) public {
        name = _name;
        age = _age;
    }
    
    function get() external view returns(string memory,uint){
        return (name,age);
    }
}

部署时就需要初始化
在这里插入图片描述
继承

pragma solidity 0.6.10;
contract Animal {
    string name;
    uint age;
    // 构造函数
   constructor (string memory _name,uint _age) public {
       name = _name;
       age = _age;
   }
   
   function get_name() public view returns(string memory){
       return name;
   }
   
   function get_age() public view returns (uint){
       return age;
   }
}
pragma solidity 0.6.10;
import "./Animal.sol";
contract Dog is Animal{
    
    constructor(string memory _name, uint _age) Animal(_name, _age) public{
    }
    
    //使用super话用父合约中的petName座
    function dogName() public view returns(string memory){
        return super.get_name();
    }
    //通过指定合约名调用父合约中的getAge函数
    function dogAge() public  view returns(uint){
        return Animal.get_age();
    }
}

直接使用父类方法和自写方法一样。
在这里插入图片描述
多继承

pragma solidity 0.6.10;
contract Pet {
// 和人玩耍
    function play()public view returns(string memory){
        return "play with people";
    }
//陪伴人
    function accompany()public returns(string memory){
        return "accompany with people";
    }
}
pragma solidity 0.6.10;
import "./Animal.sol";
import "./Pet.sol";
// is Pet 则继承Pet方法
contract CatPet is Animal,Pet{
//构造函数继承的两种方式
//contract CatPet is Animal("cat",22),Pet{    
    constructor(string memory _name, uint _age) Animal(_name, _age) public{
    }
    
    //使用super话用父合约中的petName座
    function dogName() public view returns(string memory){
        return super.get_name();
    }
    //通过指定合约名调用父合约中的getAge函数
    function dogAge() public  view returns(uint){
        return Animal.get_age();
    }
}

在这里插入图片描述

new 创建合约

//在NewPet中引用Pet, 并使用new 关键字创建
pragma solidity 0.6.10;
import "./Pet.sol";
contract NewPet {
    
    address petaddr;
    function deploy() public  returns(address){
        Pet pt = new Pet();
        petaddr=address(pt);
        return petaddr;
    }
      
    function get() public view returns (string memory){
       return  Pet(petaddr).play();
    }
}

方法覆盖
在这里插入图片描述

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.10;
contract A {    
    function foo() external view virtual returns(string memory){
       return "A";
    }
    
    function bar() external view returns(string memory){
        return "ab";
    }
}
pragma solidity 0.6.10;
import "./A.sol";

contract B is A {
    function foo() external view virtual override returns(string memory){
        return "Ba";
    }
}
pragma solidity 0.6.10;
import "./B.sol";

contract C is B {
    function foo() external view override returns(string memory){
        return "Cb";
    }
}

在这里插入图片描述

7.10 抽象合约

在这里插入图片描述

pragma solidity 0.6.10;
abstract contract A {
    function foo() external view virtual returns(string memory){
       return "A";
    }    
    function bar() external view returns(string memory){
        return "ab";
    }    
    function virt(uint x,uint y) public virtual returns (uint);
}


// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.10;
import "./A.sol";
contract B is A {
    function foo() external view virtual override returns(string memory){
        return "Ba";
    }    
    function virt(uint _x,uint _y) public override returns (uint){
        return _x+_y;
    }
}

7.11接口合约

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

7.12 库合约

在这里插入图片描述

pragma solidity 0.6.10;

library Librar {
    function max(int x,int y) internal pure returns (int){
        return x>y?x:y;//取最大值
    }
    
    function find(int[] storage arr,int t) internal view returns(uint){
        for (uint i =0;i<arr.length;i++){
            if (arr[i] ==t) return i;
        }//查找值
        revert ("no find");
    }
}

contract Library {
    
    function test(int x,int y) external view returns (int){
       return Librar.max(x,y);//调用库函数
    }
    
    using Librar for *;//简化库函数调用
    function test2(int x,int y) external view returns(int){
        return x.max(y);
    }
    
    int[]  arr = [1,2,3,6];
    function testfind() external view returns(uint){
        return arr.find(2);
    }
}

在这里插入图片描述

在这里插入图片描述

九、案例

在这里插入图片描述

9.1 权限控制合约

pragma solidity 0.6.10;

contract AcessContract {
  event GrantRole(bytes32 indexed _role, address indexed _account);      
    
  //role=>account=>bool
  mapping (bytes32=>mapping(address=>bool)) public roles;
  
  bytes32 private constant ADMIN = keccak256(abi.encodePacked("ADMIN"));
  bytes32 private constant USER = keccak256(abi.encodePacked("USER"));
  
  //升级权限
  function grantRole(bytes32 _role,address _account) internal {
      roles[_role][_account] = true;
      emit GrantRole(_role,_account);
  }
  
    //取消权限
  function evokeRole(bytes32 _role,address _account) internal {
      roles[_role][_account] = false ;
      emit GrantRole(_role,_account);
  }
  
  modifier onlyRole(bytes32 _role){
      require (roles[_role][msg.sender],"not auth");
      _;
  }
  constructor() public {
      grantRole(ADMIN,msg.sender);
  }
  // ADMIN才能修改
  function grantRoleW(bytes32 _role,address _account) external onlyRole(ADMIN) {
      grantRole(_role,_account);
  }
}

9.2 投票合约

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;

contract ballot{
    // 选民
    struct Voter{
        uint weight; //权重
        bool voted; //是否已投票
        string proposalName;//
        address delegate;// 被委托人
    }
    
    //提案
    struct Proposal{
        string name;//提案名
        uint voteCout;//投票数
    }
    //主持人
    address public chairPerson;    
    //存储所有选民
    mapping(address=>Voter) public voters;
    
    //存储所有提案
    Proposal[] public proposals;
    //是否在投票中
    bool voting = true;
    //修饰符,只有主持人可以操作
    modifier onlychairPerson() {
        require(chairPerson == msg.sender,"只有主持人可以操作");
        _;
    }
    // 修饰符,只有投票正在中可以操作
    modifier onlyproposals(){
        require(voting,"投票已结束");
        _;
    }   
    //创建合约 传入提案名
    constructor(string[] memory proposalNames) public{
        //合约创建者为主持人
        chairPerson = msg.sender;
        // 给主持人赋权
        voters[msg.sender].weight =1;
        // 添加提案到数组
        for (uint i =0;i<proposalNames.length;i++){
            proposals.push(
                //Proposal(proposalNames[i],0));
                Proposal({name:proposalNames[i],voteCout:0})
                );
        }
    }
    
    //内部使用工具 根据提案名获取索引
    function getProposalIndexByName(string memory _name) private view returns(uint){
        for (uint i = 0; i<proposals.length;i++){
            if (keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(proposals[i].name))){
                return i;
            }
        }
       revert("未找到");
    }
    
    //授权某个选民进行投票
    function approveToVote(address voteradd) public  onlychairPerson onlyproposals {
        require (voters[voteradd].voted == false,"已投票");
        require (voters[voteradd].weight ==0,"已赋权");
        voters[voteradd].weight =1;
    }
    
    // 投票给某提案
    function vote(string memory _proposalName) public onlyproposals{
        Voter storage sender = voters[msg.sender];
        require (sender.voted == false,"已投票");
        sender.voted=true;
        sender.proposalName= _proposalName;
        uint i= getProposalIndexByName(_proposalName);
        proposals[i].voteCout += sender.weight;
    }
    // 停止投票
    function stoped()   public  onlychairPerson {
        voting=false;
    }
    
    // 将投票权委托给指定用户,并跟随指定用户的投票
    function delegate(address delegateAddr) public onlyproposals {
        //获取操作用户
        Voter storage sender = voters[msg.sender];
        require (sender.voted == false,"已投票");
        require(delegateAddr!=msg.sender,"自己不能自己委托" );
        //委托是可以传递的,可能形成闭环让合约卡住
        while (voters[delegateAddr].delegate!=address(0)){
            delegateAddr =voters[delegateAddr].delegate;
            require(delegateAddr!= msg.sender,"不能循环委托");
        }
        //设置为已投票
        sender.voted=true; 
        sender.delegate = delegateAddr;
        
        //获取被委托人
        Voter storage d = voters[delegateAddr];
        if (d.voted){
            //若被委托人投过票,则直接增加票数
            uint i = getProposalIndexByName(d.proposalName);
            proposals[i].voteCout+=sender.weight;
        } else {
            // 若被委托人没投过票,增加被委托人票数
            d.weight += sender.weight;
        }    
    }
 //获取投票最多的提案
    function getMax() public view returns (string memory winName){
         uint maxVote=0;
         for (uint i = 0; i<proposals.length;i++){
             if(proposals[i].voteCout >maxVote){
                 maxVote = proposals[i].voteCout;
                 winName = proposals[i].name;
             }
         }
         return winName;
    } 
}

在这里插入图片描述
在这里插入图片描述
通过代码了解联邦选举流程

pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;

contract ballot2{
    
    struct Area{
       string name; //选取名称
       uint weight; // 选区计票权重
       mapping(string=>uint) Proposal;// 该区投票情况
    }    
    //投票人
    struct Voter{
        uint weight; //权重
        bool voted; //是否已投票
        string proposalName;//
        string areaName;// 选区名
    }
    
    //提案
    struct Proposal{
        string name;//提案名
        uint voteCout;//投票数
    }
    //主持人
    address public chairPerson;
    
    //存储所有选民
    mapping(address=>Voter) public voters;
    
    //存储所有提案
    Proposal[] public proposals;
    //存储所有的选区
    Area[] areas;
    //是否在投票中
    bool voting = true;
    //修饰符,只有主持人可以操作
    modifier onlychairPerson() {
        require(chairPerson == msg.sender,"只有主持人可以操作");
        _;
    }
    // 修饰符,只有投票正在中可以操作
    modifier onlyproposals(){
        require(voting,"投票已结束");
        _;
    } 
  
    //创建合约 传入提案名和主持人所在地区
    constructor(string[] memory proposalNames,string memory chairPersonArea) public{
        //合约创建者为主持人
        chairPerson = msg.sender;
        // 给主持人赋权
        voters[msg.sender].weight =1;
        // 设置主持人所在区域
        voters[chairPerson].areaName = chairPersonArea;

        // 添加提案到数组
        for (uint i =0;i<proposalNames.length;i++){
            proposals.push(
                //Proposal(proposalNames[i],0));
                Proposal({name:proposalNames[i],voteCout:0})
                );
        }
    }
    
    //内部使用工具 根据提案名获取索引
    function getProposalIndexByName(string memory _name) public view returns(uint){
        for (uint i = 0; i<proposals.length;i++){
            if (keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(proposals[i].name))){
                return i;
            }
        }
        revert("未找到");
    }
    //内部使用工具 根据提小区获取索引
    function getAreaIndexByName(string memory _name) public view returns(uint){
        for (uint i = 0; i<areas.length;i++){
            if (keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(areas[i].name))){
                return i;
            }
        }
        revert("未找到");
    }
    
    // 添加小区
    function addArea(string memory _name,uint _weight) public onlychairPerson onlyproposals{
        areas.push(
                Area({name:_name,weight:_weight})
            );
    }
    //授权某个选民进行投票,并设置选民所在地区
    function approveToVote(address voteradd,string memory _areaname) public  onlychairPerson onlyproposals {
        require (voters[voteradd].voted == false,"已投票");
        require (voters[voteradd].weight ==0,"已赋权");
        voters[voteradd].weight =1;
        voters[voteradd].areaName = _areaname;
    }
    
    // 投票给某提案
    function vote(string memory _proposalName) public onlyproposals{
        Voter storage sender = voters[msg.sender];
        require (sender.voted == false,"已投票");
        sender.voted=true;
        sender.proposalName= _proposalName;
        uint areai= getAreaIndexByName(sender.areaName);
        //获取选民选区,增加对应投票
        areas[areai].Proposal[_proposalName] += sender.weight;
    }
    // 停止投票
    function stoped()   public  onlychairPerson {
        voting=false;
    }
      
 //获取区域最大投票和权重
    function getAreaMax(string memory _areaname) public view returns (string memory winName,uint){
        uint maxVote=0;
        // 获取指定区域
        uint areai= getAreaIndexByName(_areaname);
        Area storage a = areas[areai];
         for (uint i = 0; i<proposals.length;i++){
            uint  ProposalCount = a.Proposal[proposals[i].name];
             if(ProposalCount>maxVote){
                 maxVote = ProposalCount;
                 winName = proposals[i].name;
             }
         }
         return (winName,a.weight);
    }    
   //将每个区的票相加
   function areaTotel() public onlyproposals {
       
       string memory winName;
       uint winWeight;
       for (uint i =0;i<areas.length;i++){
           (winName,winWeight) = getAreaMax(areas[i].name);
           uint indexi = getProposalIndexByName(winName);
           proposals[i].voteCout += winWeight;
       }
   }   
    //获取投票最多的提案
    function getMax() public view returns (string memory winName){
        uint maxVote=0;
         for (uint i = 0; i<proposals.length;i++){
             if(proposals[i].voteCout >maxVote){
                 maxVote = proposals[i].voteCout;
                 winName = proposals[i].name;
             }
         }
         return winName;
    } 
}

9.3 拍卖合约

在这里插入图片描述
在这里插入图片描述

pragma solidity 0.6.10;

contract Auction{
    //拍卖收益人
    address public beneficiary;
    //拍卖结束的时间戳(毫秒)
    uint public auctionEnd;
    //当前出价最高者和最高金额
    address public highestBidder;
    uint public highestBid;
    //参与拍卖用户余额
    mapping (address=>uint) public balance;
    //最高出价变更EVENT
    event HighestBidIncreased(address bidder,uint amount);
    //初始化拍卖,传入拍卖时间(秒)和收益人地址
    constructor (address _beneficiary, uint _biddingtime) public{
        beneficiary = _beneficiary;
        auctionEnd = now+_biddingtime*1000;
    }
    //存入余额
    function deposit(uint _value) public{
       balance[msg.sender] += _value;
    }
    //取出余额
    function withdraw() public returns(uint) {
      uint valueNow =balance[msg.sender];
      balance[msg.sender]=0;
      return valueNow;
    }
    // 竞拍出价
    function bid (uint _value) public {
        require(now<=auctionEnd,"拍卖时间结束");
        require(balance[msg.sender]>=highestBid,"余额不足");
        require(_value > highestBid,"当前价低于最高价");
        // 将余额返还给之前最高者
        balance[highestBidder]+=highestBid;
        // 当前最高者减余额
        balance[msg.sender]-= _value;
        //更新最高者,发送event
        highestBidder = msg.sender;
        highestBid = _value;
        emit  HighestBidIncreased(msg.sender,_value);
    }    
    function stopAuction() public {
        require(now>auctionEnd,"拍卖时间未到");
        balance[beneficiary]+=highestBid;
    }
}

在这里插入图片描述
在这里插入图片描述

// 声明 solidity 版本为 0.6.10
pragma solidity 0.6.10;
// 定义 Auction 合约
contract Auction2{
    //拍卖结构体,存储盲拍的散列和保证金
    struct Bid{
        bytes32 blindedBid;
        uint margin;
    }
    //拍卖受益人
    address public beneficiary;
    // 拍卖结束的时间戳
    uint public biddingEnd;
    // 出价披露结束的时间戳
    uint public revealEnd;
    // 参数拍卖的用户
    mapping(address =>Bid) public bids;
    //当前出价最高者和最高金额
    address public highestBidder;
    uint public highestBid;
    // 参与拍卖用户的余额
    mapping(address=>uint) balance;
    
    // 修饰符,限制操作时间必须小于 time
    modifier onlyBefore(uint time){
        require(now<time);
        _;
    }
    // 修饰符,限制操作时间必须大于 time
    modifier onlyAfter(uint time){
        require(now>time);
        _;
    }
    
    // 初始化拍卖,传入拍卖持续时间(秒),出价披露持续时间(秒),受益人地址
    constructor(uint biddingTime,uint revealTime,address beneficiary)public{
        beneficiary=beneficiary;
        biddingEnd =now+biddingTime*1000;
        revealEnd =biddingEnd +revealTime*1000;
    }
    
    // 存入余额
    function deposit(uint value)public {
        balance[msg.sender]+=value;
    }
    //取出余额
    function withdraw()public returns(uint){
        uint value =balance[msg.sender];
        balance[msg.sender]=0;
        return value;
    }
    // 工具函数,供用户计算哈希(该函数不会在区块链上留下日志)
    function bidTool(uint value, string memory secret)public view returns(bytes32){
        return keccak256(abi.encodePacked(value,secret));
    }
    //盲拍,传入盲拍哈希值和保证金
    function blindedBid(bytes32 blindedBid, uint value) public onlyBefore(biddingEnd){
        require(balance[msg.sender]>= value,"余额不足");
        balance[msg.sender]-= value;
        Bid storage bid= bids[msg.sender];
        require(bid.margin ==0,"只能出价一次");
        bids[msg.sender]= Bid({blindedBid:blindedBid,margin:value});
    }
    // 判断 value 是否为最高出价,更新当前最高价和出价用户
    function placeBid(address bidder, uint value)internal returns (bool success){
        if(value<= highestBid){return false;}
        if(highestBid !=0 ){balance[highestBidder]+=highestBid;}
        highestBid =value;
        highestBidder=bidder;
        return true;
    }
    
    //披露价格,验证哈希值,正确则执行出价流程
    function reveal(uint value, string memory secret) public onlyAfter(biddingEnd) onlyBefore(revealEnd){
        Bid storage bid= bids[msg.sender];
        uint refund = bid.margin;
        if(bid.blindedBid != keccak256(abi.encodePacked(value, secret))){
            return;
        }
        //只能披露一次价格
        if(bid.blindedBid ==bytes32(0)){
                return;
        }
        bool isHighest=placeBid(msg.sender,value);
        if(isHighest){
            refund -= value;
        }
        //将盲拍哈希设置为空
        bid.blindedBid=bytes32(0);
        balance[msg.sender]+= refund;
    }
    //结束拍卖,将拍卖所得转给受益人
    function stopAuction()public{
        require(now>= biddingEnd,"拍卖还未到结束时间");
        balance[beneficiary]+= highestBid;
    }    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/890603.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

与鸿蒙同行,Java Solon v3.0 正式发布(向下兼容)

与 HarmonyOS NEXT 10月8日公测同行。Solon &#xff08;开放原子开源基金会&#xff0c;孵化项目&#xff09; v3.0 正式发布&#xff0c; 且将在 2025 年启动华为编程语言 “仓颉” 版开发&#xff08;届时会有 Solon-Java 和 Solon-CJ 两大版本&#xff09;。本次大版本更新…

免费送源码:Java+Springboot+MySQL 水环境检测系统的设计与实现 计算机毕业设计原创定制

摘 要 在我国,水源的污染是不可忽视的问题。对于水质监测进行数据的采集工作,目前主要通过人工实现。因此,部分地区的采集工作,实施起来难度很大,比如恶劣环境和偏僻山区等地。所以,目前对于水质监测的研究,主导方向是建立更加高效完善,智能化的水质监测系统。近几年,无线传感器…

【C++贪心 DFS】2673. 使二叉树所有路径值相等的最小代价|1917

本文涉及知识点 C贪心 反证法 决策包容性 CDFS LeetCode2673. 使二叉树所有路径值相等的最小代价 给你一个整数 n 表示一棵 满二叉树 里面节点的数目&#xff0c;节点编号从 1 到 n 。根节点编号为 1 &#xff0c;树中每个非叶子节点 i 都有两个孩子&#xff0c;分别是左孩子…

java数据库操作-cnblog

创建lib目录&#xff0c;填入jar包 选择 libraries添加lib目录 package nb;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;public class JDBCtest {private static final String url "jdbc:mysql://localhost:3306/test?c…

SAP学习笔记 - 豆知识12 - 自动批量更新会计期间

网上买的那种SAP学习虚拟机&#xff0c;一般都是古老的会计期间。 要想更新到现在的日期&#xff0c;需要MMRV/MMPV挨月更新&#xff0c;感叹SAP挺会折磨人。 之前也做过多次探索&#xff0c;基本都没太成功。 SAP MM学习笔记 - 豆知识10 - OMSY 初期化会计期间&#xff0c;…

深入探索Spring Cloud Gateway:微服务网关的最佳实践

优质博文&#xff1a;IT-BLOG-CN Spring Cloud Gateway作为Spring Cloud框架的第二代网关&#xff0c;在功能上要比Zuul更加的强大&#xff0c;性能也更好。随着Spring Cloud的版本迭代&#xff0c;Spring Cloud官方有打算弃用Zuul的意思。在笔者调用了Spring Cloud Gateway的…

使用 Visual Studio Installer Projects 打包 C# WinForms 程序的教程

前言 在开发完成一个 C# WinForms 程序后&#xff0c;打包成安装程序是发布和分发软件的重要步骤之一。通过使用 Visual Studio Installer Projects&#xff0c; 可以轻松创建一个 .exe 或 .msi 格式的安装包供用户安装。本文将详细介绍如何使用 Visual Studio Installer Proj…

网络资源模板--Android Studio 实现简易记事本App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 实现的简易记事本App 二、项目测试环境 三、项目详情 首页 创建一个空的笔记本列表 mNotebookList。使用该列表和指定的布局资源 item_notebook 创建…

苹果最新论文:LLM只是复杂的模式匹配 而不是真正的逻辑推理

大语言模型真的可以推理吗&#xff1f;LLM 都是“参数匹配大师”&#xff1f;苹果研究员质疑 LLM 推理能力&#xff0c;称其“不堪一击”&#xff01;苹果的研究员 Mehrdad Farajtabar 等人最近发表了一篇论文&#xff0c;对大型语言模型 &#xff08;LLM&#xff09; 的推理能…

2.实现第一个three.js程序

实现第一个three.js程序 1.目标效果 注意一个版本问题&#xff1a;three.js版本并不稳定&#xff0c;几乎每个月都会更新一个小版本&#xff0c;尽可能使用固定版本进行开发&#xff0c;事实上我们入门的话&#xff0c;只掌握其中一个版本即可&#xff0c;如果使用新版本&…

文件与fd

访问文件前&#xff0c;为什么必须要打开文件&#xff1f;/ 打开文件的实质 访问文件前&#xff0c;都必须先打开它&#xff0c; 如fopen 访问文件时&#xff0c;是进程在访问 所以文件必须加载到内存中 我们要访问文件时&#xff0c;一定要通过内存访问 文件没有被打开时&am…

多线程(三):线程等待获取线程引用线程休眠线程状态

目录 1、等待一个线程&#xff1a;join 1.1 join() 1.2 join(long millis)——"超时时间" 1.3 join(long millis&#xff0c;int nanos) 2、获取当前线程的引用&#xff1a;currentThread 3、休眠当前进程&#xff1a;sleep 3.1 实际休眠时间 3.2 sleep的特殊…

SQLI LABS | SQLI LABS 靶场初识

关注这个靶场的其它相关笔记&#xff1a;SQLI LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;SQLI LABS 靶场简介 SQLi-Labs 靶场是一个专门用于学习和测试 SQL 注入漏洞的开源靶场&#xff0c;该靶场提供了多个具有不同漏洞类型和难度级别的 Web 应用程序的环境。这些应用…

C++ | Leetcode C++题解之第477题汉明距离总和

题目&#xff1a; 题解&#xff1a; class Solution { public:int totalHammingDistance(vector<int> &nums) {int ans 0, n nums.size();for (int i 0; i < 30; i) {int c 0;for (int val : nums) {c (val >> i) & 1;}ans c * (n - c);}return …

matlab 相关

1、xcorr 本质上是两个函数做内积运算 相关算法有两种&#xff1a; 在Matlab上既可以 1.用自带的xcorr函数计算互相关&#xff0c;2.通过在频域上乘以共轭复频谱来计算互相关&#xff1b; 网友验证程序 clc;clear;close all; % s1,s2为样例数据 s1 [-0.00430297851562500;-…

[C++ 核心编程]笔记 4.1.2 struct和class的区别

4.1.2 struct和class的区别 在C中 struct和class唯一的区别就在于 默认的访问权限不同 区别: struct 默认权限为公共class 默认权限为私有 #include<iostream> using namespace std;class C1 {int m_A;//默认私有 }; struct C2 {int m_A;//默认共有 };int main() {//s…

【3dgs】Gaussian-SLAM发展关键历程梳理

【3dgs】Gaussian-SLAM 0. 写在前面1. 3D Splatting与SLAM流程2. Splatting SLAM&#xff1a;单目/RGB-D(2024年新作&#xff09;2.1 相机跟踪精度2.2 新视图渲染性能2.3 消融实验 3. Gaussian-SLAM&#xff08;Photo-SLAM&#xff09; Photo-SLAM技术原理详解 ORBSLAM3dGS&am…

超GPT3.5性能,无限长文本,超强RAG三件套,MiniCPM3-4B模型分享

MiniCPM3-4B是由面壁智能与清华大学自然语言处理实验室合作开发的一款高性能端侧AI模型&#xff0c;它是MiniCPM系列的第三代产品&#xff0c;具有4亿参数量。 MiniCPM3-4B模型在性能上超过了Phi-3.5-mini-Instruct和GPT-3.5-Turbo-0125&#xff0c;并且与多款70亿至90亿参数的…

CentOS快速配置网络Docker快速部署

CentOS快速配置网络&&Docker快速部署 CentOS裸机Docker部署1.联通外网2.配置CentOS镜像源3.安装Docker4.启动Docker5.CentOS7安装DockerCompose Bug合集ERROR [internal] load metadata for docker.io/library/java:8-alpineError: Could not find or load main class …

动力电池SOC估算方法

1. SOC介绍 电池的荷电状态SOC反映电池的剩余容量状况&#xff0c;即在一定的放电倍率下&#xff0c;当前电池的剩余容量与总容量的比值。 为了充分发挥电池性能和提高安全性&#xff0c;需要准确估算电池SOC。动力电池在使用过程中表现的高度非线性提高了SOC估算的难度&#…