3. 배열

eunheelog·2023년 6월 7일
0

boostcourse

목록 보기
5/13

boostcourse - 배열

1) 컴파일링

  • 컴파일의 전체 과정은 네 단계로 나누어볼 수 있다.
    전처리(Precompile) : 전처리기에 의해 수행되는 단계
    (#으로 시작되는 코드를 전처리기에게 실질적인 컴파일 전에 실행하라고 알려줌)
    컴파일(Compile) : 전처리한 소스 코드를 어셈블리 코드로 변환시키는 단계
    (어셈블리어라는 저수준 프로그래밍 언어로 컴파일)
    어셈블(Assemble) : 어셈블리 코드를 오브젝트 코드로 변환시키는 단계
    (어셈블러라는 프로그램으로 연속된 0과 1들로 바꿔줌)
    링크(Link) : 여러 개의 파일을 하나의 오브젝트 파일로 합쳐주는 단계

→ 이 네 단계를 거쳐 실행 가능한 파일이 완성된다.

2) 디버깅

  • 버그와 디버깅
    - 버그(bug) : 코드에 들어있는 오류
    → 프로그램 실행에 실패하거나 원하는대로 동작하지 않음.
    - 디버깅(dubugging) : 코드에 있는 버그를 식별하고 고치는 과정
    (디버거라는 프로그램을 사용하여 디버깅)

3) 코드의 디자인

  • check50 프로그램 → 자동으로 검사
  • style50 프로그램 → 코드가 심미적으로 잘 작성됐는지 검사

4) 배열(1)

  • 메모리
    - bool : 불리언, 1바이트
    - char : 문자, 1바이트
    - int : 정수, 4바이트
    - float : 실수, 4바이트
    - long : (더 큰) 정수, 8바이트
    - double : (더 큰) 실수, 8바이트
    - string : 문자열, ?바이트

  • 컴퓨터 안에는 아래 사진의 RAM이 메모리 역할을 한다.

  • 쉽게 여러 개의 노란 사각형이 메모리, 작은 사각형 하나가 1바이트를 의미한다.

  • 배열
    - 같은 자료형의 데이터를 메모리상에 연이어서 저장하고 하나의 변수로 관리하기 위해 사용
    - int scores[3]; → int 자료형을 가지는 크기 3의 배열을 score라는 이름으로 생성 !

5) 배열(2)

  • 전역변수
    - const를 붙이면 코드 전반에 거쳐 바뀌지 않는 값으로 지정할 수 있다.
    - 관례적으로 전역 변수의 이름은 대문자로 표기한다.

    SourceCode

    #include <cs50.h>
    #include <stdio.h>
    
    const int N = 3;
    
    int main(void)
    {
        // 점수 배열 선언 및 값 저장
        int scores[N];
        scores[0] = 72;
        scores[1] = 73;
        scores[2] = 33;
    
        // 평균 점수 출력
        printf("Average: %i\n", (scores[0] + scores[1] + scores[2]) / N);
    }

    → 배열의 인덱스마다 점수를 지정해줘야해서 불편함.

  • 배열의 동적 선언 및 저장

    SourceCode

    #include <cs50.h>
    #include <stdio.h>
    
    float average(int length, int array[]);
    
    int main(void)
    {
        // 사용자로부터 점수의 갯수 입력
        int n = get_int("Scores:  ");
    
        // 점수 배열 선언 및 사용자로부터 값 입력
        int scores[n];
        for (int i = 0; i < n; i++)
        {
            scores[i] = get_int("Score %i: ", i + 1);
        }
    
        // 평균 출력
        printf("Average: %.1f\n", average(n, scores));
    }
    
    //평균을 계산하는 함수
    float average(int length, int array[])
    {
        int sum = 0;
        for (int i = 0; i < length; i++)
        {
            sum += array[i];
        }
        return (float) sum / (float) length;
    }

    → 배열의 크기를 입력 받아 배열의 크기 만큼 반복하며 해당하는 값을 동적으로 입력 받아 저장 !

