만약, 다음과 같은 함수가 있다면, B 에는 4개의 요소만 들어갈 수 있을 것이다.
uint[4] public b;
uint count;
function pushB2(uint _a) public {
b[count] = _a;
count++;
}
이미 상태변수에서 [4] 네 자리임을 선언했기 때문이다.
그렇다면, 4개의 요소로 상태변수 B 에 가득 차게되었을 때,
B 를 초기화하고 새로 입력하는 값을 0번째 요소로 넣는 함수를 써보면 다음과 같다.
uint[4] public b;
function pushB(uint _a) public {
require(_a !=0);
if(getLengthOfB()==4) {
delete b;
}
b[getLengthOfB()] = _a;
}
function getLengthOfB() public view returns(uint) {
for(uint i=0; i<4; i++) {
if(b[i]==0) {
return i;
}
}
return 4;
}
먼저, 배열의 자릿수를 구해주는 함수를 만들고 자릿수가 가득 찼다면 배열을
Delete 로 초기화 해주고, 다시 0번째 배열부터 요소를 넣는 것이다.
이렇게 하면 배열의 길이도 추적할 수 있을 뿐만 아니라, 길이를 초과하면
배열을 초기화하고 새로운 요소를 넣을 수 있다.
byte20 형은 16진수 값이 40자리가 들어갈 수 있다.
address 형은 이더리움의 주소형태로, 16진수 40자리 주소의 형태이다.
그래서 두 형태는 같은 자릿수가 정의되있으므로, 서로 변환시킬 수 있다.
다음과 같이 byte20 a, address b 를 선언한 컨트랙트를 작성했다.
contract AA {
bytes20 a;
address b;
constructor() {
b = msg.sender;
}
function AAA() public view returns(address) {
return address(a);
}
function AAB() public view returns(bytes1) {
return bytes20(b)[0];
}
}
이 컨트랙트에서 AAA 함수를 호출하면, 0x 로 시작하는 40자리의 빈값이 나온다.
AAB 함수를 호출하면, msg.sender 의 주소. 즉, 컨트랙트를 배포한 내 지갑주소의 앞 2자리를 반환한다. 아래 사진에서 확인 가능하다.
mapping 은 key 와 value 쌍으로 이루어진 형태이다.
예를들어, 학생의 숫자와 이름을 key & value 쌍으로 묶는 mapping 을 선언하면 아래와 같다.
mapping(uint => string) student;
그리고 아래와 같은 방법으로 숫자 1은 "hyeongseok" 이라는 key value 쌍을 지정해줄 수 있다.
student[1] = "hyeongseok";
mapping 에도 struct 형태와 address 같은 다른 형태들도 사용이 가능하다.
그리고 mapping 안에도 mapping 이 가능하다. (multi mapping)
하지만, struct 형은 value 값으로만 가능하다. struct 엔 여러 형태의 값이 들어가 있기에, key 로 사용할 수 없다.
예시)
uint[] A;
mapping(string => A) 불가능
struct A{
uint a;
string b;
}
mapping(string => A) 가능
[주소 => 문자 => 숫자] 형태의 double mapping 을 사용해보면 아래와 같다.
mapping(address=>mapping(string=>uint)) bankAccounts;
function setbank(string calldata _name) public {
bank[msg.sender][_name] = 100;
}
double mapping 뿐 아니라, 그 이상의 multi mapping 도 가능하며, struct 형태도 value 값으로 지정이 가능하다.
문자 => 문자 => 숫자 => 유저(struct) mapping
struct user {
uint number;
string name;
}
user B;
mapping(string=>mapping(string=>mapping(uint=>user))) bankAccounts3;
function setBankAccounts2(string calldata _city, string calldata _state, uint number) public {
bankAccounts3[_city][_state][number] = B;
}
만약 다음과 같이 struct 형태를 key 로 설정하려고 코드를 작성할 경우, 아래와 같은 오류메시지를 볼 수 있다.
mapping(address=>mapping(user=>uint)) structmapping;
기본적인 type, 사용자가 정의한 type, contract , enum 만 key 값으로 지정이 가능하다. 라는 오류메시지다.
그래서 contract , enum 을 key 값으로 지정해보았다.
contract abc{
enum food {
chicken,
pizza,
water
}
mapping(address=>mapping(abc=>uint)) contractmapping;
mapping(address=>mapping(food=>uint)) enummapping;
}
contract test{
uint public a = 4;
}
struct 와는 다르게 정의가 가능하다.