WHILE믄에 해당하는 글 1

[아두이노] 아두이노 코딩 WHILE 문

IOT/아두이노기초문법|2019. 4. 13. 09:00

[아두이노] 아두이노 코딩 WHILE 문



오늘은 제어문 중에 While문에 대해 설명하고자 합니다. While문은 For문과 유사한 반복문을 수행하는 제어문입니다. 대개 For문에서 배운 코딩을 While문으로 표현을 억지로 시키는 경우가 있고 그 반대로 While문을 배운 표현을 억지로 For문으로 코딩해보라고 시키는 경우가 있습니다. 사실 동작원리가 유사하기 때문에 표현은 가능하지만 이렇게 처음 배운분들은 대개 어떤 경우에 For문을 쓰고 While문을 쓰는지 선택하기 어렵습니다. 오히려 두 제어문을 배우면서 초보분들의 머리속에서는 "나보고 어떤 것으로 코딩하라는 거야!"라고 생각이 들게 합니다. 진짜 안좋은 학습인데 둘은 구분지어 따로 사용하는 방법으로 배우셔야 합니다. 두 제어문은 동작원리는 동일합니다. 하지만 사용하는 방향은 차이가 있습니다. 그런데 두 제어문을 배우면서 똑같은 코딩을 하라고 강요를 하게 되면 사실 두 제어문을 어떻게 써야할지 역효과가 발생하기 때문에 억지로 For문의 코딩을 While문으로 표현하는 방식을 강요하지 않겠습니다. 사설은 이만하고 While문에 대해서 알아보도록 하겠습니다.

1. WHILE 문을 FOR 문과 왜 구별해야 하는가?



지난 시간의 For문의 순서도를 왜 다시 While문을 설명하는데 올려놨냐고 의아해 하시는 분들이 많을꺼에요. 이게 While문 순서도 입니다.

[ For 소스 ]

void setup()
{
  Serial.begin(9600);
  
  int A[6] = {10,20,30,40,50,60};
  
  for(int i=0;i<6;i++){
    Serial.println(A[i]);    
  }
}

[While 소스 ]

void setup()
{
  Serial.begin(9600);
  
  
  int A[6] ={10,20,30,40,50,60};
  int i=0;
  while(i<6){  
    Serial.println(A[i]);
    i++;
  }
}

[ 결과 ]


결과는 For문과 동일하게 나왔네요. 소스를 보니깐 "For문과 다르네!"라고 하시겠죠. 초기값, 조건식, 증감연산, 실행문의 명령부분들이 For문에 있던 것들이 그대로 표현되었습니다. 해당 명령들의 코딩 위치만 좀 바뀌었을 뿐이죠.

for(초기값; 조건식; 증감연산){
    실행문;
}
초기값;
while(조건식){
    실행문;
    증감연산;
}


위 그림처럼 구조가 나뉘고 순서도에서 본것처럼 For문이나 While문 유사하게 동작합니다. 그래서 처음 접하시는 분들은 For문과 While문에서 어떤 제어문을 써야할지 잘 구별을 못합니다. 처음 배울때 While문 배울때 억지로 While문으로 표현했던 내용을 For문으로 만들어 오라고 레포트를 내줬던 기억이 나네요. 의도는 For문의 사용능력도 키우기 위한 목적이였지만 처음 배우는 사람은 서로 다른 제어문이 똑같은 동작 코딩을 하라고 요구하면 나중에 뭔가를 표현하려고 할 때 두 제어문에서 선택에 대한 혼동을 하게 됩니다.

초보분들은 완전 분리된 개념으로 차이나게 학습 해야 합니다. 그래야 이럴 때 이 제어문을 사용하고 저럴 때 저 제어문을 사용하게 됩니다. 초보분들에게는 For문이나 While문이나 그게 그거라고 생각되기 때문에 개념을 잡는게 무엇보다 중요합니다.

