본문 바로가기

Education

[부스트 코딩 뉴비 챌린지 2020] week2: C언어

반응형

1. C 기초

들어가기 전에

그래픽 인터페이스로 상호작용성이 좋은 스크래치로도 간단한 프로그래밍을 할 수 있지만, 텍스트 기반의 프로그래밍 언어를 이용해도 컴퓨터에게 동일한 일을 하게 할 수 있습니다. 가장 널리 쓰이는 프로그래밍 언어중 하나인 C의 기초를 배워보겠습니다.

학습 목표

C로 “hello, world”를 출력하는 프로그램을 만들 수 있습니다.

핵심 단어

      • stdio.h
      • clang
      • 컴파일러

 

clang(클랭)

터미널에는 명령행 인자라는 것도 추가할 있다.

clang에서는 출력과 관련된 인자로 -o 사용할 있다. 어떤 이름이든 지정하여 머신코드 파일을 저장할 있다.

clang -o hello hello.c

이를 입력하게 되면, hello.c 출력이 hello 만들어지게 된다.

따라서 ./hello 입력하면 hello.c a.out 실행하는 ./a.out 입력하는 것과 같은 결과를 불러오게 된다.

 

명령어 프롬프트를 이용하면 마우스가 하는 모든 일을 있게 된다.

  • ls : list. 현재 폴더나 디렉토리에 있는 파일의 리스트를 보여준다.
🤔 ls입력 시 이름 뒤에 있는 *의 뜻은?
- executive. 실행 가능한, 컴퓨터가 이해할 수 있는 머신코드임.
- hello.c : 뒤에 *가 없으니 소스코드이다.
- => 소스코드와 머신코드를 구분할 수 있음
  • rm : remove (ex)rm a.out
  • mkdir : 디렉토리 생성
  • rmkdir : 디렉토리 삭제

 

2. 문자열

들어가기 전에

문자열을 다루기 위해서는 문자열 형식을 가진 변수가 필요합니다. 사용자로부터 문자열을 입력받고 이를 다른 문자열과 합쳐서 출력하는 프로그램을 C로 작성해보겠습니다.

학습 목표

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

핵심 단어

  • 형식지정자
  • string
  • make

 

학습하기

cs50 라이브러리에 있는 모든 함수들을 구현하는 코드를 추가하도록 해야 한다. 그러려면 다음 명령어를 입력한다.

clang -o string string.c -lcs50

-l 연결("link") 의미하고  뒤는 cs50이다. 이의 뜻하는 것은, 프로그램의 0 1들은 우리의 소스코드인 string.c에서 나온다.

cs50 작성자도 과거에 get_string 함수나 문자열과 같은 변수를 구현하기 위해 c 코드를 작성했을 것이다. cs50 라이브러리의 0 1들은 클라우드 어딘가에 저장되어 있을 것이다. 그들은 여러분의 0 1들과 연결되어야 한다.

, 여러분의 코드는  파일에 있고,  코드는 cs50.h 있으니, 컴퓨터에게 이걸 여러분의 소스코드에 추가하도록 하고 명령어로 둘을 연결시키는 것이다.  코드가  프로그램으로 실행될  있도록 말이다.

 

하지만 이는 복잡하고 어렵다.  좋은 방법이 있다. 코드를 컴파일할 , -o -lcs50같은 것들을 기억할 필요 없다. 이런 명령어들을 외우는 대신 개념만 이해하고, string이라는 프로그램을 만들어 달라고하면 끝이다.

make string

그럼 자동으로 만들어진다. 컴퓨터에게  프로그램을 만들어달라고만 하면 끝이다. 그럼 make라는 명령어는 알아서 어떤 인자를 사용해야 할지, 파일명은 무엇으로 할지, 다른 사람들은 어떤 라이브러리나 코드를 연결했는지 등을 찾아준다.

