들어가기 전에
우리가 특정 자료형의 변수를 선언하면 이는 메모리상 어딘가에 특정 크기만큼의 자리를 차지하게 됩니다. 만약 비슷한 종류의 값을 모아서 저장하고 싶다면 어떻게 해야 할까요? 메모리상에서 여러 값을 연이어서 저장하고 사용하는 방법과 그 이점을 알아보겠습니다.
학습 목표
배열을 정의하고 사용하는 방법을 설명할 수 있습니다.
핵심 단어
- 배열
- 전역 변수
강의 듣기
들어가기 전에
우리가 특정 자료형의 변수를 선언하면 이는 메모리상 어딘가에 특정 크기만큼의 자리를 차지하게 됩니다. 만약 비슷한 종류의 값을 모아서 저장하고 싶다면 어떻게 해야 할까요? 메모리상에서 여러 값을 연이어서 저장하고 사용하는 방법과 그 이점을 알아보겠습니다.
학습 목표
배열을 정의하고 사용하는 방법을 설명할 수 있습니다.
핵심 단어
강의 듣기
전역 변수
이전 강의에 이어서, 아래 코드에서 scores 배열의 크기를 정해주는 N이라는 변수를 새로 선언하였습니다.
만약 N이 고정된 값(상수)이라면 그 값을 선언할 때 const를 앞에 붙여서 전역 변수, 즉 코드 전반에 거쳐 바뀌지 않는 값임을 지정해줄 수 있습니다.
관례적으로 이런 전역 변수의 이름은 대문자로 표기 합니다.
#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);
}
scores의 크기로 전역 변수를 선언하였기 때문에 점수 개수가 바뀌었을때 수정해야 하는 코드가 조금 줄었습니다.
하지만 여전히 일일이 배열의 인덱스마다 점수를 지정해줘야 하는 불편함이 있습니다.
배열의 동적 선언 및 저장
아래 코드에서와 같이 루프와 함수를 선언하여 좀 더 동적인 프로그램을 작성할 수 있습니다.
#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;
}
여기서는 배열의 크기를 사용자에게 직접 입력 받고, 배열의 크기만큼 루프를 돌면서 각 인덱스에 해당하는 값을 역시 사용자에게 동적으로 입력 받아 저장합니다.
그리고 average 라는 함수를 따로 선언하여 평균을 구합니다.
average 함수는 length 와 array[], 즉 배열의 길이와 배열을 입력으로 받습니다. 함수 안에서는 배열의 길이만큼 루프를 돌면서 값의 합을 구하고 최종적으로 평균값을 반환합니다.
이와 같은 방법을 통해서 임의의 점수 개수와 점수 배열에 대해서 동적으로 평균값을 구하는 프로그램을 작성할 수 있습니다.
생각해보기
점수의 평균을 구하는 예제에서, 동적으로 작성한 코드는 그렇지 않은 코드에 비해 어떤 장단점이 있을까요?
comment
동적으로 작성한 코드를 사용할 경우 시험의 개수와 시험 점수를 유동적으로 입력받아,
정적으로 작성한 코드를 사용할 때보다 활용도가 높아진다.
정적으로 작성한 코드는 현재 상황이 코드의 동작과 알맞는 경우와,
같은 값을 반복적으로 사용해야 하는 경우에는 동적으로 작성한 코드보다 더 편하게 사용할 수 있을 것이라 생각한다.
시험 갯수가 늘어났을때 추가할 수 있다는 장점이 있다.
변수 값을 바꾸고싶을 때 모든 코드의 값을 바꿔야하는 불편함이 해소된다.
유연함
정적인 코드에 비해서 낭비되는 메모리가 줄어든다. 유연한 메모리 사용
데이터 또는 데이터의 수가 변하더라도 코드를 수정하지 않고 유연하게 프로그래밍을 할 수 있다
점수의 개수가 변하더라도 코드를 수정하지 않고 편하게 평균을 구할 수 있습니다.
다만, 동적으로 작성한 코드를 작성하기가 더 어렵습니다.
점수의 가짓수가 여러개일때 동적으로 처리해야 유연하게 프로그래밍 할 수 있습니다.
버그가 덜 나게 되구요. 잘못입력했을 때 프로그램이 에러가 나는 가능성을 상당히 줄여줍니다. 효율적이라고 할 수 있습니다.
한사람의 점수만 평균을 구하는 것이 아니라 여러사람의 점수를 입력해서 평균을 구할 수 있습니다.
점수와 과목수가 변화는 상황에서, 정적인 코드는 상황이 변할때마다 변경을 해줘야하는 단점이 있습니다.
그래서 동적인 코드는 이와 같은 상황에서 유리합니다.
하지만 매번 값을 입력해줘야하는 불편함이 있을 수 있습니다.
장점 : 인원수와 점수가 상시 바뀌는 상황에서 코드 수정없이 바로 사용할 수 있으므로 범용성이 높아진다.
단점 : 특정 데이터의 결과값을 반복적으로 사용해야하는 특별한 경우 데이터를 사용시 마다 입력해야하는 번거로움이 있다.
/ / cs50 IDE를 사용하지 않으면, cs50.h 를 이용할 수 없음
// 없이 작성하면 어떤 코드가 나오느냐........
#include <stdio.h>
float average(int Length, int array[]);
int main()
{
// 사용자로부터 과목 갯수 입력받기
int scoreArray;
printf("과목은 총 몇 과목입니까? : ");
scanf_s("%i", &scoreArray);
// 과목별 점수를 사용자로부터 입력받기
int scores[scoreArray];
// 반복하며, scoreArray 만큼 받아오기
for (int i = 0; i < scoreArray; i++) {
int score[i];
printf("%i번째 과목의 점수를 입력하십시오. : ", i + 1);
scanf_s("%i", &scores[i]);
}
// 평균값 출력
printf("당신의 평균 점수는 : %.1f점 입니다.
", average(scoreArray, 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 <stdlib.h>를 추가하여 malloc(), free() 함수를 써야하는 등 코드가 더 복잡해질 수 있다.
장점: 값을 유동적으로 변환시킬 수 있어 효율적이다
단점: 코드가 길어지고 처음에 구현할 때 시간이 걸린다
장점
사용자와 더욱 능동적인 관계를 맺는다
단점
코드의 길이가 길어져서 가독성이 비교적 떨어진다
장점: 과목의 수와 점수의 값을 유동적으로 입력받을 수 있으므로 매번 코드를 수정하지 않아도 됨
단점: 정적인 코드에 비해 구현에 시간이 걸릴 수 있음