2. WHILE 문과 For 문의 차이점


For문은 일정한 규칙의 반복문에서 사용하기 좋고 While문은 불규칙적인 반복문에서 사용하기에 좋습니다. 처음에는 구분하여 생각해 주세요. 즉, For문은 시작과 끝이 일정한 간격으로 규칙적으로 접근하거나 반복하거나 할때 For문을 사용하고 While문은 시작은 주어졌지만 끝이 날때까지는 명령을 가변적 반복할 때 사용한다고 생각하시면 됩니다.


위 그림 표현에서 For문은 반복하기전에 시작때 반복횟수가 정해져 있고 일정한 간격으로 해서 순차적으로 반복을 하게 됩니다. 이 느낌을 잘 기억해 주세요.

그리고 While문은 뭐랄까 반복 횟수가 정해져 있지 않고 While문이 실행되면은 그안에서 반복을 하다가 조건이 끝나면 빠져나오는 느낌이라고 생각하시면 됩니다.

예를들면, 번호 자물쇠가 있는데 자물쇠 번호를 모를때 자물쇠를 열려고 계속 시도하는 과정을 While문이라고 생각하시면 됩니다. 번호 자물쇠가 운좋게 한번에 눌러서 열릴 수도 있고 100번을 눌러서 열릴 수도 있잖아요. 이렇게 계속 반복적으로 번호를 누르는 동작을 수행하면서 어떤 조건에 만족하면 빠져나오는 원리라고 생각하면 좋을 듯 싶네요.

뭔가 For문은 순차적으로 정해진 횟수만큼 반복하는 느낌이고 While문은 진입하게 되면 계속 그 안에서 탈출하려고 반복적으로 시도하는 느낌이라고 생각하면 좋을 것 같네요.

다른 예로는 회원 주소록을 만든다고 해봅시다. 주소록을 입력하는 창을 코딩했을 때 사용되는게 While문이고 주소록을 조회할 때 사용되는게 For문의 느낌입니다.

while(상태=="Y"){
 이름 입력;
 나이 입력;
 주소 입력;
 계속 입력하시면 "Y" 종료하실려면 "N";
}

이렇게 회원 등록을 입력하고 나서 또 등록이 필요하면 "Y"을 입력해서 다시 While문을 반복합니다. 하지만 이게 시작값에서 회원 주소록이 꼭 입력횟수가 정해져 있는게 아니라 주소록 입력을 한명하고 나서 바로 나올 수 있고 2명이상이면 그 이상 입력하고 빠져 나오기 때문에 반복횟수가 정해져 있지 않는 상황에서는 For문 보다는 While문이겠지요.

주소록 조회 같은 경우는

for(int i=0;i<회원수;i++){
    회원[i]정보;
}

회원 주소록 조회할때는 이미 입력이 끝났고 고정된 회원수에서 회원정보를 조회하게 됩니다. 입력된 회원수만큼 검색을 해야 하잖아요 고정된 회원수 만큼 반복명령을 수행하게 됩니다. 그럴때 For문을 사용하게 되는 것이죠.

For문은 반복의 횟수가 정해져 있고 While문은 반복의 횟수가 정해져 있지 않는 제어문에 사용하기 좋다고 생각하시면 됩니다. 둘 다 반복문이지만 약간 다른 느낌으로 개념을 처음에 잡아 주세요.

그냥 이렇게 생각하세요. For문은 일정한 반복문을 수행하는데 고정된 정해진 횟수만 만큼 반복되는 제어문에 어울리고, While문은 고정되어 있지 않은 끝이 만족할 때까지 반복 횟수는 달라지는 제어문에 어울린다라고 생각하시면 되겠습니다.