따라서 지금부터는 프로그램을 컴파일할  그냥 make 입력하고 프로그램 이름을 입력하면 된다. 하지만 make stirng.c 아닌 프로그램의 이름만을 입력한다. 그럼 make라는 프로그램은 그게 string.c라는 것을 알아서 찾아낼 것이다.

make 우리를 도와주는 아주 똑똑한 프로그램이기 때문에, make hello라고 하면 hello.c라는 파일을 찾는다. 찾고나면 hello라는 파일을 만든다. 소스코드에서 머신코드를 만드는 것처럼 말이다.

 

Q. make는 일반적인 명령어인가요,  cs50에만 있는 건가요?
A. 일반적인 명령어이다. 유닉스와 리눅스를 사용하는 컴퓨터들에 포함되어 있는 일반적인 툴이다.
make는 리눅스라는 운영체제에 있는 프로그램으로, 요즘은 맥과 윈도우에도 포함되어 있다. 이름을 입력해서 실행하는 프로그램으로 아이콘을 더블클릭하는 프로그램은 아니다.

 

Q. make는 컴퓨터에 저장된 건가요 아니면 클라우드 기반 컴퓨터에 저장된 건가요?
A. 클라우드에 저장되어 있다. 몇주간 우리가 하게 될 것들은 모두 cs50 샌드박스 그리고 곧 나올 cs50 랩이라는 클라우드 기반 환경에 저장되어 있다.
이는 리눅스와 맥, 컴퓨터 모두에서 작동되도록 설계되었지만 소프트웨어는 조금씩 다르기 때문에 소프트웨어 개발 분야에서 매우 유명한 운영체제인 리눅스에서 표준화한 것이다.

 

생각해보기

"좋아하는 동물을 알려주세요"로 질문하여 동물 이름을 animal이라는 변수에 저장하고, 이를 "내가 좋아하는 동물은"으로 출력해주는 코드를 작성해보세요.

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

int main(void) {
    string answer = get_string("좋아하는 동물을 알려주세요.\n");
    printf("내가 좋아하는 동물은 %s\n", answer);
}

 

3. 조건문과 루프

들어가기 전에

스크래치에서 블록으로 표현했던 조건문과 루프 또한 C로 동일하게 구현할 수 있습니다. 스크래치에서 여러 기능을 가진 블록들을 이어붙였던 것 처럼 C의 다양한 문법을 이용하면 조건문과 루프를 더 간단한 텍스트 형식으로 표현할 수 있습니다.

학습 목표

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

 

학습하기

소스코드 -> 머신코드로 컴파일하기

<=> make hello

 

프로그램 실행시키기

./ 프로그램 이름

 

= (할당연산자)

오른쪽에 있는게 무엇이든 왼쪽으로 복사됨

 

++

counter += 1;
counter++;

 

if

함수가 들어간 줄들은 세미콜론으로 끝나지만,

조건 뒤에는 세미콜론을 붙이지 않음

왜 조건 안에는 등호를 두 개 사용할까? (==)
등호 표시 하나는 할당 연산자로 정했기 때문에, 같다는 표시는 등호 표시  개를 사용해서 나타낸다.
   - = : 할당 연산자
   - ==: 일치 연산자
boolean (불리언)
예/아니오, 참/거짓, 1/0 값을 의미함
if문의 마지막 조건을 else로 작성하면 코드를 더 간단하고도 효율적으로 작성할 수 있게 된다.

 

while

  • <=> forever
  • 뭔가를 게속 반복하는 상황을 나타내기 위해 사용

루프를 구현하고 싶다면, 성립 조건을 정해주어야 한다. 답이 ,,1 나올  있는 질문을 던져 주어야 한다.

(ex) 항상 /거짓이 나오는 불리언 표현은? : true/false

따라서, 뭔가를 영원히 반복하는 무한 루프를 만들고 싶다면 while(true) 라고 작성하면 된다.

 

for

int i = 0;

while(i < 50) {
	printf("hello, world!\n");
}

