Notice
Recent Posts
Recent Comments
Link
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Development Log

[CS50] 배열 - 배열, 문자열, 명령행 인자 본문

성장 여행기/CS50

[CS50] 배열 - 배열, 문자열, 명령행 인자

gu-su 2022. 3. 27. 06:18

C언어 자료형 

  • 각각의 자료형은 서로 다른 크기의 메모리를 차지한다.
bool 1byte
char 1byte
int  4byte
float 4byte
long 8byte
double 8byte

 

메모리 생각해보기!

컴퓨터 메모리 내부를 이해하기 위해 아래의 모눈을 메모리를 아주 확대했다고 생각하자. (각 칸 1byte)
자료형마다 차지하는 메모리의 크기는 다르다. 컴퓨터가 각 값의 자료형에 따라 알아서 필요한 저장 공간을 계산한다.
2진법으로 저장된다. 즉, 실제는 비트로 저장된다.

메모리의 형태를 비유한 그림일 뿐, 실제 RAM에는 상하좌우의 개념이 없다!

 

 

코드1 : int (4byte)

int score1 = 72;
int score2 = 73;
int score3 = 33;

=> int는 4byte로, 4 칸을 차지하는 형태로 나타난다. 

 

 

코드2 : char (1byte)

char c[3];
char[0] = 'H'; // 72
char[1] = 'I'; // 73
char[2] = '!'; // 33

=> char는 1byte로, 실제로 해당 위치에는 72 73 33을 2진법으로 표현한 것 저장된다.

 

 

코드3 : 문자열

string s = "HI!";

 

=> 크기가 정해진 자료형의 경우와 달리 문자열의 경우에는 \0를 통해 문자열의 종점을 알린다.

=> \0문자열의 끝을 나타내는 널 종단 문자이다. (단순히 모든 비트가 0인 1byte를 의미한다.)

=> 즉, 문자열은 포함된 문자(char) 개수 만큼의 메모리를 차지하지 않는다. (더 큰 메모리를 차지한다!)

 

배열

  • 같은 자료형의 데이터메모리상에 연이어서 저장하고 이를 하나의 변수로 관리하기 위해 사용된다. 
int score1 = 72;
int score2 = 73;
int score3 = 33;

printf("Average: %i\n", (score1 + score2 + score3) / 3);

▼ 같은 자료형의 데이터를 하나의 변수로 관리할 수 있다.

int scores[3];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;

printf("Average: %i\n", (scores[0] + scores[1] + scores[2]) / 3);

▼ 크기를 전역변수로 선언해 점수 개수가 바뀌었을 때 수정해야할 부분이 줄어든다.

const int N = 3; // main 밖에 전역 변수 선언

int scores[N];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;

printf("Average: %i\n", (scores[0] + scores[1] + scores[2]) / N);
위의 코드를 볼 때 여전히 일일이 배열의 인덱스마다 점수를 지정해줘야하는 불편함이 있다.
반복문과 함수를 선언하여 좀 더 동적인 프로그램을 작성할 수 있다.

 

배열 동적으로 선언하고 저장하기 

#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; // 평균을 소수점으로 표시하기 위해서는 하나라도 실수형으로 형변환을 해줘야한다.
}
배열의 크기를 사용자에게 직접 받고, 배열의 크기만큼 반복문을 돌면서 각 인데스에 해당하는 값을 사용자에게 동적으로 입력받아 저장한다. 평균을 계산하는 함수를 따로 선언하여 평균을 구한다.
이와 같은 방법으로 임의의 점수 개수와 점수 배열에 대해서 동적으로 평균값을 구하는 프로그램을 작성할 수 있다. 

 

 

명령행 인자

#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]는 기본적으로 프로그램의 이름으로 저장된다.

$ ./argc David

=> 파일이름과 David 총 2개의 입력이 들어왔기 때문에 if문의 조건이 성립된다.

=> 즉, “hello, David"가 출력된다. 

 

think about

1) 실생활의 어떤 데이터를 배열로 표현할 수 있을까요?

더보기

학생들 성적, 제품 종류 및 재고량 등

 

2) 점수의 평균을 구하는 예제에서, 동적으로 작성한 코드는 그렇지 않은 코드에 비해 어떤 장단점이 있을까요?

더보기

과목의 수가 바뀌거나 점수가 바뀌는 등의 여러가지 상황이 발생했을 때, 직접 코드를 수정할 필요가 없어진다. 상황따라 유연성있게 동작해 활용성이 좋다.

단, 코드의 내용이 복잡해지며 로직을 제대로 구성해야한다.

 

3) 널 종단 문자는 왜 필요할까요?

더보기

문자열은 다른 자료형과 달리 크기가 정해져있는 것이 아니기 때문에 문자열의 종료지점이 언제인지 알기위해서는 널 종단 문자가 필요하다. (간단히 말하자면 문자열의 길이제한은 컴퓨터가 가진 메모리의 용량이다.)

 

4) 명령행 인자는 프로그램의 확장성에 어떤 도움이 될까요? 

더보기

프로그램을 실행시킬 때 받은 입력값에 따라 프로그램의 동작방식을 지정할 수 있다.

프로그래머에게 매번 물어보는 것이 아닌 지정된 명령어를 입력함으로써 원하는 방향으로 프로그램을 더 손쉽게 구현할 수 있다. 

 

David J. Malan의 강의

 

모두를 위한 컴퓨터 과학 (CS50 2019)

부스트코스 무료 강의

www.boostcourse.org