엄밀이 따지면 For문도 반복 횟수를 고정 시킬 수 있고 반복 횟수를 가변적으로 코딩 할 수 있습니다. 그리고 While()문도 반복 횟수를 고정 시킬 수 있고 반복 횟수를 가변적으로 코딩 할 수 있습니다. 처음 공부하시는 분들은 둘을 동일하게 생각하고 배우게 되면은 코딩을 할 때 어떤것을 써야할 지 어려워 합니다.

처음은 이정도로 해서 차이나게 구분 지어 주세요. 참고로 For문을 이용해서 While문처럼 가변적인 횟수로 반복할 수 도 있고 While문에서 For문처럼 고정적인 횟수로 반복할 수 있는데 그렇게 코딩하면 코딩의 가독성이 떨어집니다.

그 상황은.

for(int i=0;i<10;i++)

이 문장 한줄 For문 안에 반복명령이 0~9까지 10번 반복수행한다는 것을 쉽게 확인 할 수 있습니다. 한줄로 for문의 반복횟수를 쉽게 이해할 수 있죠. 하지만 아래의 같은 경우를 살펴봅시다.

int i=0
while(i<10){ 
반복명령문; 
i++;
}

이 경우는 i++ 증감연산이 while문 안에 있기 때문에 코딩이 짧으면 쉽게 찾을 수 있지만 코딩이 복잡하고 길면 사실 while()문이 10번 반복되는지 확인이 쉽지 않습니다. 코딩 안에서 i=i+2로 2씩 증가한다면 반복 횟수는 절반으로 줄어 들겠죠. 코딩의 가독성이 현저하게 떨어집니다. 그래서 For문으로 표현하고 While문으로 표현하지 않습니다.

반대의 경우은,

while(입력값>0){
    반복명령문; 
    입력값변화;
}

이렇게 입력값변화에 따라서 while문은 반복합니다. 이 한줄로 "아! 입력값이 도달할때까지 계속 반복수행하구나!"로 가독성이 높습니다. 하지만 아래와 같은 경우를 살펴봅시다.

for(입력값;입력값>0; ){
 반복명령문;
 입력값변화;
 }

이렇게 표현을 할 수 있지만 실제 코딩을 하고나면 부자연스러워 집니다. 증감연산부분을 생략해서 빠진 느낌과 For문이 가지고 있는 고정적이고 순차적인 이미지에서 벗어나게 되고 억지로 실을 꿰맨 느낌을 갖는 코딩이 됩니다. 이 느낌은 아직 For문과 While문의 개념이 서지 않는 상태에서는 잘 모를 수 있습니다. 이부분은 나중에 코딩을 많이 연습해 보시면 그 의미를 이해가 됩니다.

3. WHILE 문



While문은 두가지 표현 형식이 있습니다.

while(입력값>0){
  명령문;
    입력값의 변화;
}

위 식은 표에서 설명 했듯이 while문의 명령문을 수행하기 전에 조건식에 만족하는지 먼저 체크합니다. 입력값이 '0'보다 큰가를 체크하고 '0'보다 크면 조건식이 참이 되고 명령문을 수행합니다. 이때 수행된 명령문에 의해 입력값은 변하게 되고 그 변화된 입력값이 다시 '0'보다 크면 방금 수행된 명령문을 다시 반복 수행하게 됩니다. 이렇게 입력값이 '0'보다 클 때 까지 계속 반복하는 제어문이라고 생각하시면 됩니다.

do{
  명령문;
    입력값의 변화;
}while(입력값>0);

위 식은 표에서 설명 했듯이 while문의 명령문을 먼저 한번은 꼭 수행한 뒤에 수행 후의 결과값을 기준으로 while()문을 계속 반복할지를 결정하는 방식입니다.

두개의 차이점을 예를 들면은,

while("배고파"){
    밥먹어;    
}

이렇게 처음에 "배고픈지"체크 한뒤에 배고프면은 밥을 계속 먹게하다가 어느정도 포만도에 도달하면 배가 안고파지면 While문을 빠져 나온다고 생각하시면 됩니다. 먼저 배고픈지 체크를 한 뒤에 밥을 먹는 방식이고요.