6) 문자열과 배열

  • 문자열(string) 자료형 데이터는 문자(char) 자료형 데이터들의 배열이다.
    - string s = "Hi!"로 정의했다면, s는 문자의 배열이기 때문에 아래 그림과 같이 메모리상에 저장되고 인덱스로 각 문자에 접근 할 수 있다 !

    - 여기서 가장 끝의 '\n'은 문자열의 끝을 나타내는 널 종단 문자이다.

    SourceCode
    (여러 문자열이 선언된 경우)

    string names[4];
    
    names[0] = "EMMA";
    names[1] = "RODRIGO";
    names[2] = "BRIAN";
    names[3] = "DAVID";
    
    printf("%s\n", names[0]);
    printf("%c%c%c%c\n", names[0][0], names[0][1], names[0][2], names[0][3]);

    - names라는 문자열 형식의 배열에 네 개의 이름이 저장
    - 첫 번째 printf는 첫번째 인덱스 값 즉, "EMMA"를 출력
    - 두 번째 printf는 형식 지정자가 %s가 아닌 %c로 문자열이 아닌 문자이다.
    → names[0][1]은 names의 첫 번째 값 즉, "EMMA"라는 문자열에서 두 번째 값 'M'이라는 문자를 의미한다.
    - 아래 그림을 통해 메모리상에 저장되는 예시와 해당되는 인덱스를 확인할 수 있다.

7) 문자열의 활용

  • 문자열의 길이 및 탐색
    - 문자열의 끝을 알 수 있는 방법
    → 해당하는 인덱스의 문자가 널 종단 문자('\n')와 일치하는지 검사 !
    - strlen() 함수 사용

    SourceCode
    (문자열을 입력받아 한 글자씩 출력)

    #include <cs50.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        string s = get_string("Input: ");
        printf("Output:\n");
        for (int i = 0, n = strlen(s); i < n; i++)
        {
            printf("%c\n", s[i]);
        }
    }

    - strlen은 문자열의 길이를 알려주는 함수 (string.h 안에 포함)
    → 하나씩 널 종단 문자를 검사하는 것보다 효율적 !

  • 문자열 탐색 및 수정

    SourceCode
    (문자열을 입력받아 대문자로 바꾸기)

    #include <cs50.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        string s = get_string("Before: ");
        printf("After:  ");
        for (int i = 0, n = strlen(s); i < n; i++)
        {
            if (s[i] >= 'a' && s[i] <= 'z')
            {
                printf("%c", s[i] - 32);
            }
            else
            {
                printf("%c", s[i]);
            }
        }
        printf("\n");
    }

    - 각 문자가 'a'보다 크고 'z'보다 작은지 검사(소문자인지 검사하는 것과 동일)
    → 문자의 대소비교가 가능한 이유는 ASCII 코드 상에서의 숫자값으로 비교할 수 있기 때문
    ∴ 소문자일 경우 32를 뺀 후 '문자'로 출력 !

    ↓toupper함수로 대문자 변환

    #include <cs50.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        string s = get_string("Before: ");
        printf("After:  ");
        for (int i = 0, n = strlen(s); i < n; i++)
        {
            printf("%c", toupper(s[i]));
        }
        printf("\n");
    }

8) 명령행 인자

SourceCode

#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[]는 입력이 포함되어 있는 배열(string)
  • argv[0]는 기본적으로 프로그램의 이름으로 저장
  • 위 프로그램을 “arg.c”으로 저장하고 컴파일 한 후 “./argc”로 실행해보면 “hello, world”라는 값이 출력된다.
    → 명령행 인자 값이 프로그램 이름 하나밖에 없기 때문
  • “./argc David”로 실행해보면 “hello, David”라는 값이 출력된다.
    → 명령행 인자에 David라는 값이 추가로 입력하였기 때문
profile
⛧1일 1알고리즘⛧

0개의 댓글