이는 논리가 완성되지 않았다. 처음에 변수 0으로 설정하고, 계속해서 i 50보다 작은지를 물어본다.

여기서  코드가 정상적으로 작동하려면 무엇을 추가해야할까? i 증가시키는 것이다.

그걸 위해 안에 I = i+1;  추가하면 된다.

int i = 0;

while(i < 50) {
	printf("hello, world!\n");
	i = i+1;     // <=> i++;
}

이의  다른 방법이 있는데, 특정 횟수만큼 반복할  자주 사용하는 단어인 "for"이다.

for(int i=0; i<50; i++) { // 3번째: 변수를 어떻게 수정할 것인가?
	printf("hello, world\n");
}

위의 코드보다  코드가 짧아진다.

 

생각해보기

학습한 다양한 방법을 이용하여 "개발공부는 재미있다!"를 10번 출력하는 코드를 작성해보세요.

 #include <stdio.h>

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

 

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

들어가기 전에

C에서는 정수나 문자열 외에도 다양한 데이터 타입이 정의되어 있습니다. 또한 각 타입에 맞는 형식 지정자를 통해 적절한 포맷으로 출력하고, 다양한 연산자를 통해 조건문을 설정하거나 데이터 값을 계산할 수 있습니다.

학습 목표

  • 다양한 데이터 타입과 형식 지정자를 나타내는 방법을 학습합니다.
  • 다양한 연산자를 이용하여 조건문을 표현하는 방법을 학습합니다.

핵심 단어

  • char
  • long
  • float
  • double
  • %
  • &&
  • ||

 

다양한 종류의 데이터들

  • boolean: /거짓 (ex)while(true)
  • char: 딱 한 개의 문자 나타냄 (ex)y, n
  • int: 정해진 수의 정수를 나타냄. 40 정도 까지.
  • string: 쌍따옴표 안에 들어간   이상의 문자를 나타냄. char 하나하나보다 크다.
  • long: int보다   수를 요구할 경우 사용( 많은 비트를 사용하기 때문에  높은 수까지   있음)
  • float: 실수. 소수점이 있는 수들을 표현함
  • double: 소수점 뒤에  많은 숫자를 가질  있는 실수들을 의미함

 

CS50 라이브러리가 제공하는 기능

  • get_string
  • get_int
  • get_float
  • get_double
  • get_char

이들은 모두 사용자에게 특정 값을 물어보고 그들이 입력한 값을 사용할  있도록 해준다. 이와 같은 cs50 라이브러리  함수들은 사용자로 하여금 우리가 원하는 값을 입력하도록 강제한다. 에러를 미연에 방지하기 위함이다.

그래서 만약 get_int 1.5 혹은 apple라고 입력하면 정수값이 입력될 때까지 계속해서 질문한다.

 

형식 지정자

  • %s : char, string
  • %f : float, double
  • %i: int
  • %li : long

 

float

%f에서 f앞에 '.원하는 자리수'를 넣어 %.2f로 소수점 2번째 자리까지 나오게 할 수 있다.

 

터미널 명령어

  • cd ~ : 디렉토리 이동
  • cd : 기본 설정 디렉토리로 이동
  • pwd : 현재 위치를 알려줌
  • ls : 전체 파일/폴더 보기
    • 끝에 * : 실행 가능한 파일
    • 끝에 / : 폴더

 

#include<cs50.h> 는 무엇인가요?

CS50 수업을 위해 만들어진 라이브러리 입니다. 라이브러리는 여러 함수들을 모아둔 것이라고 볼 수 있습니다. CS50 수업에서는 여러분들께서 좀 더 쉽게 코딩을 짤 수 있게 CS50 라이브러리 안에 여러 함수(get_int, get_double, get_float 등등)를 만들어 두었습니다.