do{
 센서값 측정해;
 계산해;
}while("원하는 값 아냐!")

이렇게 표현하면은 아두이노가 센서의 값을 측정하고 나온 값이 원하는 값인지를 계산한 뒤에 원하는 값이 아니라면 다시 측정을 하고 원하는 값이 나올때까지 계속 반복하는 방식이라고 생각하시면 됩니다. 이렇게 먼저 명령을 수행한 뒤에 그결과를 토대로 다시 명령을 수행할지를 결정하는 방식입니다.

두가지 비유가 좀 이상했지만 순간 떠오른 것을 글로 쓰다 보니깐 적절한 비유가 생각이 안나네요.

혹시 이해가 안되면 다시 순서도로 보시기 바랍니다.


위 순서도에서 While문에서 조건식이 참일때 명령문을 수행하고 다시 조건식으로 돌아와서 체크합니다. 그리고 계속 True일때는 계속 반복하다가 조건식이 거짓(False)가 되면 빠져 나옵니다.


위 순서도에서 먼저 do의 중괄호 안에 명령문을 먼저 수행한 뒤에서 조건식을 체크합니다. 그리고 참이면 다시 do안에 문장을 반복 수행합니다. 조건식이 거짓(False)가 될때 비로소 빠져 나오게 됩니다.

위에서 말로 만든것처럼 이 순서도에 일상의 말로 대입해서 한번 표현해 보세요.

While 예제

이게 실험 할 예제를 마땅치 않아서 시리얼통신 예제로 loop()함수를 대신 while()함수로 표현 해보았습니다.



[ 원소스 ]

void setup() {
  Serial.begin(9600);    //시리얼 통신 9600 통신속도로 시작
}
void loop() {
  
  if (Serial.available() > 0) { //데이터가 수신되었는지 확인
    char ch = Serial.read(); //1byte 읽음
    Serial.println(ch); //1byte 읽은거 출력
  }
}

ch변수에 시리얼 통신을 통해서 들어온 1byte 데이터를 저장합니다. 그리고 저장된 값은 시리얼모니터로 다시 출력하는 프로그램입니다. 주석을 달았지만 이해가 안가셔도 괜찮습니다. 여기서 외부로 부터 시리얼통신으로 데이터를 읽고 그 데이터를 시리얼모니터로 출력하는 로직이라고만 알고 계시면 됩니다. loop()함수 안에서 이 동작을 계속 반복하잖아요. 그것을 While문으로 표현을 하면 아래와 같습니다.

[ While 소스 ]

void setup()
{
  Serial.begin(9600);  
  
  while(1){
    if(Serial.available() > 0) { //데이터가 수신되는지 확인
      char ch = Serial.read(); //1byte 읽음
      Serial.println(ch); //1byte 읽은거 출력
    }
  }  
} 

원소스에서 loop()함수는 전류가 공급되면 계속 무한 반복하는 함수라고 했죠. 그 역할을 while(1)으로 표현을 해서 setup()함수에 넣어 While문을 loop()함수와 동일하게 무한 반복을 시켜버려린 코딩입니다. 원소스나 While문 소스는 동일한 동작을 수행하는 명령입니다. while(1)은 조건식이 0이 아니면 참이라고 했죠. 1이니깐 무조건 While 문은 참이되고 영원히 참이되는 문한 방복함수가 됩니다. 그래서 시리얼통신으로 계속 데이터를 읽고 그 값을 시리얼모니터로 출력이 이루어 집니다. 원소스 loop()함수와 같은 함수가 되어버린 것이죠.

[ 결과 ]


결과는 위 그림처럼 나오게 됩니다. 시리얼 통신으로 'a'를 입력 하면 그 값이 시리얼모니터로 'a'가 출력됩니다. 아두이노 예제를 들어 표현을 하다 보니깐 시리얼통신 예제를 사용했네요. 시리얼통신 명령문을 설명하자면 또, 길어지니깐 참고 자료에 링크가 걸린 시리얼 통신 포스트를 보시기 바랍니다.

