Love Every Moment

〔CS50 / C언어〕배열: 컴파일링, 디버깅, 문자열, 명령행 인자 본문

PROGRAMMING::LANGUAGE/C

〔CS50 / C언어〕배열: 컴파일링, 디버깅, 문자열, 명령행 인자

해 송 2021. 1. 20. 12:32
반응형

 

1. 컴파일링(Compiling)

 

(1) 전처리(Precompile) : 실질적인 컴파일 전에 무언가를 실행하라고 시키는 과정

#include <stdio.h> 를 소스 코드에 작성하면 stdio.h 파일의 내용을 포함한 새로운 소스 코드 파일이 생성된다

 

(2) 컴파일(Compile) : 전처리한 소스 코드를 어셈블리 코드로 변환하는 과정

컴파일이라는 용어는 넓은 의미로 소스 코드에서 오브젝트 코드로 변환하는 전체 과정을 의미하기도 하고 좁은 의미로는 전처리된 소스 코드를 어셈블리 코드로 변환하는 것을 의미한다

*** make 명령어를 통해 clang 이라는 컴파일러를 호출해서 소스코드를 오브젝트 코드로 변환할 수도 있다

 

(3) 어셈블(Assemble) : 어셈블리 코드를 오브젝트 코드로 변환하는 과정

어셈블러라는 프로그램을 통해 컴퓨터가 이해할 수 있는 0과 1로 이루어진 오브젝트 코드로 파일을 변환해준다

 

(4) 링크(Link) : 여러 개의 오브젝트 코드 파일을 실행 가능한 하나의 오브젝트 코드 파일로 합치는 과정

예를 들어 소스 코드에 #include <stdio.h>  #include <cs50>  두 개의 라이브러리를 포함시켰다면 컴파일하는 과정에서

clang hello.c     (x)                        clang hello.c  -lcs50  (o)

이런 식으로 링크해야 오브젝트 코드 파일이 하나로 통합되어 컴퓨터가 인식할 수 있게 된다

 


 

2. 디버깅(Debugging)

 

 

(1) help50 : 프로그램의 실행에 실패하는 경우에 사용하는 디버깅 프로그램

help50 make 파일명  의 형식으로 커맨드 라인을 작성하면 기존에 컴파일 시에 생겼던 오류의 원인을 해석해준다

 

(2) printf : 프로그램이 정상적으로 실행되지만 사용자의 의도와 다르게 작동하는 경우에 사용

직접 의심이 가는 변수를 출력하여 버그의 원인을 확인한다

예시의 경우 진단을 위해 printf("i is now %i: ", i)  라는 명령어를 임시로 추가하였다

i 가 0 부터 시작해서 10으로 끝나므로 #이 총 11개 출력되었다는 것을 확인할 수 있으며 이를 고치기 위해서는

(1) for 루프 안의 조건 i<=10 을 i<10 으로 바꾸거나

(2) for 루프 안의 i 최초값을 0 에서 1로 바꿀 수 있다

 

(3) debug50 : CS50 IDE 에서 활용할 수 있는 디버깅 프로그램

한 줄씩 코드를 실행해보면서 변수의 값을 확인하며 버그의 원인을 파악하는 방법이다

디버깅 프로그램 재생버튼 옆에 있는 화살표(Step Over) 버튼을 누르면 브레이크 포인트부터 한 줄씩 코드를 실행할 수 있다

cd : Change Directory / 지정된 디렉토리로 이동하는 명령어
빨간색 점으로 표시되는 브레이크 포인트를 지정하지 않으면 디버깅 프로그램을 실행할 수 없다

 

(4) check50 : CS50 IDE 에서 활용하는 디버깅 프로그램

 

(5) style50 : 문법적 오류를 발견하는 것이 아니라 심미적 관점에서 읽기 쉬운 코드를 작성하는데에 도움을 주는 프로그램 

 


 

 

3. 배열(Array)

 

 

(1) 정적 배열(Static Array)

같은 타입의 변수가 여러 개가 존재한다면 배열을 이용하여 하나의 변수로 묶어 관리할 수 있다.

위의 예시에서는 int 타입의 변수 score1, score2, score3 를 묶어 하나의 변수 scores 로 선언하였다.

int scores[3]; 라는 코드는 "int 자료형을 가지는 크기 3의 배열을 scores 라는 이름으로 생성한다"를 의미한다.

배열의 인덱스는 0부터 시작하므로 scores[0] scores[1] scores[2] 가 각각의 요소가 된다.

 

전역 변수(Global Variable) N 을 선언함으로써 점수 개수가 바뀌는 경우 코드를 수정하는 수고를 줄일 수 있다.

 

 

 

(2) 동적 배열(Dynamic Array)

 

for 루프와 함수의 선언을 통해 동적인 프로그램을 작성할 수 있다.