반면에 C에는 표준 라이브러리도 있습니다. 우리가 처음부터 사용한 #inclue<stdio.h>가 표준 라이브러리 중 하나 입니다. 가장 많이 쓰고 가장 보편적으로 사용하는 라이브러리입니다. 그 밖에도 <math.h>, <time.h> 등 자신이 코딩하는데 필요한 함수들을 그때 그때 라이브러리를 불러와서 다른 사람들이 만들어둔 함수를 사용할 수 있습니다. 이 강좌 이후에 직접 코딩을 해보고 좀 더 공부를 하다 보면 배우실 수 있을 것입니다.

그렇다면 sandbox.cs50.io가 아닌 Visual Studio 같은 곳에서 CS50 라이브러리를 바로 사용이 가능할까요? 답은 사용할 수 없습니다. 표준 라이브러리는 기본적으로 설치가 되어 있기 때문에 사용이 가능하지만 앞서 말씀드렸듯이 CS50 라이브러리는 수업을 위해 만들어진 라이브러리 입니다. 그래서 sandbox.cs50.io 처럼 미리 설치가 된 곳이 아니면 따로 설치를 하여야만 사용이 가능합니다. 설치하는 방법은 현재 수준에서 필요한 것이 아니기 때문에 아래 첨부된 CS50 라이브러리 문서를 참고해 주세요.

추가로 CS50 라이브러리의 get_int, get_float 등의 함수로 좀 더 쉽게 입력을 받아 보았는데요, 일반적으로 사용되는 입력을 받는 함수도 아래의 참고자료를 통해 학습하실 수 있게 준비해 두었으니 참고하시면 좋을 것 같습니다.

 

생각해보기

짝수인지 홀수인지 알려주는 코드짜기에 자신의 스타일 대로 주석을 달아보고 다른 수강생은 어떻게 주석을 달았는지 비교해보세요.

#include <stdio.h>  // printf, scanf ... 함수 포함하는 라이브러리
#include <cs50.h>   // get_int 함수 포함하는 라이브러리

int main(void){
    int n = get_int("n: "); // 사용자에게 하나의 정수값을 받음
    if(n % 2 == 0) { // 짝수인 경우  (% : 나머지)
        printf("even\n");   //even 출력
    }
    else {   // 홀수인 경우
        printf("odd\n");    // odd 출력
    }
}

 

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

들어가기 전에

프로그래밍을 하다 보면 가끔 반복적으로 작성해야 하는 코드가 있습니다. 이런 코드를 여러번 쓰지 않고 함수 형태로 저장해두면 코드를 간결하고 이해하기 쉽게 만들 수 있습니다. 사용자 정의 함수를 사용 하는 방법을 배워봅니다. 더불어서 하나의 루프로 수행하기 힘든 작업을 중첩 루프를 이용하여 해결하는 방법도 배워 보겠습니다.

학습 목표

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

핵심 단어

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

 

사용자 정의 함수

void: input, output 없는 경우,

 

하지만 여기에도 문제가 있습니다. 함수를 1개가 아닌 여러개를 만들수록 main 함수는 아래로 내려가기 때문입니다. 중요한 것이 아래에 있는 것보다 바로 나오는 것이 보기 좋습니다.

그럼 main 함수를 위로 올리고 cough 함수를 내려볼까요? 실행을 해보면 오류가 발생합니다.

main 함수에서 cough() 함수를 사용했습니다. 그런데 cough함수는 아래에 있습니다. C는 오래되었고 똑똑하지 않기 때문에 아래에 cough라는 함수가 있을 것이라 생각하지 못하는 것이죠.

여러분이 시킨대로만 행동합니다. 이 것을 해결하려면 다시 cough함수를 위로 올려야합니다. 물론 이것은 악순환의 반복일 것입니다. 영원히 새로운 함수를 위에 올릴 수 없으니까요.

 

그래서 다른 방법이 있습니다. void cough(void)를 세미콜론과 함께 위로 올리는 것입니다. 마치 이전에 cough를 봤던 것처럼 C를 속이는 방법입니다. cough함수를 전부 본 적은 없어도 이름은 본적이 있으니 main 함수에 나올 때까지 코드를 계속 읽도록 하는 것입니다.

 

