부스트코스 CS50 코칭스터디2기 3주차

승아·2021년 1월 25일
0

CS50 코칭스터디2기

목록 보기
3/6

📌 배열

프로그램 실행 단계

  1. 전처리(Precomplie)
    #으로 시작되는 C 소스 코드는 전처리기에서 실질적인 컴파일이 이루어지기 전에 무언가를 실행하라고 알려줍니다.
    예를 들어, #include는 전처리기에게 다른 파일의 내용을 포함시키라고 알려줍니다. 프로그램의 소스 코드에 #include와 같은 줄을 포함하면, 전처리기는 새로운 파일을 생성하는데 이 파일은 여전히 C소스 코드 형태이며 stdio.h 파일의 내용이 #include 부분에 포함됩니다.
  2. 컴파일(Complie)
    전처리기가 전처리한 소스 코드를 생성하고 나면 그 다음 단계는 컴파일입니다. 컴파일러라고 불리는 프로그램은 C코드를 어셈블리어라는 저수준 프로그래밍 언어로 컴파일합니다.
    어셈블리는 C보다 연산의 종류가 훨씬 적지만, 여러 연산들이 함께 사용되면 C에서 할 수 있는 모든 것들을 수행할 수 있습니다. C코드를 어셈블리 코드로 변환시켜줌으로써 컴파일러는 컴퓨터가 이해할 수 있는 언어와 최대한 가까운 프로그램으로 만들어 줍니다. 컴파일이라는 용어는 소스 코드에서 오브젝트 코드로 변환하는 전체 과정을 통틀어 일컫기도 하지만, 구체적으로 전처리한 소스 코드를 어셈블리 코드로 변환시키는 단계를 말하기도 합니다.
  3. 어셈블(Assemble)
    소스 코드가 어셈블리 코드로 변환되면, 다음 단계인 어셈블 단계로 어셈블리 코드를 오브젝트 코드로 변환시키는 것입니다. 컴퓨터의 중앙처리장치가 프로그램을 어떻게 수행해야 하는지 알 수 있는 명령어 형태인 연속된 0과 1들로 바꿔주는 작업이죠. 이 변환작업은 어셈블러라는 프로그램이 수행합니다. 소스 코드에서 오브젝트 코드로 컴파일 되어야 할 파일이 딱 한 개라면, 컴파일 작업은 여기서 끝이납니다. 그러나 그렇지 않은 경우에는 ㄹ이크라 불리는 단계가 추가됩니다.
  4. 링크(Link)
    만약 프로그램이 (math.h나 cs50.h와 같은 라이브러리를 포함해) 여러 개의 파일로 이루어져 있어 하나의 오브젝트 파일로 합쳐져야 한다면 링크라는 컴파일의 마지막 단계가 필요합니다. 링커는 여러 개의 다른 오브젝트 코드 파일을 실행 가능한 하나의 오브젝트 코드 파일로 합쳐줍니다. 예를 들어, 컴파일을 하는 동안에 CS50 라이브러리를 링크하면 오브젝트 코드는 GetInt()나 GetString() 같은 함수를 어떻게 실행할 지 알 수 있게 됩니다.

이 네 단계를 거치면 최종적으로 실행 가능한 파일이 완성됩니다.

💡 컴파일링 과정을 거치지 않고 기계어로 프로그래밍을 바로 작성한다면?

  • 내가 기계어를 배워야 함
  • 내 동료가 기계어를 배워야 함
  • 가독성이 떨어짐

디버깅(Debugging)

코드 상에 있는 버그를 식별하고 고치는 과정 오류를 고치기 위해 필요함

💡 디버깅을 도와주는 도구가 없다면?

  • 오류가 의심되는 부분에 printf()를 도배하여 변수들의 상태를 살펴보고
  • 코드를 다시 컴파일-실행해서 출력을 하나씩 확인합니다

코드의 디자인

협업하기 위해 필요. 컴퓨터 언어 각각의 스타일 가이드 또는 업무 단위의 약속
C -> snake_case, Java -> camelCase

