최초작성일: 2023-02-04
부스트코스 <모두를 위한 컴퓨터 과학 (CS50 2019)> 강의 수강
3. 배열
1. 컴파일링
- 컴파일링의 네 단계를 설명할 수 있다.
- 컴파일링, 어셈블링, 링킹
전처리 단계(preprocessing, precompile)
- #으로 시작되는 C 소스 코드는 실질적인 컴파일이 이루어지기 전 실행할 것을 알려줌
- 참조하라고 써놓은 파일(라이브러리)을 해당 파일의 실제 파일로 대체
컴파일링(compiling)
- 소스 코드를 머신 코드로 바꾸는 단계
- 소스 코드가 어셈블리 코드로 바뀜
- 어셈블리어는 저수준 프로그래밍 언어
- 컴퓨터가 이해할 수 있는 언어와 최대한 가까운 프로그램으로
어셈블링(assembling)
- 어셈블리 코드를 0과 1로 이루어진 머신 코드(기계어, 오브젝트 코드)로 만듦
링킹(linking)
- 여러 파일을 컴파일하기 위해 우리가 명령을 여러 번 내릴 필요는 없음
- 모든 0과 1들을 하나의 큰 파일로 합침
- 여러 개의 다른 오브젝트 코드 파일을 실행 가능한 하나의 오브젝트 코드 파일로 합쳐줌
2. 디버깅
- 디버깅하는 여러 방법을 설명할 수 있다.
버그와 디버깅
버그(bug)
코드에 들어있는 오류
- 의도하지 않은 프로그램 내 실수
디버깅(debugging)
코드에 있는 버그를 식별하고 고치는 과정
- 디버거를 이용하면 프로그램을 특정 행(
중지점, breakpoint
)에서 멈출 수 있게 해주어 버그를 찾는 데 도움을 줌 - 프로그래머는 멈춰진 지점에서 무슨 일이 일어났는지 볼 수있음
- 프로그램을 한 번에 한 행씩 실행할 수 있게 해 줌
러버덕 디버깅
- 자신의 코드를 다른 이에게 설명해보면 어디가 잘못되었는지 찾게 되는 경우가 있다
3. 코드의 디자인
- 코드의 정확성과 디자인을 관리하는 방법을 설명할 수 있다.
코드 디자인의 중요성
- 코드 작성 시에는 자신과 다른 사람들이 읽기 쉽게, 유지보수하기 쉽게 작성해야
- 공백 수나 줄바꿈 등은 코드의 실행에 직접적으로 영향을 주지는 않지만 코드를 작성하는 사람들이 코드를 읽고 이해하는 데 영향을 줌
- 불필요한 오해를 없애고 코드를 이해하는 데 드는 비용을 최소화하기 위해 스타일 가이드를 준수해야
4. 배열 (1)
- 배열을 정의하고 사용하는 방법을 설명할 수 있다.
- 배열
C의 자료형
data type | memory |
---|---|
bool | 1 byte |
char | 1 byte |
int | 4 bytes |
float | 4 bytes |
long | 8 bytes |
double | 8 bytes |
string | ? bytes |
- C에서
char
자료형을 입력하려면 작은따옴표,string
자료형을 입력하려면 큰따옴표 사용
배열이 필요한 이유
- 서로 연관있는, 반복적인 데이터를 저장할 때 각 변수를 하나 하나 입력하면
- 수정이 어려움
- 보기도 어려움
- 같은 코드를 반복해서 적어야 함
- 하나 이상의 값들이 있고 서로 연관되어 있을 때 -> 배열로 저장
C의 배열
- 여러 개의 값을 가진 하나의 변수를 만들 때 배열 사용
모두 같은 자료형
의 값들이 같은 이름의 변수에 저장됨
int main(void)
{
int scores[3];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;
printf("Average: %i\n", (scores[0] + scores[1] + scores[3]) / 3)
}
- 그러나 위와 같은 코드는 여전히 점수 개수가 바뀌는 상황에서 제약이 많음
- 나중에 배열의 길이(3)와 평균을 구할 때 나누는 수(3)가 같아야 한다는 걸 모르고 바꿔버릴 수 있음
5. 배열 (2)
- 배열을 정의하고 사용하는 방법을 설명할 수 있다.
- 배열, 전역 변수
전역 변수
코드 전반에 걸쳐 바뀌지 않는 값
- 함수 바깥에서 선언하는 변수
- 코드 최상단에
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[3]) / N)
}
- 여전히 배열의 인덱스마다 점수를 지정해줘야 함
C의 배열2
- 좀 더 동적인 프로그램 작성
#include <cs50.h>
#include <stdio.h>
float average(int length, int array[]);
int main(void)
{
int n = get_int("Number of 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; // float으로 여기도록.
}
- C의 배열은 스스로의 길이를 기억하지 않음.
- 배열의 길이를 넣어줘야.
- 배열 내 원소의 순서는 바이트 수와 무관
- 컴퓨터가 각 값의 자료형에 따라 알아서 필요한 저장 공간 계산
- int를 int로 나누면 int가 나옴
- int를 float으로 나누면 float
6. 문자열과 배열
- 문자열이 C에서 정의되는 방식과 메모리에 저장되는 방식을 설명할 수 있다.
- 문자, 문자열
문자열
string
은char
의 배열- 길어지면 메모리를 많이 차지. 정해진 크기를 가질 수 없음.
- 변수명은 문자열의 시작점에 대한 정보를 알려줌
- 문자열이 언제 끝나는지 알려주는 정보도 필요 ->
널(Null) 문자(\0)(널 종단 문자)
널 문자
: 8비트가 모두 0인 상태- 3글자를 저장하기 위해 널 문자까지 4바이트를 씀.
- 문자열을 printf 함수로 출력하면 printf 함수가 문자 하나하나마다 널 문자인지 아닌지 판단해서 출력함
- '%c'를 이용해서 string을 char 하나하나로 받아 출력하면 널 문자는 나오지 않지만, 널 문자를 '%i'로 받으면 0이 출력됨.
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%i\n", names[0][0], names[0][1], names[0][2], names[0][3], names[0][4]);
// EMMA0
- 문자열 길이보다 더 가서 문자를 출력하면 메모리에 저장된 값을 들여다볼 수 있음.
7. 문자열의 활용
- 문자열을 탐색하고 일부 문자를 수정하는 코드를 구현할 수 있다.
- strlen, toupper
문자열의 길이 및 탐색
- 사용자로부터 문자열을 입력받아 한 글자씩 출력하는 프로그램
- 문자열의 끝을 어떻게 알까?
- for 루프 이용:
for (int i = 0; s[i] != ‘\0’; i++) { ..}
string.h
라이브러리의strlen()
함수 이용
- for 루프 이용:
- string.h
- 문자열 복사, 합치기, 비교, 검색 등의 함수가 있음
문자열의 탐색 및 수정
- 사용자로부터 문자열을 입력받아 대문자로 바꿔주는 프로그램
- 아스키코드 이용
ctype.h
라이브러리의toupper()
함수 이용
- ctype.h
- 아스키코드인지, 숫자인지, 문자인지 등 판단
- 소문자, 대문자 변환 등의 함수가 있음
8. 명령행 인자(command-line arguments)
make
나clang
같은 프로그램을 실행할 때 컴파일하고자 하는 코드 외에도 컴파일 후 저장하고자 하는 파일명과 같이 추가적인 정보를 함께 줄 수 있는데, 이것을명령행 인자
라고 함- 명령행 인자를 받는 프로그램을 C로 작성할 수 있다.
- 명령행 인자, argv, argc
main 함수
#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
는 함수가 받을 입력의 개수,argv[]
는 그 입력이 포함되어 있는 배열- argv[0]는 기본적으로 프로그램의 이름으로 저장됨.
argc
라고 저장 후 명령창에서./argc David
로 실행하면 "hello, David" 출력- main 함수의 반환값은 int인데 기본적으로 프로그램이 잘 실행되면 0을 반환.
'NOTES > CS50' 카테고리의 다른 글
[CS50] Chapter 6. 자료구조 (0) | 2023.03.04 |
---|---|
[CS50] Chapter 5. 메모리 (0) | 2023.02.25 |
[CS50] Chapter 4. 알고리즘 (0) | 2023.02.13 |
[CS50] Chapter 2. C언어 (1) | 2023.01.30 |
[CS50] Chapter 1. 컴퓨팅 사고 (0) | 2023.01.30 |