[FLUS 스터디 1주차] Dart 기초 - Control flow statements(제어문)

sucream·2022년 9월 2일
0

flutter-study

목록 보기
4/17

이전까지 다트에서 사용하는 타입들의 사용법에 대해 익혀봤다.
이번에는 다트를 이용해 흐름을 지정할 수 있는 방법에 대해 알아보자.

다트는 if / else if / else, switch-case를 이용해 흐름을 지정할 수 있으며, for, while, do while을 이용해 반복을 사용할 수 있다. 각각을 살펴보자.

1. if, else, else if

가장 기본적인 조건을 만드는 방법으로, if (statement) {code}로 사용한다.

  • statement에는 반드시 bool타입 데이터를 넣어야 하며, 다른 언어에서 제공하는 암시적 타입을 사용한 if문의 사용은 허용되지 않는다.
var isDart = true;

print('이 부분은 항상 출력됩니다.');


if (isDart == true) {  // isDart의 값이 true이기 때문에 해당 식의 결과는 true이다.
	print('이 부분은 isDart 변수가 참일 경우에만 출력됩니다.');
}

if (isDart) {  // isDart 자체가 bool 타입의 true이기 때문이 이것도 참이다.
	print('isDart가 참이면 이것도 출력됩니다.');
}
  • 만약 조건이 참이면 A를 하고 그렇지 않으면 B를 수행해줘라는 코드를 짜기 위해서 else가 존재한다.
  • else는 단독으로 사용될 수 없으며, 반드시 if와 같이 쌍으로 사용되어야 한다.
  • elseif의 조건이 참이 아닐 경우에 수행되기 때문에 별도의 조건을 작성하지 않는다는 것을 명심하자.
var myAge = 28;

print('이 부분은 항상 출력됩니다.');

if (myAge > 30) {  // myAge가 30보다 크면 true, 아니면 false가 반환된다.
	print('이 부분은 myAge 변수가 30보다 클 경우에만 출력됩니다.');
} else {  // 위 if문이 거짓이면 자동으로 수행되기 때문에 별도의 조건을 작성하지 않는다.
	print('이 부분은 myAge 변수가 30보다 작거나 같을 경우에만 출력됩니다.');
}
  • 만약 조건1이 참이면 A를 하고 그렇지 않고 조건2가 참이면 B를 하고 그렇지 않으면 C를 수행해줘라는 코드를 짜기 위해서 else if가 존재한다.
  • else ifelse처럼 단독으로 사용될 수 없으며, 반드시 if와 같이 사용되어야 한다.
  • else는 각 조건문의 마지막에 한번만 사용될 수 있지만, else ifif 아래, else 위에 필요한 조건의 수만큼 사용할 수 있으며, 각 조건은 위에서 아래로 순서대로 체크하다 true가 나올 때 멈추게 되며, 모든 조건이 참이 아니면 else가 실행된다.
var myScore = 75;

if (myScore > 90) {  // myScore 변수가 90보다 크면 수행
	print('점수가 90점보다 높습니다!');
} else if (myScore > 80) {  // 위 조건이 거짓이고 myScore 변수가 80보다 크면 수행
	print('점수가 80점보다 높습니다');
} else if (myScore > 70) {  // 위 조건이 거짓이고 myScore 변수가 70보다 크면 수행
	print('점수가 70점보다 높습니다..');
} else {  // 그 외 경우라면 수행
	print('점수가 너무 낮습니다...');
}

2. switch - case

if문은 각각의 조건이 독립된 조건으로 이루어져 있어서 서로 관련없는 데이터를 조건문으로 사용할 수 있다. switch문은 하나의 데이터를 기준으로 다양한 case로 비교하는 조건문이라 할 수 있다.

  • switch (variable)에 들어가는 variable==를 사용하여 비교되기 때문에 ==를 override하면 일반적으로 사용할 수 없다.(hashCode를 같이 override하면 되는것 같기도...)
  • 각 조건은 case statements: 형식으로 사용하고, 그 아래에 해당 내용을 작성한다.
  • 각 조건이 끝날 때 꼭 break문을 작성하여 해당 구문이 끝났음을 알려주어야 한다. 만약 break를 사용하지 않으면 해당 조건이
  • if문의 else처럼 모든 조건이 일치하지 않으면 실행되는 default문을 사용할 수 있으며, default는 조건의 맨 아래에 사용되기 때문에 별도의 break를 사용하지 않아도 된다.
var subject = '수학';