배열(Array)

  • 인덱스와 번호에 대응하는 데이터들로 이루어진 프로그래밍 언어에서 가장 기초적인 자료구조
  • 일반적으로 같은 종류의 데이터들이 순차적으로 저장되어, 상대적인 위치로 표현됨
  • 같은 자료형의 데이터를 메모리 상에 저장하고 이를 하나의 변수로 관리하기 위해 사용

전역 변수

const int N = 3;

const 키워드를 이용해 선언. 관례적으로 전역 변수는 대문자로 표현한다.

string

char의 배열. "HI!"입력시 메모리에 종단문자 \0가 추가로 들어간다.

string.h

문자열 라이브러리

  • strcpy : 문자열 복사
  • strcat : 문자열 합침
  • strlen : 문자열 길이
  • strcmp : 문자열 비교

ctype.h

  • toupper : char를 대문자로 변환
  • tolower : char를 소문자로 변환
  • isalnum : char이 알파벳 또는 숫자이면 0이 아닌 값을 반환한다
  • isgraph : char이 그래픽 문자이면 0이 아닌 값을 반환한다
  • __toascii : char를 아스키 코드로 변환한다

명령행 인자

main() 안에 기계적으로 void 라고 입력하는 대신 아래 코드와 같이 argc, argv 를 정의해보겠습니다.

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

int main(int argc, string argv[])
{
    if (argc == 2)
    {
        printf("hello, %s\n", argv[1]);
    }
    else
    {
        printf("hello, world\n");
    }
}

여기서 첫번째 변수 argc는 main 함수가 받게 될 입력의 개수입니다. 그리고 argv[]는 그 입력이 포함되어 있는 배열입니다. 프로그램을 명령행에서 실행하므로, 입력은 문자열로 주어집니다. 따라서 argv[]는 string 배열이 됩니다. argv[0]는 기본적으로 프로그램의 이름으로 저장됩니다. 만약 하나의 입력이 더 주어진다면 argv[1]에 저장될 것입니다. 예를 들어 위 프로그램을 “arg.c”라는 이름으로 저장하고 컴파일 한 후 “./argc”로 실행해보면 “hello, world”라는 값이 출력됩니다. 명령행 인자에 주어진 값이 프로그램 이름 하나밖에 없기 때문입니다. 하지만 “./argc David”로 실행해보면 “hello, David”라는 값이 출력됩니다. 명령행 인자에 David라는 값이 추가로 입력되었고, 따라서 argc 는 2, argv[1] 은 “David”가 되기 때문입니다.

📺 라이브

개발자가 지켜야할 덕목

  1. 모르는 것을 두려워하지 말자 (배우는 것을 두려워하지 말자)
  2. 의사소통
  3. 스트레스 관리

함께 일하고 싶은 개발자 또는 동료가 되는 법

  1. 리뷰를 잘해주는 동료
  2. 아는 것/모르는 것을 공유해주는 동료

요건 역량은 꼭 챙기자

  • 코드 스타일
  • 테스팅

API(Application Programming Interface)

  • 응용 프로그램에서 사용할 수 있도록, 운영체제나 프로그래밍언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 의미함

팀미션 👩🏻‍💻

  1. 학점 계산 문제
  • 제일 쉬웠던 문제 난이도는 저번주차와 비슷하다.
#include <cs50.h>
#include <stdio.h>

string calculateGrade(int myScore){
    string grade[] = {"A+","A","B+","B","C+","C","D+","D","F"};
    if (myScore >= 95){
        return grade[0];
    } else if(myScore >= 90){
        return grade[1];
    } else if(myScore >= 85){
        return grade[2];
    } else if(myScore >= 80){
        return grade[3];
    } else if(myScore >= 75){
        return grade[4];
    } else if(myScore >= 70){
        return grade[5];
    } else if(myScore >= 65) {
        return grade[6];
    } else if(myScore >= 60) {
        return grade[7];
    } else {
        return grade[8];
    }
}