중첩 루프

마리오 게임에서 흔히 보는 것 처럼 화면에 여러 개의 이미지를 가로나 세로로 여러 개 이어서 출력하고 싶으면 어떻게 해야 할까요? 아래처럼 for 루프를 사용할 수 있습니다.

 

6. 하드웨어의 한계

들어가기 전에

컴퓨터는 우리가 작성한 프로그램을 구동하기 위해 다양한 물리적 장치를 사용합니다. 그 중 하나는 메모리로, 프로그램이 필요한 정보가 저장되는 곳입니다. 메모리의 용량은 무한하지 않기 때문에, 때때로 프로그램에서 우리가 의도하지 않은 오류가 발생하기도 합니다.

학습 목표

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

핵심 단어

  • 메모리
  • 오버플로우

 

 소수점 부정확성

RAM

모든 프로그램이 실행  저장되는 곳이다. 그리고 모든파일이 열려있는 동안 저장되는 곳이다. 컴퓨터가 여러 일을  번에   기억하기 위해 사용하는 곳이다.

하지만  성능은 유한하다. 어디까지나 하드웨어이기 때문이다. , 컴퓨터가   있는 일에는 근본적인 한계가 있다는 것이다. 당연히 무한대까지 셀수도 없다. 저장공간이 유한하므로 저장가능한 숫자에도 한계가 있다.

이를 확인해보자. 사용자에게 실수값  개를 받아오는 프로그램인 float.c 만들어본다.

input  ouptut

메모리 저장 공간이 유한하므로 컴퓨터는 특정 지점에서 한게에 부딪히게 된다.  값보다는 높이   없거나, 소수점  이보다 많은 숫자는 저장할  없기 때문이다.

float 32비트를 사용하고, double   배인 64비트를 사용한다. 따라서  정확하게 계산할  있다. 하지만 컴퓨터가 계산할  있는 값은 유한하다. 그래서 컴퓨터가 계산할  있는 값들 중에서 1/10 가장 가까운 값을 저장하게 되는 것이다. 유한한 정보를 사용해서는 무한한 숫자들을 100% 정확하게 저장할  없기 때문이다.

=> 정확한 결과는 0.1 되어야 하지만, float에서 저장 가능한 비트 수가 유한하기 때문에 다소 부정확한 결과를 내게 되는 것이다.

 

정수 오버플로우

부동 소수점 부정확성이나 정수 오버플로우는 float 정확성이나 정수의 크기에 한계가 있다는 것을 의미한다. , 이런 것이다. 만약 숫자 3자리만 사용할  있다면, 999에서 1 더하게 되면 000 남게 된다.

이도 컴퓨터에서 마찬가지이다. 오버플로우가 일어나 앞으로 가져온 1 사라지면서 실제로 저장된 값은 0 남게 되는 것이다.

Y2K

1999 99 나타내었다.하지만 2000년을 1900으로 인식하게 되었다. 이를 Y2K문제라고 한다. 이는 통찰력 부족으로 인해 나타난 아주 현실적이고 값비싼 문제이다.

보잉 787

소프트웨어 내부 변수가 248일이 지난 후에 오버플로우되어 발생하게  문제이다. 이를 윙해 소프트웨어 업그레이드 준비중에 있다고 한다.

248일을 1/100초로 계산하면, 대략 2 32승이 나온다. , 보잉이 실제 787비행기에서 아주 중요한 부분을 설계할  사용한 정수가 너무 커져 전원이 켜진  248일이 지나면 오버플로우가 발생하고, 결국 비행기  모든 전력이 끊긴다는 것이다. 그래서 보잉은 248일마다 비행기를 재시동했다고 한다. 변수를 0으로 다시 리셋하기 위해서이다.

  여러 기능들

figlet

ASCII 아트라고 하는 형태로 문자들을 활용해서 멋진 형태로 화면에 출력해주는 프로그램

반응형