switch (subject) {  // String 타입의 '수학' 문자열이 비교 대상이 된다.
  case '국어':  // '수학' == '국어' 비교를 통해 참/거짓을 확인하고 참일 경우 아래를 수행한다.
    print('국어입니다!');
    break;  // case가 종료될 때 반드시 break를 작성하여 해당 구문을 끝내도록 한다.
  case '수학':  // '수학' == '수학' 비교를 통해 참/거짓을 확인하고 참일 경우 아래를 수행한다.
    print('수학입니다!');
    break;
  case '영어':  // '수학' == '영어' 비교를 통해 참/거짓을 확인하고 참일 경우 아래를 수행한다.
    print('영어입니다!');
    break;
  default:  // 위 모든 조건이 거짓일 경우 수행되는 구문이다.
    print('잘 모르겠습니다...');  // default 아래에는 별도의 구문이 없기 때문에 아래에 break를 작성하지 않아도 된다.
}

labelcontinue

switch문에서는 labelcontinue를 이용하여 좀 더 복잡한 조건을 사용할 수 있다.
만약 값이 30일 땐 그냥 30을 출력하고, 10인 경우엔 10을 출력한 뒤 30도 출력하고 싶다고 하면 아래와 같이 사용할 수 있다.

  • 다른 곳에서 사용되길 원하는 곳에 labellabelName: 형태로 사용하고, 다른 case에서 continue labelName형태로 사용할 수 있다.
  • 이 때, continue를 사용하고 아래에 break를 작성하지 않아도 되는데, 이는 continue를 수행하면 해당 구문이 종료되고 라벨명쪽으로 흐름이 이동되기 때문이다.
  • 추가로 각 케이스에서 멀티라인을 작성할 수 있으며, 구분을 위해 중괄호를 사용할 수도, 사용하지 않을 수도 있다.
var data = 10;
  
  
switch(data) {
  case 10:  // data == 10 이 참일 때만 수행한다.
    print('10입니다.');
    continue test;  // 본 case가 끝나면 test 라벨 구문으로 이동해서 다음을 수행하라는 명령이다.

  case 3: {
    print('3입니다.');
    break;
  }

  test:  // test 라벨이 작성된 곳으로, 라벨은 case 위에 존재해야 한다.
  case 30:
    print('30입니다.');
    break;

  default:
    print('모르겠어요...');
}

3. for

반복 횟수를 지정하고 반복을 수행하는 기능으로, for (초기식;조건식;증감식)의 형태로 사용된다. 초기식을 기준으로, 조건식이 참이면 반복문 내에 있는 기능을 수행하고 증감식을 수행한다. 이후 조건식을 확인하며 거짓이 될 때까지 반복한다.

  • 초기식:var localVar = 0; 형식으로 반복문 내에서 사용할 변수를 초기화 한다.
  • 조건식: localVar < 10; 형식으로 반복문이 수행할 조건을 작성해 준다. 예시는 localVar이 10보다 작을 때만 수행한다는 뜻이다.
  • 증감식: localVar++ 형식으로 반복문 내에서 변화할 내용을 작성해 준다. 예시는 localVar를 1씩 증가시킨다는 뜻이다.
for (int i = 0; i< 10; i++){  // 0부터 9까지 1씩 증가하며 반복한다.
	print('${i}');
}

for-in

다트는 Iterable 객체를 대상으로 for-in을 지원한다. Iterable이라는 말이 어려울 수 있는데, 지금은 List, Set 같은 데이터라고 생각하면 될 것 같다. 쉽게 말해 내부적으로 반복할 수 있는 기능이 들어있는 객체들을 말한다. 내부적으로 기능이 있기 때문에 기존의 for문 처럼 사용하지 않아도 더 간편하게 사용할 수 있다.

  • for (var localVar in iterable) 형식으로 사용하며, 본 기능은 Iterable에 한해서 사용할 수 있다.
var myList = [1,2,3,4,5];

for (var element in myList) {  // 반복문 내에서 사용할 로컬 변수 element를 지정하여 사용한다.
	print('element: ${element}');
    element += 10;
}

print('myList: ${myList}');

// 로컬 변수에 final 키워드를 이용하면 반복문 내에서 변수의 값이 변경되는 것을 방지할 수 있다.
// 근데 var로 해도 원본 데이터엔 반영이 안되는 것을 보니 for in은 값의 복사로 이루어지는 것 같다.
for (final element in myList) {  
	print('element: ${element}');
    element += 10;  // [ERROR] final로 선언한 데이터를 변경하려 해서 에러 발생
}

print('myList: ${myList}');

4. while, do while