int main(void){
    int myScore = 0;

    printf("학점 프로그램\n");
    printf("종료를 원하면 \"999\"를 입력\n");
    printf("[ 학점 테이블 ]\n");
    printf("점수 : 95   90  85  80  75  70  65  60  0\n");
    printf("학점 : A+   A   B+  B   C+  C   D+  D   F\n");

    while(true){
        myScore = get_int("성적을 입력하세요 (0 ~ 100) : ");
        
        if(myScore == 999){
            printf("학점 프로그램을 종료합니다.\n");
            break;
        }

        if(myScore >= 0 && myScore <=100){
            printf("학점은 %s 입니다.\n",calculateGrade(myScore));
        } else {
            printf("** %i 성적을 올바르게 입력하세요. 범위는 0 ~ 100 입니다.\n",myScore);
        }
    }

}
  1. 없는 숫자 찾기
  • redirection을 사용한 문제 make hello < 10.txt 을 입력하면 10.txt 파일을 scanf()를 통해 읽어준다. txt파일엔 여러개의 숫자가 무작위로 저장되어있으며 그 중 빠진 숫자를 찾는 문제이다. 풀이 방법은 1 ~ n까지의 합 공식인 n(n+1)/2를 활용하여 n까지의 합을 구한 후 txt 파일에 있는 숫자의 합을 빼주면 된다.
#include <cs50.h>
#include <stdio.h>
#define SIZE 500000

int main(int argc, char*argv[]){
    int n;

    scanf("%d", &n);

    // 1부터 N의 숫자중 K가 빠진 배열
    int partArr[SIZE];
    int lengthOfPartArr = n-1;
    long totalSum = n * (n + 1) / 2;
    long sum = 0;

    for(int i=0; i < lengthOfPartArr; i++){
        scanf("%d", &partArr[i]);
        sum += partArr[i];
    }

    printf("K : %ld\n", totalSum - sum);

    return 0;
}
  1. Queue
#include <cs50.h>
#include <stdio.h>
#define MAX 10

int front = -1;
int rear = -1;
int queue[MAX];
int count = 0;

void add(){
    if (count == MAX){
        printf("Queue가 꽉 찼습니다.\n" );
    } else {
        int value = get_int("숫자를 입력하세요 : ");
        rear = (rear + 1) % MAX;
        queue[rear] = value;
        count++;
    }
}

void pop(){
    if(count == 0){
        printf("Queue가 비었습니다.\n" );
    } else {
        front = (front + 1) % MAX;
        count--;
    }
}

void display() {
//     - 반복문을 사용하여 배열의 모든 요소를 출력 (hint: front, rear 변수 범위로 배열값을 출력)
    if (count == 0){
        printf("Queue가 비었습니다.\n" );
    }
    else {
        if(front >= rear){
            printf("Queue : " );
            for(int i = front+1; i<= MAX + rear; i++){
                printf("%d ",queue[i % 10]);
            }
            printf("\n");
        } else {
            printf("Queue : " );
            for(int i = front+1; i<=rear; i++){
                printf("%d ",queue[i]);
            }
            printf("\n");
        }
    }
}

int main(int argc, char*argv[]){
    int num = 0;
    while(num != 4){
       num  = get_int("1.add 2.pop 3.display 4.quit : ");

      switch(num){
        case 1 : 
            add(); 
            break;
        case 2 :
            pop();
            break;  
        case 3 :
            display();
            break;  
        default :
            break;   
        }

        printf("f : %d , r : %d\n",front, rear);
    }
    
    return 0;
}

회고 ✍🏻

3주차 난이도는 초보자들에게 너무 어려웠던것 같다 😭 우리팀도 거의 반 이상이 문제를 풀지 못하였다. 나도 1학년때 이 문제를 받았다면 절대 풀지 못했을거다.. 하지만 출제의도는 이해가 된다. 코딩을 하다 보면 모르는문제를 매번 직면하게 되니 이런 난이도를 한 번 접해보는것도 도움이 될 수 있을수도 ...?!
이번 문제 중 제일 재밌었던 문제는 2번문제이다. 텍스트파일의 숫자가 무작위로 있어 순서를 통해 찾는게 아닌 총합을 구해 찾아야된다. 나는 밑에 힌트가 있어 생각도 안하고 바로 풀었지만 만약 힌트가 없었으면 얼마나 헤매였을지 궁금하다..
다음주는 어렵다는 사람들의 의견때문에 난이도를 조절해서 나온다고한다. 다음주는 팀원들이 다 풀고 같이 코드리뷰를 해봤으면 한다.

0개의 댓글