boostcource
모두를 위한 컴퓨터 과학 (CS50 2019) : David J. Malan
www.boostcourse.org/cs11
실습환경 : CS50 Sandbox & CS50 IDE
메모리
이전에 자료형과 하드웨어의 한계에 대해 공부하며 가볍게 언급했던 메모리에 대해 다시 알아보자.
자료형 | 메모리 크기 | |
bool | 불리언 | 1byte (8bit) |
char | 문자 | 1byte (8bit) |
int | 정수 | 4byte (32bit) |
float | 실수 | 4byte (32bit) |
long | (더 큰) 정수 | 8byte (64bit) |
double | (더 큰) 실수 | 8byte (64bit) |
string | 문자열 | ??byte |
컴퓨터 안에는 RAM(Random Access Memory)이라고 하는 물리적 저장 장치가 존재한다.
소프트웨어 구동 시에 정보가 저장되는 곳이다.
RAM은 위와 같은 칩 형태로 존재하는데
쉽게 접근하자면 칩 내부의 검은 사각형이 메모리.
메모리를 쪼개어낸 노란색 작은 사각형 하나가 1byte(8bit)를 의미한다고 볼 수 있다.
이 RAM으로 무엇을 할 수 있을까?
만일 char 타입의 변수를 하나 생성한 뒤 값을 입력하면, 작은 사각형 하나 안에 저장이 되는 것이다.
그리고 만일 int 타입이라면 4byte이기 때문에, 작은 사각형 4개를 사용하는 것이다.
이전 char(문자)를 잠시 복습해보는 시간을 가지자.
아래와 같이 c1, c2, c3에 각자 문자를 하나씩 선언해준 뒤 printf 해보자.
#include <stdio.h>
int main(void){
char c1 = 'H';
char c2 = 'I';
char c3 = '!';
printf("%c %c %c\n", c1, c2, c3);
}
// ? H I !
❕ char 선언 시에는 작은 따옴표(''), string 선언 시에는 큰 따옴표("") 를 사용한다.
공백을 가지며 %c %c %c로 출력했기 때문에 H I ! 라는 결과가 출력된다.
여기서 잠시
char는? ASCII를 이용해 숫자로 변환 가능했다. (ASCII 코드 : 문자를 숫자로 표현할 수 있도록 정해진 약속 중 하나)
위 문자들을 아스키코드로 변환하려면 아래같이 작성한다.
int main(void){
char c1 = 'H';
char c2 = 'I';
char c3 = '!';
printf("%i %i %i\n", (int)c1, (int)c2, (int)c3);
}
// ? 72 73 33
printf를 진행하면서 각 변수 앞에 (int)를 붙여 정수로 표현할 것임을 알려주고
형식 지정자 역시 int에 맞는 %i 로 변경해주면 각 문자의 아스키코드가 출력된다.
이렇게 하나의 자료형을 다른 종류의 자료형으로 바꾸는 행위를 형변환이라고 한다.
정리해보자면
c1은 'H' 이자 72, c2는 'I' 이자 73, c3는 '!' 이자 33 임을 확인했다.
그리고 사실 이들은 2진법으로 표현된다.
즉, 정말 실제로 저장된 형태는 01001000, 01001001, 00100001 과 같다는 것이다.
배열
배열(array)은 값들의 리스트를 의미한다.
모두 같은 자료형을 갖는 값들을 같은 이름의 변수 하나로 저장하는 방법이다.
대괄호([])를 사용해서 값들의 개수를 적고 세미콜론을 붙여 선언할 수 있다.
이는 컴퓨터에게 n개의 메모리를 줘! 라고 하는 것과 같다.
다음은 3개의 점수를 가지고 평균 점수를 반환하는 코드이다.
#include <stdio.h>
#include <cs50.h>
int main(void){
int score1 = 72;
int score2 = 73;
int score3 = 33;
printf("Average: %i\n", (score1 + score2 + score3) / 3);
}
// ? Average: 59
이 코드의 문제점은 최선의 디자인이 아니라는 것이다.
앞으로 코드의 수정 없이 오로지 3개의 값만 받을 것 같이 고정적이고, 복사-붙여넣기 한 듯한 모습이 아쉽다.
이럴 때 배열을 통해 개선할 수 있다.
1단계 : 배열로 선언하기
scores 라는 변수명을 이용해서 배열을 선언한다.
그리고 각각을 [0][1][2] 로 할당해서 사용한다.
int main(void){
int scores[3];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;
printf("Average: %i\n", (scores[0] + scores[1] + scores[2]) / 3);
}
// ? Average: 59
2단계 : 배열의 크기를 전역 변수로 선언하기
배열의 크기를 N으로 새로 선언해준다.
main 함수 바깥에서 선언해주면 함수 내부에서만 영향을 주는 것이 아닌 코드 전반에 영향을 준다.
그리고 const를 앞에 붙여 고정된 값(상수)로 선언할 수 있다.
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);
}
// ? Average: 59
(관례적으로 전역 변수의 이름은 대문자로 표기한다.)
3단계 : 루프와 함수를 이용해 평균값 구하기
평균값에 대한 계산을 반복문으로 진행할 수 있다.
이 과정에서 int를 float으로 형변환하여 소수점까지 계산하는 식으로 함께 변경해보자.
const int N = 3;
float average(int length, int array[]);
int main(void){
int scores[N];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;
int sum = 0;
for(int i=0; i<N; i++){
sum += scores[i];
}
printf("Average: %.1f\n", (float)sum / N);
}
// ? Average: 59.3
그리고 이 평균값 계산 단계를 함수로 분리할 수도 있다.
average 함수로 따로 선언하면 아래와 같다.
const int N = 3;
float average(int length, int array[]);
int main(void){
int scores[N];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;
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: 59.3
4단계 : 사용자로부터 점수 받기
마지막으로 cs50 라이브러리의 get_int를 이용해서
사용자로부터 입력할 점수들의 갯수(n)와 점수들(scores)을 입력받는 방식으로 개선 가능하다.
입력받을 때 역시 평균값을 계산하던 것과 같이 루프를 이용할 수 있다.
#include <stdio.h>
#include <cs50.h>
float average(int length, int array[]);
int main(void){
int n = get_int("Count: ");
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;
}
// ? Count: 4
// ? Score 1: 80
// ? Score 2: 90
// ? Score 3: 100
// ? Score 4: 85
// ? Average: 88.8
이렇게 최종적으로
임의의 점수 개수와 점수 배열을 받아 동적으로 평균값을 구하는 프로그램을 작성할 수 있다.
'CS > CS50' 카테고리의 다른 글
[CS][CS50] 배열 - 명령행 인자 (1) | 2023.06.09 |
---|---|
[CS][CS50] 배열 - 문자열과 배열 / 문자열의 활용 (0) | 2023.06.08 |
[CS][CS50] 배열 - 컴파일링 / 디버깅 / 코드의 디자인 (0) | 2023.05.26 |
[CS][CS50] C언어 - 하드웨어의 한계 (2) | 2023.05.26 |
[CS][CS50] C언어 - 사용자 정의 함수, 중첩 루프 (0) | 2023.05.24 |