for문이 수행 횟수가 정해진 반복문이라면, whiledo while은 횟수가 아닌 조건만을 따지는 횟수가 정해지지 않은 반복문이다. `while은

  • while(조건) 형식으로 사용하며, 반복문 내 내용을 수행 후 조건이 거짓인지 확인하고 거짓이 될 때까지 반복한다. 따라서 조건 설정을 신중하게 하지 않으면 무한루프에 빠질 수 있으니 주의해야 한다.
  • 또한 조건을 설정하기 위한 값이 반복문 이전에 존재해야 하며, 반복문 내에서 적절히 조건을 컨트롤할 수 있어야 한다.
int cnt = 0;  // while문의 조건식에서 사용할 변수를 선언

while (cnt<10) {  // cnt가 10보다 작을 때만 반복문 내용을 수행한다.
	print('cnt: ${cnt}');
    cnt++;
}


print('-'*20);  // -를 20번 반복하여 출력


// flag용 변수를 지정하고 반복문 내에서 플래그를 변경하여 반복문을 컨트롤할 수 있다.
int cnt2 = 0;
bool flag = true;

while (flag) {
	cnt2++;
    
	if (cnt2 > 10) {  // cnt 값이 10보다 크면 flag 변수를 false로 바꿔 반복문이 종료될 수 있도록 한다.
    	flag = false;
    }
    print('cnt2: ${cnt2}');
}


print('-'*20);  // -를 20번 반복하여 출력


// do while은 조건을 검사하기 전에 최소 한번 수행 하는 것만 다르다.
// 조건을 만족하지 않으면 실행을 하지 않는 while과 다르게, do while은 조건을 만족하지 않아도 최소 한 번은 수행한다.
int cnt3 = 0;
do {
	print(cnt3);
    cnt3++;
} while(cnt3<10);

결과

cnt: 0
cnt: 1
cnt: 2
cnt: 3
cnt: 4
cnt: 5
cnt: 6
cnt: 7
cnt: 8
cnt: 9
--------------------
cnt2: 1
cnt2: 2
cnt2: 3
cnt2: 4
cnt2: 5
cnt2: 6
cnt2: 7
cnt2: 8
cnt2: 9
cnt2: 10
cnt2: 11
--------------------
0
1
2
3
4
5
6
7
8
9

5. continue, break

반복, 분기가 존재하는 경우, continue 또는 break를 사용할 수 있다.
보통 for, while, switch 등에서 사용한다.

  • continue: 여기까지 진행하고 처음으로 돌아간다. 일부의 경우 뒤에 라벨을 붙여 해당 부분으로 이동할 수도 있다.
  • break: 여기까지만 진행하고 해당 구문을 종료한다. 일부의 경우 뒤에 라벨을 붙여 해당 부분을 종료할 수도 있다.
int i = 0;

while (true) {
	i++;
	if (i < 5) {  // i가 5보다 작을 때만 수행된다.
    	print(i);
        continue;  // continue 문을 만나면 이후 작업을 수행하지 않고 반복문의 처음(조건)으로 돌아간다.
    }
    
    if (i == 10) {
    	print('i의 값이 10이 되어 반복문을 종료합니다.');
    	break;  // break 문을 만나면 이후 작업을 진행하지 않고 반복문을 빠져나갑니다.
    }
    
    print('이 부분은 i가 5 이상일 때만 출력됩니다.  -> i: ${i}');
    
}

결과

1
2
3
4
이 부분은 i가 5 이상일 때만 출력됩니다.  -> i: 5
이 부분은 i가 5 이상일 때만 출력됩니다.  -> i: 6
이 부분은 i가 5 이상일 때만 출력됩니다.  -> i: 7
이 부분은 i가 5 이상일 때만 출력됩니다.  -> i: 8
이 부분은 i가 5 이상일 때만 출력됩니다.  -> i: 9
i의 값이 10이 되어 반복문을 종료합니다.

label을 사용한 continuebreak

반복문 위에 라벨을 작성하여 continue 및 break를 사용할 수 있다.

outerLoop:  // 외부 루프 라벨
for (var i = 0; i<5; i++) {
	innerLoop:
	for (var j = 0; j<5; j++) {
        if (i == 2) {
            print('outerLoop를 continue합니다.');
        	continue outerLoop;  // 외부 반복문을 패스하는 기능
        }
        
        if (j == 3) {
        	print('innerLoop를 continue합니다.');
        	continue innerLoop;  // 내부 반복문을 패스하는 기능
        }
        
        if (i == 4) {
        	print('outerLoop를 break합니다.');
        	break outerLoop;  // 외부에 있는 반복문을 한번에 빠져나갈 수 있는 좋은 기능
        }
        
        print('i: ${i}, j: ${j}');
    }
}

결과

i: 0, j: 0
i: 0, j: 1
i: 0, j: 2
innerLoop를 continue합니다.
i: 0, j: 4
outerLoop를 continue합니다.
i: 2, j: 0
i: 2, j: 1
i: 2, j: 2
innerLoop를 continue합니다.
i: 2, j: 4
i: 3, j: 0
i: 3, j: 1
i: 3, j: 2
innerLoop를 continue합니다.
i: 3, j: 4
outerLoop를 break합니다.

Refference

profile
작은 오븐의 작은 빵

0개의 댓글