다른 예제로는,

 while (!Serial.available());  

이런 문장이 있으면 어떤 의미일까요. 데이터 수신되었는지 확인하는데 문장입니다. Serial.available()함수는 시리얼통신으로 데이터가 수신되지 않으면 반환값은 '0'이 됩니다. 수신되면 '0'이 아닌 값이 되겠죠. 그러면 저렇게 문장을 표현하면 데이터가 입력이 될 때 까지 무한 대기하게 됩니다. 한마디로, "난! 데이터가 입력될 때 까지 기다리고 있을꺼야!"라고 생각하시면 됩니다. 데이터가 입력이 되면 While()문을 빠져나와서 다음 명령문을 수행 하겠죠.

void setup()
{
  Serial.begin(9600);   
 
}  
void loop()
{
   while (!Serial.available());  
   char ch = Serial.read(); //1byte 읽음
   Serial.println(ch); //1byte 읽은거 출력
 
}

표현은 이렇게 됩니다.

시리얼통신 명령문으로 예제를 들었는데 좀 어렵게 되어 버렸네요.

loop()함수를 대신 while(1)로 표현을 했고 그다음 어떤 상태가 만족할 때까지 무조건 대기하는 "while(조건식);"을 다뤄 보았습니다. 아두이노 상에서 While문을 설명하려고 하니 적절한 예제가 시리얼통신 뿐이 생각 안나네요. 시리얼통신을 이해해야 하는데 오히려 더 복잡하게 되었네요.

그냥, 1부터 입력된 수 까지의 합을 구하시오. 예제로 하겠습니다. For문의 느낌이 강해서 이런 예제를 안들려고 했는데 While문의 동작을 이해하는 차원으로 소개 합니다.

int input_val = 10;
int total=0;

while(input_val>0){
    total=total+input_val;
    input_val--;
}

코딩에서는 input_val로 변수를 선언하고 임이의 숫자 '10'을 저장 시켰습니다. 이것을 입력값이라고 정하고 나서 조건식이 '0'보다 클때 참이니깐 입력값이 '0'이될때 까지 while문은 반복하게 됩니다.
그리고 'input_val--'로 한번씩 반복명령문을 수행할 때마다 input_val값은 1씩 감소하게 됩니다. 이 의미는 10이 입력되면 10에서 부터 1씩 감소해서 0이 될때 While문을 빠져나오게 된다는 의미가 됩니다.

입력된 수 까지의 합은,

total = total+input_val
input_val이 10일때  => total = 0 + 10;
input_val이 9일때  => total = 10 + 9;
input_val이 8일때  => total = 19 + 8;
...
input_val이 1일때 => total = 54 + 1;

이렇게 입력된 수까지의 합이 구해지게 됩니다. 마지막 "total = 55"가 되겠죠. While문이 어떤 느낌으로 돌아가는지 이해가 되셨는지 모르겠네요.

위 시리얼통신 예제는 이해가 안되면 이 예제로 이해해 주세요. for문 성향이 유사해서 예제 코딩을 좀 고민 했네요.

마무리


While문의 의미를 보다 쉽게 전달해야 했는데 For문과 차별화를 너무 고집한 나머지 예제를 어려운 걸 보여 드린 것 같고 좀 어렵게 설명이 되었네요.

For문과 While문은 반복 제어문으로 유사하지만 For문은 회수가 정해진 고정된 일련의 규칙적인 반복 제어문에 어울리고 While문은 고정되지 않는 반복 제어문의 표현에 어울리는 제어문이라고 생각해 주세요.

While문과 For문의 소스들을 많이 접해 보고 따라 해보면 그 차이를 구분하여 사용하실 수 있을꺼에요.

댓글()