int n = get_int("Number of scores: ");  함수를 통해 배열의 크기(n)를 사용자로부터 입력 받는다. 

그리고 average 라는 새로운 함수를 선언하여 평균을 구한다.

이 함수는 length 와 array[], 즉 배열의 길이와 배열을 입력으로 받는다.

printf 함수에서 %f 에 플러그인된 average 함수에서는 배열의 길이: n, 배열: scores 가 된다.

새로운 함수를 선언할 때에는 int main(void) 전에 함수선언문; 을 따로 작성해주는 것을 잊지 말자!
sum += array[i];   는    sum = sum + array[i]   와 같다.
기존에 sum 과 length 를 int 라고 지정하였기 때문에 return 값이 소수점을 포함하지 않는 정수로 계산되는 오류를 방지하기 위하여 sum 또는 length 앞에 (float) 를 덧붙여준다. 

 


 

4. 문자열(String)

 

(1) 배열을 이용하여 문자열 출력하기

문자열은 문자열을 이루는 문자(Char)들의 배열과도 같다.

예를 들어, 문자열 EMMA 는 각각의 문자 E, M, M, A 로 이루어져 있다.

크기 4의 배열 names 에 네 개의 이름을 할당하고 첫 번째 이름 "EMMA" 를 출력하는 두 가지 방법은 다음과 같다.

 

(1) printf("%s\n", names[0]);  → 문자열(string) 자체를 출력

(2) printf("%c%c%c%c\n", names[0][0], names[0][1], names[0][2], names[0][3]);  →   문자(char)들을 나열하여 출력

 

(2) for 루프 이용하여 문자열 출력하기

s 라는 변수에 "EMMA" 라는 입력값을 넣으면   s[0]='E'   s[1]='M'   s[2]='M'   s[3]='A'   s[4]='\0'  가 된다.

실제로 출력되지 않지만 문자열의 종료를 의미하는 '\0' 가 나올 때까지 문자의 출력을 반복하면 "EMMA"가 된다.

이는 for 루프의 실행 조건으로 s[i] != '\0' 혹은 i < strlen(s) 을 작성함으로써 가능해진다.

다만, 컴퓨터의 처리 속도가 빠르기에 상관치 않아도 되지만 루프가 반복될 때마다 i < strlen(s) 인지 묻는 것은 비효율적이다.

따라서 n 이라는 변수를 따로 만들어 strlen(s) 값을 저장하고 i < n 을 조건으로 작성하는 방법을 사용할 수 있다. 

새로운 라이브러리 <string.h> 를 추가하여 strlen() 함수를 사용할 수 있다.
아스키 코드 \0 은 null character 라고 부르며 문자의 마지막이 어디인지를 표현해주는 기능을 한다.

 


5. 문자열의 활용

 

사용자로부터 문자열을 입력 받아 대문자로 바꾸어주는 프로그램을 작성하는 방법이다.

첫 번째 사진은 알파벳 대문자와 소문자의 ASCII 코드 상의 값이 32씩 차이나는 것을 이용한 방법이다.

두 번째 사진은 toupper() 함수를 이용하여 더욱 간단하게 소문자를 대문자로 변환하는 방법이다.

새로운 라이브러리 <ctype.h> 를 추가하여 toupper() 함수를 사용할 수 있다.
CS50 사용자를 위한 매뉴얼 사이트를 이용하여 새로운 함수와 라이브러리를 탐색할 수 있다.

 


 

6. 명령행 인자(Command Line Argument)

 

소스코드를 컴파일하면서 clang hello.c 뿐만 아니라 clang -o hello 와 같이 머신코드 파일명을 바꾸어주는 경우가 있었다.

예시에서의 -o 와 같이 추가적인 정보를 주는 것들을 명령행 인자라고 부른다.

 

언제나 습관처럼 사용하는 int main(void) 를 자세히 들여다보면 main() 역시 하나의 함수라는 것을 알 수 있다.

main() 함수 안에 변수를 지정함으로써 명령행 인자를 받는 프로그램을 설계할 수 있다.

첫 번째 변수 argc 는 arguments count, 즉 함수가 받을 입력의 개수를 의미한다.
두 번째 변수 argv[] 는 arguments vector, 즉 해당 입력이 포함되어 있는 배열을 의미한다.

 

argv[0] 는 기본적으로 프로그램의 이름으로 저장되므로 사용자가 새로운 입력을 추가한다면 그것이 argv[1]가 된다.

./command 라고만 입력했을 경우 argc==1 이므로 else 인 경우의 "Hello,world" 가 출력된다.

./command David 라고 입력하면 argc==2 가 되므로 argv[1] 에 해당하는 "David"가 포함된 "Hello, David"가 출력된다.

 

 

※ 네이버 부스트 코스 모두를 위한 컴퓨터 과학(CS50) 강의를 참고하여 작성하였습니다.

컴퓨터 코딩 프로그래밍 교육

 

반응형
Comments