• 2024. 6. 12.

    by. 취PT


    모두를 위한 컴퓨터 과학(CS50 2019) 강의를 듣고 요약한 내용입니다.
    해당 글에는 퀴즈에 대한 정답 및 풀이도 있습니다. 아직 퀴즈를 풀지 못하신 분들은 퀴즈를 풀고 난 후에
    해당 포스팅을 읽으시길 바랍니다.

     

    목차

    1) C 기초

    2) 문자열

    3) 조건문과 루프

    4) 자료형, 형식 지정자, 연산자

    5) 사용자 정의 함수, 중첩 루프

    6) 하드웨어의 한계

     

     


    1. C 언어 - C 기초

    학습 목표: C로 "hello, world"를 출력하는 프로그램을 만들 수 있습니다.

     

    C 언어

    - C는 아주 오래되고 전통적인 순수 텍스트 기반의 언어
    - 검은 색 바탕에 있는 이상한 글씨들은 아래의 스크래치 블록과 결과적으로 정확히 같습니다.

     

     

    - #include <stdio.h> 는 "stdio.h"라는 이름의 파일을 찾아서 "printf" 함수에 접근할 수 있도록 해줍니다.

    - int main(void) 는 "초록색 깃발을 클릭했을 때" 블록과 같은 역할을 합니다. 

    - printf("hello, world\n")은 스크래치의 "'hello, world'라고 말하기" 블록과 같은 역학을 합니다.

    - 글자나 단어, 문장을 적을 때는 텍스트에 쌍따옴표로 감싸야 합니다.

    - C에서 코드가 끝날 때는 세미콜론을 붙입니다.

    - \n 은 줄바꿈(개행)을 의미합니다.

     

     

    컴파일러

    - 우리가 직접 작성한 코드: 소스 코드

    - 2진수로 작성된 코드: 머신 코드

    - 소스 코드를 머신 코드로 변환해야 컴퓨터가 우리의 소스 코드를 실행할 수 있습니다.

    - 소스 코드를 머신 코드로 변환해주는 프로그램: 컴파일러

     

     

    - 터미널 창의 명령어 프롬프트에서 "$" 기호 옆에 우리가 원하는 명령어를 입력하면 됩니다.

    - clang hello.c 라는 명령어는 "clang" 이라는 컴파일러로 "hello.c" 라는 코드, 파일을 컴파일 하라는 의미입니다.

    - 그 결과 a.out 이라는 파일이 생성됩니다. (a.out 이라는 파일 이름이 마음에 들지 않으면 clang -o "마음에 드는 이름" hello.c 를 입력하고 실행시켠 됩니다.)

    - 터미널 창의 명령어 프롬프트에서 ./a.out 이라는 명령어를 실행하면 컴퓨터가 현재 디렉토리에 있는 a.out 이라는 프로그램을 실행하게 해줍니다.

     

     

     


    2. C 언어 - 문자열

    학습 목표: C로 문자열 형식을 가진 변수를 선언하고 출력하는 프로그램을 만들 수 있습니다.

     

    실습

    - String(문자열)은 단어, 구절, 문장, 알파벳 글자들이 쌍따옴표에 들어가 있습니다.(숫자와는 다른 종류의 데이터)

    - 왼쪽 사진을 아래와 같이 C 언어로 작성해보겠습니다.

     

     

    - 사용자의 이름을 받아서 저장할 변수를 answer 라고 정해보겠습니다.(answer라는 글자 외에 다른 문자가 와도 괜찮습니다)

    - C 언어는 변수가 저장하는 데이터의 종류를 정확하게 명시해야 합니다.

    - answer 라는 변수에 담기는 값의 종류가 문자열이라는 것을 명시하기 위해 string 을 붙여줍니다.

     

    - 프로그래밍 언어에서 = 는 오른쪽에 있는 것을 왼쪽에 있는 것에다가 지정한다는 의미

    - = 는 할당 연산자 

    - get_string 함수가 사용자의 이름을 반환하면 그 이름을 answer 라는 변수에 저장합니다.

     

     

    - printf 함수는 뭔가를 화면 상에 출력하고 싶을 때 사용하는 함수

    - printf("hello, %s\n", answer) 에서 괄호 안의 내용물을 인자 혹은 매개 변수라고  하며 우리의 입력이 들어가는 것입니다. 

    - answer 값을 활용해서 출력 시, printf("hello, answer") ❎, printf("hello, %s\n", answer) 🅾️

    - 입력하고자 하는 값이 문자열이라면 모든 형식 지정자에 %s 가 필요합니다.

     

     

    - 현재 단계에서는 문자열이라는 것이 C 에 없습니다. 

    - 문자열은 이 강의가 제공하는 cs50.h 라는 파일 안에 있습니다. 

    - stdio.h 에서 printf 함수를 가져온 것처럼 문자열, get_string 함수에 대한 정의가 cs50.h 라는 파일 안에 있습니다.

    - 위 코드를 컴파일할 때 나타났던 문제의 원인은 문자열이 뭔지 컴퓨터가 몰랐기 때문입니다. get_string 함수가 무엇인지 몰랐기 때문입니다.

     

     

    - cs50 라이브러를 사용할 때는 두 가지를 명심해야 합니다.

    - 먼저 소스코드에서는 #include <cs50.h> 를 통해 컴퓨터에게 cs50 파일을 추가해야 한다고 명령합니다.

    - 코드를 컴파일 할 때도 마찬가지로 clang -o string string.c -lcs50 명령을 통해 cs50 파일을 링크 시켜줘야 합니다. 

    - 위 코드에서 " -l " 은 연결을 의미합니다. 따라서 위 명령어는 cs50파일을 연결해서 string.c 파일을 컴파일하라는 의미의 코드입니다.

    - 또는 터미널 창에 명령어 프롬프트에 make string 을 입력하면 위와 같은 작업을 똑같이 수행합니다.

    - make 라는 명령어는 알아서 어떤 인자를 사용해야 할지 파일명은 무엇으로 할지, 어떤 라이브러리나 코드를 연결했는지 등을 찾아서 알아서 만들어줍니다. 

    - 따라서 지금부터는 프로그램을 컴파일 할 때 make를 입력하고 프로그램을 입력하면 됩니다. make string.c 이렇게 입력하지 말고 make string 이렇게만 입력해줘도 string.c 라는 소스코드를 컴파일 하라는 의미이구나를 압니다.

    - make 라는 명령어는 cs50 한정적인 것이 아니라 유닉스와 리눅스를 사용하는 컴퓨터들에 포함되어 있는 일반적인 툴입니다.

     

     

     


    3. C언어 - 조건문과 루프

    학습 목표: 조건문과 루프를 c로 작성할 수 있습니다.

     

    조건문

    - C 는 지정하고자 하는 변수의 종류(데이터 타입)를 알려줘야 합니다.

    - 숫자를 저장하고 싶을 때, 특히 정수(integer)를 저장하고 싶을 때 변수명 앞에 int 를 붙여줍니다.

     

     

    - if ( ) 의 괄호 안에는 검사하고자 하는 조건이 들어가고, { } 안에는  조건을 만족할 때 수행하고자 하는 작업이 들어갑니다.

    - == 는 일치 연산자 입니다. 등호 표시 하나는 이미 할당 연산자로 정해져 있기 때문에 =을 2개 사용하여 같다는 표현하자라고 오래전 약속되었습니다. 

    - if, else, else if 뒤에는 세미콜론(;)을 붙이지 않습니다.

     

     

     

    루프

    - C 에서도 while 이나 for 을 통해서 루프를 구현

     

     

    - while ( ) 괄호 안에 조건을 넣고 { } 안에 수행할 작업을 포함시킵니다.

    - 위 코드에서는 true라는 항상 참이 되는 조건을 통해 while 루프가 영원히 수행됩니다.

     

     

    - for 를 사용하면 for ( ) 안에 각각 (변수 초기화; 변수 조건; 변수 증가) 에 해당하는 코드를 넣어서 간단하게 표현할 수 있습니다.

     

     

    실습

    - 개발공부는 재미있다!"를 10번 출력하는 코드를 작성해보세요.

     

    #include <stdio.h>
    
    int main(void)
    {
        for (int i = 0; i < 10; i++) {
            printf("개발공부는 재미있다!\n");
        }
    }

     

     


    4. C언어 - 자료형, 형식 지정자, 연산자

    학습 목표:
    1) 다양한 데이터 타입과 형식 지정자를 나타내는 방법을 학습합니다.

    2) 다양한 연산자를 이용하여 조건문을 표현하는 방법을 학습합니다.

     

    데이터 타입

    - bool: 불리언 표현, (예) True, False, 1, 0, yes, no
    - 
    char: 문자 하나 (예) 'a', 'Z', '?'

    - string: 문자열

    - int: 특정 크기 또는 특정 비트까지의 정수 (예) 5, 28, -3, 0

    - long: 더 큰 크기의 정수

    - float: 부동소수점을 갖는 실수 (예) 3.14, 0.0, -28.56

    - double: 부동소수점을 포함한 더 큰 실수

    * int 는 대략 40억 (four billion) 까지 셀 수 있습니다.

     

     

    형식 지정자

    - %c : char

    - %f : float, double

    - %i : int

    - %li : long

    - %s : string

     

     

    기타 연산자 및 주석

    - +:  더하기

    - -: 빼기

    - *: 곱하기

    - /: 나누기

    - %: 나머지

    - &&: 그리고

    - ||: 또는

    - //: 주석

     

     

    정수와 실수를 받아서 출력해보기

    - 정수 데이터 타입을 표현할 때는 int, 정수의 형식 지정자는 %i

     

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
        int age = get_int("What's your age?\n");
        printf("You are at least %i days old\n", age * 365);
    }

     

    - 실수 데이터 타입을 표현할 때는 float, 실수의 형식 지정자는 %f

    - 소수점 2번째 자리까지 나오게 하고 싶다면 형식지정자를 %.2f 로 작성하면 됩니다.

     

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
      float price = get_float("What's the price?\n");
      printf("Your total is %f.\n", price * 1.0625);
    }

     

     


    5. C언어 - 사용자 정의 함수, 중첩 루프

    학습 목표: 사용자 정의 함수와 중첩 루프를 작성할 수 있습니다.

     

    사용자 정의 함수

    - 동일한 작업을 반복하는 코드를 사용자 정의 함수를 만들어 사용할 수 있습니다.

     

    #include <stdio.h>
    
    int main(void) {
      printf("cough\n");
      printf("cough\n");
      printf("cough\n");
    }
    #include <stdio.h>
    
    void cough(void)
    {
      printf("cough\n");
    }
    
    int main(void)
    {
      for (int i = 0; i < 3; i++)
      {
        cough();
      }
    }

     

    - main 함수와 같이 중요한 함수는 바로 나오는 것이 좋습니다. 

    - 그러나 위의 코드에서 cough와 main 함수의 위치를 바꾸면 main 함수 내에 있는 cough 를 인식하지 못해 오류가 발생합니다.

    - 이런 오류를 방지하기 위해 void cough(void); 코드를 main 함수 위에 작성합니다. 이 코드는 cough 함수 전체를 알 수는 없지만 cough 라는 이름을 가진 함수가 있음을 알려줍니다.

     

    #include <stdio.h>
    
    void cough(void);
    
    int main(void)
    {
      for (int i = 0; i < 3; i++)
      {
        cough();
      }
    }
    
    void cough(void)
    {
      printf("cough\n");
    }

     

    - 원하는 횟수만큼 "cough"를 출력할 수 있습니다.

     

    #include <stdio.h>
    
    void cough(int n);
    
    int main(void)
    {
      cough(3);
    }
    
    void cough(int n)
    {
      for (int i = 0; i < n; i++)
      {
        printf("cough\n");
      }
    }

     

    cough 함수 내 int n 은, cough 함수가 입력값을 받는데 int 형식을 갖고 n 이라는 변수에 저장하겠다는 의미입니다.

     

    #include <cs50.h>
    #include <stdio.h>
    
    int get_positive_int(void);
    
    int main(void)
    {
      int i = get_positive_int();
      printf("%i\n", i);
    }
    
    int get_positive_int(void)
    {
      int n;
      do
      {
        n = get_int("Positive Integer: ");
      }
      while (n < 1);
      return n;
    }

     

    - get_positive_int 함수는 int 값을 반환합니다. 정의된 함수 왼쪽에 표시된 int는 함수의 반환 값의 종류를 의미합니다. 즉, 출력의 종류를 의미합니다.

    - get_positive_int 함수 내에 정의된 void는 입력의 종류를 의미합니다. 입력값을 아무것도 받지 않는다면 void를 표시합니다.

     

     


    6. C 언어 - 하드웨어의 한계

    학습 목표: 메모리 용량이 프로그램의 구동에 미치는 영향을 설명할 수 있습니다. 

     

    부동 소수점 부정확성

    - 실수 x, y를 인자로 받아 x 나누기 y를 하는 프로그램이 있다고 가정했을 때,  x에 1을, y에 10을 입력하면 아래와 같은 결과가 나옵니다.

    - 컴퓨터는 모든 정보를 0과 1로 저장하고 숫자 또한 마찬가지 입니다.

    - 0.1 라는 실수를 0과 1로 구성된 이진수로 바꾸면 0.000110011... 무한 소수값이 나옵니다.

    - 메모리는 유한한 값만 저장할 수 있기 때문에 무한 소수를 정확한 값으로 저장할 수 없습니다. 

    - 약간의 오차가 있는 무한소수를 저장했기 때문에 아래와 같이 다소 부정확한 결과를 내게 되는 것입니다.

     

     

    정수 오버플로우

    - 비슷한 오류로 1부터 시작하여 계속해서 2를 곱하여 출력하는 프로그램이 있다고 가정했을 때, int 타입이 저장할 수 있는 수를 넘은 이후에는 아래와 같이 에러가 발생하며 0이 출력됩니다.

    - int 는 32개의 비트(4byte) 의 크기만큼만 저장할 수 있습니다.

    - 따라서, 다루고자 하는 데이터 값의 범위를 유의하며 프로그램을 작성하는 것이 중요합니다.

     

     


    퀴즈

    3. C언어로 작성된 hello.c 소스코드를 컴퓨터가 이해할 수 있는 머신코드로 컴파일 하기 위해 어떤 명령어를 프롬프트에 입력해야할까요?

    $clang hello.c

     

    4. 사용자 이름이 저장된 문자열 변수 name와 "Hello"를 연결해서 출력하려합니다. 올바른 C언어 코드는 무엇인가요?

    printf("Hello, %s", name);

     

    5. ‘x가 y와 같다면’ 이라는 조건문을 C 코드로 나타내면 어떻게 될까요?

    if (x == y)

     

    6. 변수 x가 입력되었을 때 x가 짝수인지 홀수인지 알아내는 프로그램을 구현하기 위해 사용하면 좋은 연산자는 다음 중 무엇인가요?

    %

     

    8. 아래와 같이 hello()라는 사용자 정의 함수를 작성한 후, 메인 함수에서 사용하려고 합니다. 파일 상단에 정의되어야하는 코드는 무엇일까요?

    void hello(int n);

     

    10. 컴퓨터 하드웨어의 한계로 인해 발생하는 문제 중 하나로, 변수가 담을 수 있는 최대 허용 범위를 벗어난 값을 저장해 예상치 못한 결과가 나오는 현상을 무엇이라고 하나요?

    오버플로우