-
Loops, functions | CS50 Week 1Computer Science/CS 50 Harvard 2021. 11. 6. 23:30
야옹(meow)하고 세번 프린트 하는 코드를 어떻게 만들 수 있을까?
#include <stdio.h> int main(void) { printf("meow\n"); printf("meow\n"); printf("meow\n"); }
세번 프린트 하면 된다! 컴파일을 하고 돌려보자.
> make meow clang meow.c -lcs50 -o meow > ./meow meow meow meow
잘 돌아간다. 하지만 100번 프린트하고싶다면? 1000번, 10000번은? 이를 위해서 loop을 이용해서 더 나은 디자인의 코드를 완성해보자.
while
Scratch 블락과 같은 동작을 할 수 있는 while loop을 이용하면, 조건에 따라서 영원히 또는 어떤 경우에 괄호안 동작을 하게끔 할 수 있다.
while (true) { printf("meow\n"); }
while loop은 괄호안 조건이 true일때만 동작하는데, 위의 예시는 항상 true이기 때문에, 멈추지않고 meow를 프린트하게 된다. 그렇기때문에 아래와같이 3이라는 조건을 만들어서 3번만 loop을 돌게 만들 수 있다.
int counter = 0; while (counter < 3) { printf("meow\n"); counter = counter + 1; }
counter라는 variable을 만들어서 0으로 설정해놓고, loop이 돌때마다, 몇번째 loop인지 카운팅을 하는 용도이다. while 의 조건을 counter < 3 으로 바꿔줘서, counter가 3보다 작을때만 동작을 하게끔 설정해준다. 매번 loop이 반복을 할 때 마다, 우리는 "meow"라는 문장을 보게될것이고, 이때마다 counter는 1씩 더해진다. 이 코드를 아래와같이 조금 단순화 시킬 수 있다.
int i = 0; while (i < 3) { printf("meow\n"); i++; }
기계만 알아들으면 되기 때문에, 간단하게 i 로 바꾸어주고, 짧게 i++ 로 바꾸어줬다.
for
for loop을 이용해서 똑같은 동작을 하는 프로그램을 만들수도 있다.
for (int i = 0; i < 3; i++) { printf("meow\n"); }
while loop에서 사용했던 로직과 거의 비슷하지만 시작과 끝이 어디인지 정확히 알 때 사용을 많이 한다. for loop에게는 3가지 정보를 세미콜론(;)으로 나눠서 알려주어야한다. 처음은 i를 만들어서 0으로 만든다는 정보를 주고 (int i = 0), 매 loop마다 조건이 맞는지 체크하기 위한 정보를 주고 (i < 3), 그리고 loop이 한차례 끝나면 변경시킬 것을 알려준다. 여기서는 i를 1씩 더해준다고 명시했다.
while loop과 다른점중 하나는, for loop에서는 for loop에서 만들어진 variable은 loop 안에서만 사용하고 접근할 수 있다. 반면에, while loop 밖에서 선언했던 i는 while loop이 끝나도 사용할 수 있다.
loops에 대해서는 추가 영상 자료도 준비되어있었다.
function
Scratch에서 custom block을 만들었던것처럼, C에서도 function을 만들어서 사용할 수 있다.
#include <stdio.h> void meow(void) { printf("meow\n"); } int main(void) { for (int i = 0; i < 3; i++) { meow(); } }
meow라는 단어를 프린트하는 meow라는 프로그램을 만들어서 main method에서 부를 수 있다. void meow(void)에서, 첫번째 void는 return값이 없다는 뜻이고, parentheses 안에 있는 void의 뜻은 이 함수(function)은 어떠한 argumetns 또는 input을 받지 않는다는 뜻이다. 프로그램을 컴파일하고 실행시켜보자.
> make meows clang meows.c -lcs50 -o meows > ./meows meow meow meow
잘 동작한다. 하지만 meow function을 아래쪽으로 옮기면 어떨까?
#include <stdio.h> int main(void) { for (int i = 0; i < 3; i++) { meow(); } } void meow(void) { printf("meow\n"); }
코드를 수정하고 다시 컴파일 후 돌려보았다.
> make meows clang meows.c -lcs50 -o meows meows.c:7:9: error: implicit declaration of function 'meow' is invalid in C99 [-Werror,-Wimplicit-function-declaration] meow(); ^ meows.c:11:6: error: conflicting types for 'meow' void meow(void) ^ meows.c:7:9: note: previous implicit declaration is here meow(); ^ 2 errors generated. make: *** [meows] Error 1
에러가 발생한다. 첫번째로, "implicit declaration"라는 에러인데, meow라는 함수를 사용했으나, 그게 무엇인지 알 수 없다는 내용이다. 이 함수가 무엇인지 정의되기 전에 사용되는것이 허용되지 않는다. 컴파일러는 우리 코드를 위에서부터 아래로 읽기 때문에 meow라는 함수가 존재하는지 모른다. 이 문제를 prototype을 선언해주는것으로 해결할 수 있는데, 컴파일러에게 "우리가 이런 function을 나중에 정의할것인데 이런 타입을 리턴할것이고 argument들은 이런것을 주는 함수이다" 라고 알려주는것이다.
#include <stdio.h> void meow(void); int main(void) { for (int i = 0; i < 3; i++) { meow(); } } void meow(void) { printf("meow\n"); }
수정한 코드는 위와 같다. void meow(void) 라는 prototype을 main 전에 선언해주는것이다. 이 라인을 읽을때까지는 아직 코드가 실행되는것이 아니다.
이후, meow function을 조금 발전시켜서, argument를 받을 수 있게 수정할수도 있다.
#include <stdio.h> void meow(int n); int main(void) { meow(3); } void meow(int n) { for (int i = 0; i < n; i++) { printf("meow\n"); } }
void meow(int n) 으로 수정해서 아무것도 안 받던 함수에서 integer인 input, n을 받는 구조로 바꾸었다. 그리고 loop에서는 i < 3 대신 i < n 으로 바꿔줌으로써, 0부터 n 전까지, 즉 n 회의 loop을 돌게 할 수 있다. 그리고, main에서 meow를 부르고, 숫자를 줌으로써 위 코드에서는 3회가 프린트된다.
우리가 사용하고있는 header files (.h 로 끝나는 파일들)은 위와같은, void meow(int n),와 같은 prototypes들을 담고있다. 그리고 library files들은 실제 이 함수들의 implementation을 담고있다. 추후에 main이 어떻게 inputs를 받고 outputs를 보내는지에 대해서 다룰것이다.
Reference
'Computer Science > CS 50 Harvard' 카테고리의 다른 글
Imprecision, overflow | CS50 Week 1 (0) 2021.11.07 Mario | CS50 Week 1 (0) 2021.11.07 Conditionals, Boolean expressions | CS50 Week 1 (0) 2021.11.06 Calculations | CS50 Week 1 (0) 2021.11.06 Variables, syntactic sugar | CS50 Week 1 (0) 2021.11.06