boostcource
모두를 위한 컴퓨터 과학 (CS50 2019) : David J. Malan
www.boostcourse.org/cs11
실습환경 : https://sandbox.cs50.io/
C언어
오래되고 전통적인 순수 텍스트 기반의 언어 C
이전에 스크래치를 사용해서 만들어보던 프로그램을 이제는 프로그래밍 언어로 작성해볼 수 있다.
int main(void){ } 는 "초록색 깃발을 클릭했을 때"와 같은 시작을 의미하는 부분이라 이해해볼 수 있다.
간략하게 C언어는 #include <stdio.h> int main(void) { ... } 에서 ... 위치에 동작할 코드를 작성한다.
즉, 핵심은 printf("hello, world"); 부분이 된다.
printf 는 C언어의 함수로 프린트한다는 단어와 같이 사용자 눈에 보이도록 결과를 출력하는 동작을 한다.
예시의 경우는 "hello, world" 라는 문장을 사용자에게 보여주는 것이다.
C로 작성한 코드는 "파일이름.c"로 저장해야 한다. c라는 확장자를 가진다.
Compiler
앞서 C언어로 작성한 코드와 같이, 우리가 직접 작성한 코드를 소스 코드(source code)라고 말한다.
이전에 2진법을 공부했던 이유는 무엇이였는가? 컴퓨터가 2진법만을 이해하기 때문이였다.
이렇게 0과 1로만 만들어진, 컴퓨터가 이해할 수 있는 언어의 코드를 우리는 머신 코드(machine code)라고 말한다.
우리가 작성한 내용을 컴퓨터에서 작동하도록 하기 위해서는
소스 코드를 머신 코드로 번역하는 중간 단계가 필요한데, 이를 우리는 컴파일(compile) 이라고 말한다.
그리고 컴파일을 수행하는 프로그램을 컴파일러(compiler)라고 칭한다.
Source Code -> Compiler -> Machine Code
C로 작성된 소스 코드를 머신 코드로 만들기 위해서 강의에서는 clang 이라는 컴파일러를 이용한다.
만일 소스 코드가 저장된 파일의 이름이 hello.c 인 경우, 아래와 같은 명령어를 이용해 컴파일을 수행할 수 있다.
$ clang hello.c
명령어를 수행하면 a.out 이라는 파일이 새롭게 생성된다
a.out 을 클릭한다면 "File contains binary data and cannot be displayed" 라는 문구가 뜨며 자세한 내용물을 보여주지 않는데, binary data 라는 것을 보아 0과 1로 이루어진 머신 코드로 잘 변환된 것으로 추측된다.
a.out 은 아래 명령어로 실행 가능하며, 결과는 터미널에 노출된다.
$ ./a.out
+)
터미널에 자동 작성되는 "$" 기호는? 프롬포트(prompt)
prompt의 사전적 의미는 "사용자의 명령을 받아들일 준비가 되었음을 모니터에 나타내는 표시" 이다.
즉, 이 곳에 무언가를 작성하라는 의미이다.
문자열 (string)
단어나 구절, 문장을 의미하는 데이터의 종류(type)
C언어에서 문자열을 사용하려면
변수 명 앞에는 string 이라는 데이터 타입을 명시해야 하는데 이 string을 형식지정자라고 한다.
CS50 Sandbox 에서는 cs50.h 의 get_string 함수를 이용해서
What's your name? 으로 질문을 던진 뒤에 사용자가 입력한 대답 문자열을 저장할 수 있다.
string answer = get_string("What's your name?\n");
프로그래밍 언어에서 = 는 같다의 의미가 아니라
우측의 값을 왼쪽이 갖도록 한다, 지정한다와 같은 의미로 이해해야 한다. 이를 할당연산자라고 한다.
정리하자면 위 코드는
get_string 함수가 사용자의 이름을 반환하면 그 이름을 answer라는 문자열 변수에 저장하는 것이다.
이렇게 만들어진 answer가 과연 원하는대로 만들어졌는지 확인하기 위해서는 printf 함수를 사용할 수 있다.
printf("hello, %s\n", answer);
"hello, 령이" 와 같이 이름을 넣은 문장을 만들 수 있도록 %를 이용해 인자를 받아준다.
이름이라는 문자열을 받아야 하기 때문에 string의 s를 이용해서 %s 를 사용해준다.
그리고 answer 값이 해당 자리에 들어가게 된다.
printf("hello, answer"); 라고 작성하면 그대로 "hello, answer" 문장이 출력된다는 점을 참고해서
우리는 왜 %가 필요한지, 왜 인지가 필요한지에 대해 이해해볼 수 있다.
C언어의 함수들은 인자를 받지 않거나, 1개를 받거나, 여러가지를 받을 수 있다.
필요에 따라 아래과 같이 %s 를 연속으로 사용하면서 printf 함수를 이용할 수 있다.
#include <stdio.h>
#include <cs50.h>
int main(void)
{
string pink = "핑크";
string blue = "블루";
printf("%s와 %s \n", pink, blue);
}
// ? 핑크와 블루
컴파일을 수행하는 터미널 명령어는 아래와 같이 사용할 수 있다.
앞서 진행했던 $ clang string.c 컴파일 명령어는 머신코드의 파일명을 따로 지정할 수 없었으나 아래처럼 옵션들을 이용하면 조금 더 상세한 컴파일을 수행할 수 있다.
// string.c 를 string.out 이라는 머신코드로 저장하는 -o 함께 사용
// cs50 파일을 합치기 위해서 연결(link)해주는 -l 함께 사용
$ clang -o string string.c -lcs50
// 위 과정 대신 간단하게 컴파일 수행하는 make 명령어도 사용 가능
$ make string
// 머신코드 실행
$ ./string
조건문과 반복문에 대해서 알아보기 이전
앞서 문자열을 다룬 것과 다르게 이번에는 숫자를 다뤄보자,
counter라는 변수에 숫자를 저장하고 싶기 때문에 데이터 타입을 숫자로 지정해주어야 하는데
숫자 중에서도 정수(integer)라는 것을 알려주기 위해 int 를 이용한다.
int counter = 0; 을 통해서 변수 counter는 0으로 저장(초기화) 할 수 있다.
변수 counter에 값을 1씩 증가시키고 싶다면 counter = counter + 1; 이라고 작성할 수 있다.
앞서 = 가 할당연산자라고 설명했듯이 counter에 1을 더한 값을 다시 counter 저장(할당)했다는 의미이다.
그리고 이 연산은 +=, ++ 과 같은 방식으로도 사용할 수 있다.
int counter = 0; // 0 (초기화)
counter = counter + 1; // 1
counter += 1; // 2
counter++; // 3
조건문 (condition)
데이터 타입 중 숫자를 이용하면 관계 연산자 >, < 를 사용할 수 있게 된다.
관계 연산자는 결과로 참(true)과 거짓(false) 두 값인 불리언(boolean)을 결과로 반환하기 때문에 조건문에서 이용하기에 적합하다.
숫자 x와 y 두 변수를 가지고
- x가 y보다 작은 경우
- 그 외 (x가 y보다 크거나 같은 경우)
로 두 조건을 나누어, 각 조건을 만족할 때 수행하고자 하는 작업을 지정할 수 있다.
C언어는 조건문을 표현하기 위해 if 를 사용한다.
if () 의 괄호 안에는 검사하고자 하는 조건을 집어넣고
{ } 안에는 조건을 만족할 때 수행하고자 하는 작업을 집어넣는다.
else 를 이용하면 if 로 지정한 조건이 아닌 경우를 대응할 수 있다.
만일, 조건을 x<y / x>y / 그 외 와 같이 3가지 이상을 지정하고 싶은 경우에 else if 도 사용이 가능하다.
if(x < y) {
printf("x는 y보다 작다");
} else if (x > y) {
printf("x는 y보다 크다");
} else { // x == y
printf("x는 y와 크기가 같다");
}
주석으로 처리한 x == y 중 == 를 잠깐 짚어보자면, 할당 연산자 = 와는 다르다.
여기서 사용된 등호는 x와 y가 같다 를 표현하는 일치 연산자이다.
같다의 의미로 사용하려면 꼭 두 번 사용해야만 함을 기억해야 한다.
+)
위 코드에서는 조건이 3가지로 완전히 나눌 수 있기 때문에
if - else if - else 를 이용했는데
if - else if - else if 와 비교하자면 위 방식이 더 효율적이라고 판단이 가능하다.
굳이 세번째 조건에 해당하는지 안하는지 체크하지 않고 바로 남은 경우에 대해 대응하기 때문.
코딩에서는 얼마나 효율적으로 하는지, 얼마나 적은 메모리나 CPU를 사용해서 수행하는지가 아주 중요하기 때문에
위와 유사한 상황을 맞닥뜨릴 때 뭐가 더 좋은 코드가 될 지 스스로 판단하고 적용해야 한다.
루프 (loop)
다음은 루프, 반복문에 대한 내용이다.
스크래치에서는 forever, repeat 50 과 같은 블록을 이용해 수행한 "영원히 반복하기", "50번만 반복하기" 를
C언어에서는 while, for 등으로 수행 가능하다.
while의 경우 ( ) 안에 조건을 작성하고, { } 안에 수행할 작업을 지정한다.
괄호 안에 작성한 조건이 만족하는 경우에만 대괄호 안에 작성한 작업을 수행하기 때문에
조건 위치에 참(true) 값이 나올 수 있는 질문을 넣어주어야 한다.
만일 위 예시처럼 while (true) { ... } 와 같이 작성하면 forever 영원히 printf 함수를 수행한다.
특정 횟수만큼 작업을 수행하고 싶다면 조건으로 숫자 변수를 이용할 수 있다.
int i = 0;
while (i < 50) {
printf("hello, world\n");
i++; // 작업 수행 마다 i값을 1씩 증가
}
// i가 0~49인 동안 총 50회 printf() 수행
위는 i로 숫자 변수를 따로 선언하고 작업마다 덧셈하도록 만들었는데
이 경우는 반복문 내에서만 변수를 사용하는 for를 사용해 간단하게 표현할 수 있다.
for (int i = 0; i < 50; i++) {
printf("hello, world\n");
}
for () 안에 각각 (변수 초기화; 변수 조건; 변수 증가) 로 반복할 횟수에 대한 조건을 선언하여 사용한다.
'CS > CS50' 카테고리의 다른 글
[CS][CS50] C언어 - 하드웨어의 한계 (2) | 2023.05.26 |
---|---|
[CS][CS50] C언어 - 사용자 정의 함수, 중첩 루프 (0) | 2023.05.24 |
[CS][CS50] C언어 - 자료형, 형식 지정자, 연산자 (0) | 2023.05.09 |
[CS][CS50] 컴퓨팅 사고 - 알고리즘 (0) | 2023.04.23 |
[CS][CS50] 컴퓨팅 사고 - 컴퓨터 과학 / 2진법 / 정보의 표현 (0) | 2023.04.22 |