CS50 2주차 - C언어

5 minute read

이 포스팅은 부스트코스의 CS50 2019 강의의 내용을 공부한 글 입니다.

2주차 C언어 기초

C언어는 현재 사용되고있는 모든 언어의 시초라고도 할 수 있는 순수 텍스트기반 언어이다.

프로그래밍을 하게되면 가장 먼저 하는 것이 ‘Hello, world!!’를 실행하는 것이다.

#include<stdio.h>

int main(void)
{
    printf("Hello, world");
}

위에 코드는 가장 기초가 되는 ‘Hello, world’를 실행시키는 코드이다.

  • include - stdio.h 라는 이름의 파일을 찾아서 printf 함수에 접근 할 수 있도록 해준다.

  • int main(void) - ‘ 시작한다’ 라는 의미를 가지고 있고 중괄호 사이에 코드를 작성한다.

  • pirntf(); - 무언가를 출력하는 단어이고 () 안에 작성을 한다

  • ()안에 문자가 들어갈 때에는 “” 쌍따옴표로 감싸줘야 한다.

  • ; - 세미콜론은 우리가 평소에 문장의 끝을 맺는 곳에 마침표를 붙이는 것과 같다.

파일이름을 작성 할 때에는 .c를 붙인다.

이미지를 저장하는 .jpg .png 워드를 저장하는 .docx 같이 ‘C언어로 작성 된 코드이다’는 의미를 가진다.

위와 같은 코드를 ‘소스 코드’라고 불리다.

1주차때 배웠던 컴퓨터가 알아들을 수 있는 2진법으로 바꾸기 위해 ‘머신 코드’로 변환해야 하는데

이렇게 변환하는 과정을 ‘컴파일’ 이라고 한다. 컴파일을 도와주는 프로그램은 컴파일러이다.

소스 코드 -> 컴파일러 -> 머신 코드

위 과정을 진행하기 위해서 우리는 터미널창의 명령어 프롬프트에서 $ 기호옆에 명령어를 입력해야한다.

강의의 예로 clang hello.c라는 명령어를 입력하면

‘clang’라는 컴파일러로 ‘hello.c’라는 코드를 컴파일하는 의미를 가진다.


문자열

#include <stdio.h>
#include <cs50.h>

int main(void)
{
    string answer = get_string("What's your name?\n");
    printf("hello, %s\n", answer);
}

make answer

./answer

// What’s your name?

// Jamking

// hello, Jamking

위 코드를 통해 문자열에 대해서 알아보자.

string answer = get_string("What's your name?\n");

C언어는 오래된 언어이기에 변수가 저장하는 데이터 종류를 명확하게 명시해줘야 한다.

그래서 저장하고자 하는 값의 종류가 string이라는 것을 알려줘야 한다.

형식지정자 Place holder라고 하는 것을 통해서 string을 알려주었다.

answer은 변수의 이름이다. 다른 단어를 사용해도 되지만 간결하고 직관적인 단어가 좋다.

한마디로 ‘string answer’ 은 “answer”에게 들어갈 것들은 문자야!!”라고 알려주는 것이다.

’=’은 사람이 알고있는 같다가 아니고 ,오른쪽에 있는 것을 왼쪽으로 지정할거야 라는 의미이다.

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

print("hello, %s\n", answer);

함수를 출력하는 코드이다.

변수 answer에 들어있는 이름을 출력해야 하기에 %를 사용하고 s를 붙여

‘string’으로 인자를 받는다.

터미널에서 make라는 명령어로 원하는 이름으로 머신코드를 만들 수있고

./파일이름을 통해서 출력할 수 있다.

$ clang -o string string.c -lcs50 == $make string

마지막으로 **#include **는 string 값과 get_string 함수에 대한 코드가 포함되어있다.

그래서 #include 가 포함되어야만 컴파일이 가능하고 실행할 수 있다.


조건문 & 반복문

위에서 문자열을 변수에 저장하는 법을 배웠다. 그렇다면 숫자는??

int counter = 0;

연산자를 통해 변수에 할당 할 수 있다.

1씩 증가 시키는 코드는 세가지가 있다.

counter = counter + 1; // 길어서 가독성 떨어짐

counter += 1;

counter++; // 가독성이 좋음

조건문

조건문은 if를 통해서 구현한다.

#include <cs50.h>

#include<stdio.h>

int main(void)
{
  if (x < y)
  {
    printf("x는 y보다 작다"\n);
  }
  else if (x > y)
  {
    printf("x는 y보다 크다"\n);
  }
  else
  {
    printf("x는 y와 같다"\n);
  }
}

반복문 while

#include <cs50.h>

#include<stdio.h>

int main(void)
{
  int i = 0;
  while (i < 50>)
  {
    printf("hello, world\n");
    i = i++;
  }
}

반복문 for

#include <cs50.h>

#include<stdio.h>

int main(void)
{
  for (int i = 0; i <50; i = i++)
  {
    printf("hello, world\n");
  }
}

while문 보다 for문을 훨씬 간결해서 작성할 수 있다.


데이터타입, 형식 지정자, 연산자

