C언어 while문 : 포문과 함께 많이 쓰인다.

코딩/C 2019. 8. 20. 00:22

 이제 C언어 while문을 배워봅시다. for문과 더불어서, 꽤 많이 쓰이는 반복문입니다. do while까지가 3대장인데요. 저것은 사용 빈도가 그렇게 높지는 않은 듯 싶어요. 문법은 다음과 같습니다.

 

 

while(contidion) s1

 

 

 대충 condition을 만족하면 s1 블록을 수행하고, 다시 condition을 만족하는지 검사한다. 정도로 보시면 됩니다. 그러면 condition이 참이면 계속 루프를 돈다는 것이겠군요. 넵. 맞습니다.

 

 

 그러니까 condition을 만족하면 Loop를 계속 돈다고 보시면 되겠습니다.

 

 


 먼저 백준의 A+B-5를 봅시다. 이것은 a와 b를 입력을 계속 받습니다. 파일의 끝에 도달할 때 까지요. 즉, 어떠한 입력 파일이 n개의 줄로 이루어져 있다면 n번째 줄에 a(n) b(n)이 주어지고 파일이 끝날 거에요.

 

 

 그러면 a와 b를 입력 파일에서 받을 수 있으면, a와 b를 입력 받아서 print를 하면 됩니다. 그렇지 않으면 빠져 나오면 되고요. 보통, C언어에서는 scanf를 이용하는데요. 이 함수는 EOF를 만나면 -1을 리턴합니다.

 

 

 그러면 결론은 scanf(...)의 값이 0보다 크면 a와 b를 scanf로 받아서 출력하면 되는 거고, 아니면 그냥 빠져 나오면 됩니다. 즉, while문의 조건에는 scanf의 리턴값이 0보다 큰가? 만 입력 받으면 됩니다.

 

 

 코드는 다음과 같습니다.

 

 


 그러면 0 0을 입력 받으면 끝내는 건 어떻게 해야 할까요? 아직 우리는 continue나 break문, return문을 배우지 않았어요. 그러니까 어떻게라도 해야 할 거 같은데요. 일단 입력의 끝에 도달하면 끝내기는 해야 합니다. 그런데, 0 0 다음에는 input이 끝난다는 조건이 걸려 있습니다.

 

 

 그러면, a와 b를 입력받을 때 EOF가 들어오지 않았는가? 는 공통입니다. while문에 들어갈 조건입니다. 그리고 a와 b를 받았을 때 이 두 값이 어때야 할까요? 그 전에 a가 0이면서 b가 0이면 출력을 하지 않아야 합니다. 맞나요? 그러면, 거꾸로 ~(a가 0이면서 b가 0이다) 이면, 출력을 해야 합니다. 그러면 a == 0이면서 b == 0을 부정하면 되겠네요.

 

 A and B를 부정하면 ~A or ~B입니다.

 

 

 그러면, 이렇게 다시 흐름도를 그릴 수 있어요. a가 0이 아니거나 b가 0이 아니라면 0 0꼴이 아니기 때문에 a+b를 출력하면 되고, 그게 아니라면 그냥 출력 안 하고 while에 걸린 조건문으로 바로 가면 될 겁니다.

 

 

 

 그러면 이런 식으로 처리하면 됩니다.

 

 


 이제 백준 1110번, 더하기 사이클을 풀어봅시다. 이 문제는 다음과 같습니다. 0보다 크거나 같고 99보다 작거나 같은 N이 있습니다. 이 사이에 있는 수들이 한 번 변환이 되면 다음과 같은 규칙으로 변합니다. 먼저 현재 수가 10보다 작다면, 앞에 0을 붙입니다. 예를 들어 8은 08이 됩니다. 다음에 자릿수 2개를 더합니다. 08의 자릿수 둘을 더하면 8입니다. 이를 결과값이라고 합시다.

 

 새로운 수를 만들 때에는 현재 수의 일의자릿수와, 결과값의 일의자릿수를 이어 붙여서 만듭니다. 그러면 현재 수가 8이였다면, 새로운 수는 88이 됩니다. 현재 수가 39였다면, 결과값은 12이기 때문에, 92가 됩니다. 42가 현재 수라면, 4+2 = 06입니다. 현재 수의 일의자리와 결과값의 일의 자리를 이어 붙이면 26이 됩니다.

 

 

 x를 규칙에 맞게 다음 수로 변환하는 루틴을 conv(x)라고 합시다. 그러면 크게 그림을 그리면 아래와 같습니다. 일단, n에서 출발하기 때문에, 기준 수는 n으로 잡습니다. 이것은 gi로 잡았습니다. 그리고 현재 cur는 conv(gi)의 값을 넣는데요. n을 규칙에 맞게 conversion을 한 결과를 넣습니다. 그러면 ans의 값은 처음에 1이 set 될 겁니다.

 

 그리고 cur의 값이 기준값과 다르다면 계속 while loop를 돌면 될 거에요. loop 안에 conv랑 ans의 값을 하나 증가시키는 무언가가 들어가야 할 거고요. 그러면 conv(x)를 어떻게 처리하느냐가 문제에요. 이것도 천천히 생각해 봅시다.

 

 

 먼저 두자릿수 x는 십의 자리가 x/10, 일의 자리가 x%10으로 나타낼 수 있습니다. x가 정수형이라면, x/10은, x를 10으로 나눈 몫을 의미하고, x%10은 x를 10으로 나눴을 때 나머지를 의미합니다. 예를 들어서 92는 십의 자리가 9, 일의 자리가 2인데요.

 

 그러면 res에 들어가는 것은 x/10 + x%10일 겁니다. 그런데 이 중 일의 자릿수만 취한다면 (x/10 + x%10)%10이 될 거고요. 우리는 이 값을 뒤에 붙여야 합니다. 앞에는 어떤 값을 붙여야 하나요? 원래 수 x의 일의자리수인 x%10을 붙여야 합니다.

 

 

 그러면 새로운 수는 (x%10)에다가 10을 곱한 값에다가 (x/10 + x%10)%10을 더하면 될 겁니다.

 

 

 이걸 토대로 conv 부분만 알아보기 쉽게 바꿔보면 다음과 같습니다. 사실, 이러한 건 그냥 모듈화 시켜 놓고 함수를 따로 만드는 게 편한데요. 함수는 제어문 끝나고 다뤄보도록 하겠습니다.

 

 

 이것을 while문으로 구현하면 다음과 같습니다.