[멋쟁이 사자처럼 블록체인 스쿨 3기] 23-05-12

임형석·2023년 5월 12일
0

Solidity


fallback

예외처리와 비슷하다.

누군가 컨트랙트에 함수를 호출했는데 함수명이 잘못 되어있다거나 함수가 실행되지 않을 때,

컨트랙트에서는 default 로 fallback 을 반환해준다.

이때, 가스비를 지출하지 않으며 함수의 실행 전으로 완전히 되돌아간다.

fallback() external payable{}

receive

돈을 받는 함수이다.

누군가 컨트랙트에 돈을 보내려고 할때에

receive 함수가 붙어있다면, 함수명은 보여지지 않고 receive 만 받게된다.

이 함수는 컨트랙트에 종속되어 있으므로, 컨트랙트가 이더리움을 받을 수 있게 된다.

    function deposit() public payable{}
    receive() external payable{}

remix 의 좌측 상단에서 이 함수를 실행 시켜 컨트랙트에게 이더리움을 보낼 수 있다.

이렇게 이더리움의 단위를 지정해주고,

deposit 함수를 실행시키면.

상단의 Account Balance, 중단의 Contract Balance 의 변화를 확인할 수 있다.

컨트랙트가 10 이더만큼을 받게 되었다.


Test


보충반 조회

보충반 조회 기능 - F 학점을 받은 학생들의 숫자와 그 전체 정보를 반환

이 문제는 앞선 날짜의 블로그 포스팅에도 올려놨는데, 가스비를 줄일 수 있는 방법이 있어서 수 많은 도전 끝에 성공했다...

먼저, 솔리디티에서는 가스비를 최대한 줄여야 한다.

이 문제에서는 상태변수를 선언하고 이를 수정해 사용하면 쉽게 코드를 작성할 수 있지만, 가스비가 소모된다.

그래서 가스비를 소모하지 않는 지역변수를 이용해 문제를 풀어보았다.

    function getF() public view returns(uint, student[] memory){
        uint num; // f 인 학생 수를 담기 위한 지역변수 선언.

        for(uint i=0; i < students.length; i++){   // f 인 학생을 찾기 위해 for,if문 사용, 그리고 string 값 비교를 위해 keccak256 사용.
            if(keccak256(abi.encodePacked(students[i].credit)) == keccak256(abi.encodePacked("F"))){
                num++; // f 인 학생 수의 증가.
            }
        }

        student[] memory fstudents = new student[](num); // F 인 학생의 수를 담은 num 으로, 배열의 길이를 정적으로 바꿔줌.
        uint num2; // 배열의 Key 값을 0부터 지정하기 위해 지역변수 선언.

        for(uint i=0; i < students.length; i++){
            if(keccak256(abi.encodePacked(students[i].credit)) == keccak256(abi.encodePacked("F"))){
                fstudents[num2] = students[i];
                num2++; // fstudents 에 값을 넣을때 마다 key 값이 1씩 증가.
            }
        }
        return (fstudents.length,fstudents); // f 인 학생의 수, f 인 학생의 정보. 총 2개의 값을 반환.
    }

학생의 수 3, F 학생 전체 정보를 반환받았다.


S반 조회 기능

가장 점수가 높은 학생 4명을 S반으로 설정하는데, 이 학생들의 전체 정보를 반환하는 기능 (S반은 4명으로 한정)

어제 못했던 S반 조회기능을 구현해본다.

가장 점수가 높은 4명의 정보만을 가져와야 하기에, 먼저 내림차순으로 점수로 정렬을 해주어야겠다.

먼저, students 배열을 불러온다면 학생들의 점수는 2,7,4,3,8,9,1 처럼 뒤죽박죽 섞여있다.

학생들의 점수를 내림차순으로 만드려면..

0번째 배열과 1번째 배열의 score 를 비교. 1번째 배열의 점수가 크다면, 0번째 배열과 자리를 바꾼다.

0번째 배열과 2번째 배열의 score 를 비교. 2번째 배열의 점수가 크다면, 2번째 배열과 자리를 바꾼다.

...

1번째 배열과 2번째 배열의 score 를 비교. 2번째 배열의 점수가 크다면, 2번째 배열과 자리를 바꾼다.

1번째 배열과 3번째 배열의 score 를 비교. 3번째 배열의 점수가 크다면, 3번째 배열과 자리를 바꾼다.

이런식으로 하나하나 바꾸어준다. 그림으로 보면 아래와 같다.

그러려면 for 문으로 배열을 하나하나 반복해서 찾아주고,

if 문으로 배열의 score 값을 비교하여 큰 값을 앞쪽으로 옮겨주어야 한다.

그리고 sorting 된 4명의 정보를 반환 해주어야 한다.

그래서 4자릿수의 새로운 정적 배열을 만들어주고, 여기에 정보를 넣고 반환시키면 되겠다.

이렇게 숫자를 하나하나 비교해서 자리를 바꿔 주는 방식의 정렬을 bubble sort 라고 한다.

그럼, bubble sort 를 이용해서 정렬해본다.

    function sclass() public view returns(student[] memory){
        student[] memory sstudents = new student[](4); // s반은 4명이므로 4자리의 정적 지역변수 선언.
        student[] memory allstudents = students; // 모든 학생의 값을 담을 지역변수 선언.

        for(uint i=0; i < students.length-1; i++){ // 버블정렬로 값을 하나 하나 비교해줌. 이 함수의 return 아래 주석을 참조.
            for(uint j=i+1; j < students.length; j++){
                if(allstudents[i].score < allstudents[j].score){ // j가 크다면 아래와 같이 순서를 바꿔줌
                    (allstudents[i], allstudents[j]) = (allstudents[j], allstudents[i]);
                }
            }
        }
        for(uint i=0; i < 4; i++){ // 점수기준 내림차순 정렬한 값에서 상위 4명을 대입해줌.
            sstudents[i] = allstudents[i];
        }
        return sstudents;
    }
/* 
3,6,7,4,2   6,3,7,4,2   7,3,6,4,2     0번째와 1번째, 0번째와 2번째, 0번째와 3번째...
7,3,6,4,2   7,6,3,4,2   7,6,4,3,2     1번째와 2번째, 1번째와 3번째, 1번째와 4번째...
*/
}

0개의 댓글