데이터타입

**include**

  • bool - 참 / 거짓의 값을 가진다. true / false
  • char - “” 안에 들어 간 한개의 문자를 나타낸다. ex) “가”
  • string - “” 안에 들어간 한 개 이상의 문자를 나타낸다. ex) “가나다라마바”
  • double - float 보다 소수점 뒤에 더 많은 숫자를 가질 수 있다. ex) 1.23456789
  • float - 실수를 나타낸다. ex) 1.23
  • int - 정수를 나타낸다. 40억 정도까지 셀수 있다.
  • long - 특정 분야에서 40억 이상의 정수를 표현할때 사용.( 큰 기업 위주 )

. . .

**include**

  • get_char
  • get_double
  • get_float
  • get_int
  • get_long
  • get_string

형식 지정자

  • %c - char
  • %f - float, double
  • &i - int
  • &li - long
  • &s - string

int 값형식과 형식 지정자를 통한 코드

#include<cs50.h>
#include<stdio.h>

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

make int
./int

// What's your age?
// 28
// You are at least 10220 days old.

더 간결한 코드로 구현

#include<cs50.h>
#include<stdio.h>

int main(void)
{
    printf("You are at least %i days old.\n", get_int("What's your age?\n") * 365);
}

make int
./int

// What's your age?
// 28
// You are at least 10220 days old.

float 값형식과 형식 지정자를 통한 코드

#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);
}

make float
./float

// What's the price?
// 100
// Your total is 106.250000.

프린트 되는 문자에 소수점을 2자리만 보여줄 떄에

#include<cs50.h>
#include<stdio.h>

int main(void)
{
    float price = get_float("What's the price?\n");
    printf("Your total is %.2f.\n", price * 1.0625);
}

make float
./float

// What's the price?
// 100
// Your total is 106.25.

연산자

  • +: 더하기
  • -: 빼기
  • *: 곱하기
  • /: 나누기
  • %: 나머지
  • &&: 그리고
  •   : 또는
  • //: 주석

나머지 연산자를 통한 짝수, 홀수 구하기 구현

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int n = get_int("n: ");

    if (n % 2 == 0)
    {
        printf("even\n");
    }
    else
    {
        printf("odd\n");
    }
}

make parity
./parity

n: 4
even

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

사용자 정의 함수

#include<stdio.h>

void hello(int n);

int main(void)
{
    hello(3);
}

void hello(int n)
{
    for(int i = 0; i < 3; i++)
    {
        printf("hello, world!!\n");
    }
}

make helloWorld
./helloWorld

hello, world!!
hello, world!!
hello, world!!

위 코드는 main(void)의 안에 hello(int n)를 샤용한 코드이다.

C언어는 위에서부터 코드를 읽어내려가는 단순한 방식으로 실행되기 때문에

void hello(int n);

맨 위에서 먼저 함수를 읽을 수 있게해줘야 main(void)에 적용된다.

그리고 main(void)에 hello(int n)을 호출하고 n을 3으로 지정해주면

해당 프린트가 세번호출되는 것을 볼 수 있다.

사용자 정의 함수를 구현하게되면 장점이 많다.

  • 재사용되는 코드를 간결하게 해주어서 가독성이 좋아진다.

중첩 루프


#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int n;

    do
    {
        n = get_int("Size: ");
    }
    while (n < 1);

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            printf("#");
        }
        printf("\n");
    }
}

do-while은 do에서 무조건 적어도 한 번 수행한 뒤 조건을 확인하고

사용자의 협조 여부에 따라 다시 반복 할 지를 결정한다.

while문은 조건을 확인하고 true일 떄에 수행을 한다.

위 코드는 사용자가 지정한 Size가 1보다 클때 행과 열의 #이 만들어진다.


메모리 & 오버플로우

RAM(랜덤 액세스 메모리)

모든 프로그램이 실행 중 저장되는 곳이다. 컴퓨터가 여러 일들을 한 번에 할 때

기억하기 위해 사용한다. RAM은 유한한 크기의 비트만 저장할 수 있기 때문에

때때로 부정확한 결과를 내기도 한다.

다른 말로는 메모리 저장 공간이 유한하다면 컴퓨터의 특정 지점에서 한계에 부딪힌다.

Overflow

컴퓨터는 게속해서 숫자를 키워나가다보면 언젠가 한계에 부딪혀 더 큰 값을 저장할 수 없다.

부동 소수점 부정확성이나 정수 오버플로우는 float의 정확성이나 정수의 크기에

한계가 있다는 것을 의미한다.

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

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    float x = get_float("x: ");

    float y = get_float("y: ");

    // 나눗셈 후 출력
    printf("x / y = %.50f\n", x / y);
}

make floats
./floats

// x: 1
// y: 10
// x / y = 0.10000000149011611938476562500000000000000000000000

위 코드는 float 에 저장 가능한 비트의 수가 유한하기 때문에 잘못된 결과를 가져온 것이다.

오버플로우가 나게 되면 그 이상의 값은 저장할 수 없다.

Tags:

Categories:

Updated:

Comments