다음 장부터 본격적으로 C 문법 공부를 시작하게 될 것이다. 그 전에 C문법의 기본적인 특징과 구조에 대해 미리 숙지하도록 하자. 이미 다 알고 있는 내용인지 모르겠지만 본격적인 실습에 들어가기 전에 C의 특징에 대해 간략하게 정리해 보았다.

① C언어는 대소문자를 구분하므로 키워드나 명칭 등을 작성할 때 대소문자 구분에 유의해야 한다. 변수를 선언할 때는 Score로 선언해 놓고 쓸 때는 score로 쓰면 이 변수는 선언되지 않은 것으로 취급된다. 또한 main을 Main으로 써도 안되며 예약어들도 대소문자에 맞게 써야 한다. INT num; 이라고 쓰면 안된다. C의 예약어들은 모두 소문자이고 변수나 함수명도 대부분 소문자로 작성하므로 가급적이면 소문자만 쓰는 것이 좋다. 책의 소스를 직접 입력할 때도 소스에 적힌대로 정확하게 입력해야 한다.

② C 프로그램은 항상 main 함수로 시작한다. C는 함수 위주의 언어이며 필요한 함수를 자유롭게 만들어 쓸 수 있는데 함수 중에 반드시 있어야 하는 함수가 바로 main 함수이다. main은 프로그램의 시작점이 되며 이름이 고정되어 있다. 컴파일러는 main에서부터 실행을 시작한다.

③ 모든 문장은 세미콜론으로 끝이 나는데 세미콜론은 자연어의 마침표에 해당한다. 컴파일러는 세미콜론을 기준으로 어디서 어디까지가 한 문장인지를 구분하므로 모든 명령 끝에 반드시 세미콜론을 달아 주도록 하자.

④ C언어는 프리포맷(Free Format)을 지원한다. 문법에만 맞으면 한줄에 붙여 쓸 수도 있고 여러 줄에 나누어 쓸 수도 있다. 조금 여백을 주기 위해 괜히 한 줄을 비워 둘 수도 있으며 들여쓰기나 공백의 개수도 편한대로 작성할 수 있다. First 예제를 다음과 같이 수정해도 제대로 컴파일된다.

#include <stdio.h>

void main() {printf("korea\n");}

단 두 줄에 다 붙여 써도 상관없다. 또는 다음과 같이 한 명령을 여러 줄에 나누어 써도 전혀 상관없다.

#include <stdio.h>

void

main() {

              printf(

          "korea\n")

          ;}

물론 이렇게 소스를 작성하면 별로 보기에 좋지 않으므로 가급적이면 구조를 한눈에 파악할 수 있도록 빈줄과 공백을 적당히 끼워 넣고 들여 쓰기를 하는 것이 좋다. C 언어가 소스의 형식에 별 제한을 두지 않기 때문에 소스는 개성에 따라 자유롭게 작성할 수 있다. 이에 비해 베이직같은 언어는 프리포맷을 지원하지 않기 때문에 다소 불편하다.

⑤ C 프로그램의 구조는 대체로(절대적이지는 않다) 다음과 같다.

#include <...>

#define ...

함수의 원형

전역변수

void main()

{

     코드

}

함수

함수

함수

프로그램 선두에 #include, #define 같은 전처리문이 오고 이어서 함수 원형, 전역변수 선언이 온다. 그리고 프로그램의 본체인 main 함수와 그 외 필요한 함수들이 이어진다. 물론 꼭 이 구조대로 작성해야 한다는 강제가 있는 것은 아니지만 대부분의 C 소스는 이런 구조로 되어 있다.

Posted by 테티스
,

사람이 쓰는 자연어에는 명사, 동사, 형용사 같은 품사가 있다. 각 품사별로 고유한 특징이 있고 품사별로 올 수 있는 위치나 단어를 조합하는 방법이 달라진다. 예를 들어 명사, 대명사는 주어가 될 수 있고 형용사, 부사는 다른 품사를 수식한다. 이런 품사들의 위치나 자격에 대한 규칙이 바로 문법이며 문법에 의해 어디가 왜 틀렸는지 알 수 있고 어떻게 수정해야 하는지도 알게 된다. 다음 예를 보면 문법에 의해 언어에 질서가 부여되고 언어가 간단 명료해짐을 알 수 있다.

아가야 씩씩한 자라다오 : '씩씩한'의 품사는 형용사이며 주로 명사를 수식한다. 동사를 수식하는 것은 부사이므로 '씩씩하게'라고 고쳐야 옳다.

씩씩하게 군인들이 싸운다 : 명사를 수식하는 것은 형용사이므로 '씩씩한'이라고 해야 한다. 또는 수식어와 피수식어는 최대한 인접해야 하므로 '군인들이 씩씩하게 싸운다'로 수정할 수도 있다.

프로그래밍 언어도 자연어와 마찬가지로 품사를 나눌 수 있다. 각 언어마다 품사를 나누는 방법이 다르듯이 프로그래밍 언어들도 각각 다른 품사 구성을 가진다. C언어는 일곱 개의 구성 요소로 나누어지는데 각각의 구성 요소들은 모두 고유한 특징을 가지고 있다. 언어를 구성하는 이 일곱 개의 요소를 잘 구분해야 문법을 체계적으로 학습할 수 있으며 그래서 구성 요소를 파악하는 것이 C언어 공부의 시작이다. C언어 문법의 가장 기초가 되는 부분이므로 일단 외워 두는 것이 좋다.

키워드(Keyword)

C언어 자체가 의미를 미리 정해 놓은 단어들이며 예약어(Reserved word)라고도 한다. C언어가 이미 사용하고 있는 단어들이므로 다른 목적으로 사용할 수 없다. 즉, 키워드와 똑같은 이름의 변수나 함수를 만들 수 없다. 만약 키워드와 같은 이름의 변수를 사용하면 컴파일러는 이것을 변수로 인식하지 않고 키워드로 인식하므로 변수의 역할을 할 수 없을 것이다.

C언어의 키워드에는 다음과 같은 것들이 있는데 보다시피 그렇게 수가 많지는 않다. C는 함수 위주의 언어이기 때문에 대부분의 기능을 함수로 정의하고 있으며 따라서 다른 고급언어에 비해서는 키워드가 아주 적은 편이다.

auto, case, cdecl, const, char, continue, default, do, double, else, enum,

extern, float, for, goto, if, int, long, register, return, short, signed,

sizeof, static, struct, switch, typedef, union, unsigned, void, volatile,

while

각 키워드의 의미에 대해서는 차차로 배우게 될 것이다. 다음은 C++ 언어에서 새로 추가된 키워드들인데 주로 클래스와 관련된 것들이다.

asm, class, delete, friend, inline, mutable, new, operator, private,

protected, public, template, this, virtual, explicit, ....

이 외에도 각 컴파일러별로 추가로 제공하는 키워드들이 몇 가지 더 있는데 사용 빈도가 높지 않거나 예제 수준에서는 사용할 경우가 거의 없으므로 표준 키워드 목록 정도만 알아 두면 된다. 14882 표준 문서에는 총 63개의 키워드가 정의되어 있다.

명칭(Identifier)

명칭은 사용자가 직접 만들어서 사용하는 것이다. 변수나 함수같은 것들은 다른 것들과 구분(Identify)되어야 하므로 자기만의 고유한 이름을 가져야 한다. 만약 두 변수가 같은 이름을 가진다면 컴파일러가 이 변수들을 구분하지 못하는 애매함이 생기므로 제대로 컴파일되지 않을 것이다. 디렉토리의 파일들이 고유의 이름을 가져야 하는 것처럼 모든 명칭은 고유한 이름을 가져야 한다.

명칭은 사용자가 직접 정의하는 것이므로 이름을 자유롭게 붙일 수 있다. 입력하기 편리하도록 적당한 길이의 명칭을 작성하는 것이 좋고 최대한 의미를 기억하기 쉽도록 만드는 것이 좋다. 예를 들어 점수를 기억하는 변수라면 Score, 합을 계산하는 함수라면 GetTotal 등과 같이 이름을 붙이면 된다.

그러나 사용자가 이름을 붙인다고 해서 아무렇게나 명칭을 작성할 수 있는 것은 아니다. 하드 디스크의 파일명도 사용자가 마음대로 붙이는 것이지만 콜론이나 따옴표, 역슬레쉬 등 예약된 기호는 쓸 수 없다. 탐색기로 직접 테스트해 보면 Report:C.txt 따위의 이름은 거부된다. 이와 마찬가지로 명칭 작성에 대해서도 몇 가지 간단한 규칙이 있다. 중요한 규칙이기는 하지만 상식적인 수준에서 쉽게 이해가 가는 규칙들이다.

키워드는 쓸 수 없다. 키워드는 언어 자체가 이미 사용하고 있는 단어이기 때문에 명칭으로 사용해서는 안된다. int, if, while 같은 단어는 그 의미가 미리 정해져 있다.

알파벳, 숫자, 밑줄기호(_)로 구성된다. 그 외의 콜론, 따옴표, 괄호 같은 기호는 명칭으로 쓸 수 없다. 한글도 알파벳이 아니므로 명칭으로는 사용할 수 없다. 명칭 중간에 공백이 와서도 안된다.

첫 문자는 알파벳이나 밑줄기호만 올 수 있다. 숫자는 명칭의 중간에는 올 수 있지만 처음에는 오지 못한다. Num1, Inch2Cm은 적합한 명칭이지만 3D, 4you 같은 명칭은 숫자가 앞에 있으므로 적합한 명칭이 아니다.

C언어는 대소문자를 구분한다. 따라서 Score, score, SCORE는 철자는 같지만 모두 다른 명칭으로 인식된다. 명칭의 대소문자 구성은 가급적이면 일관되게 작성하는 것이 좋다. 예를 들어 모두 소문자로 작성하거나 아니면 첫 문자만 대문자로 쓰는 것이 좋다.

이 외에 For, Switch처럼 키워드와 대소문자 구성만 다른 명칭은 문법적으로는 가능하지만 결코 바람직하지 않다. 규칙이 그다지 까다롭지 않기 때문에 일반적인 영어 단어들은 대부분 명칭으로 사용할 수 있다. 다음은 명칭의 예인데 잘못된 명칭을 찾아 보자.

Korea, Score2, My Score, z, c:\, kkk, Total_Student, _line

Korea는 예약어가 아니므로 적합한 명칭이다. Score2도 숫자가 첫 부분에 있지 않으므로 역시 적합한 명칭이다. 그러나 My Score는 중간에 공백이 들어갔으므로 명칭으로 쓸 수 없다. 두 개의 단어로 명칭을 만들고 싶을 때는 MyScore처럼 두 단어를 붙여 쓰거나 아니면 밑줄기호를 사용하여 My_Score로 쓰는 것이 일반적이다.

z는 비록 한 글자로 되어 있지만 이것도 적합한 명칭이다. 명칭의 길이에 대해서는 특별한 제한이 없으므로 한 글자로 쓸 수도 있고 아주 길게 쓸 수도 있다. 그러나 너무 길면 입력하기 불편하며 또 너무 짧으면 의미를 기억하기 어려우므로 적당한 길이의 이름을 붙이는 것이 좋다. a, b, kkk 같은 명칭은 가능하기는 하지만 별로 바람직하지는 않다. c:\는 명칭에 쓸 수 없는 콜론, 역슬레쉬 등의 기호가 중간에 들어 있으므로 명칭으로 사용할 수 없다. Total_Student나 _line은 둘 다 명칭으로 사용 가능하다.

명칭이란 쉽게 말해서 변수나 함수 등에 원하는 이름을 붙이는 것이다. 이렇게 작성한 명칭으로 변수, 함수, 레이블, 타입 등을 만드는데 각각에 대해서는 관련장에서 하나씩 배우게 될 것이다. 여기서는 명칭 작성 규칙에 대해서만 알아 두도록 하자.

상수(Constant)

변수의 반대되는 개념이며 고정된 값을 가지는 식이다. 5, 638, 1.414 이런 것들이 상수이다. 5는 언제까지나 5일 뿐 그 값이 변하지 않으므로 분명히 상수이다. 숫자 상수외에 문자 상수, 문자열 상수도 있다. 문자 상수는 홑따옴표로 감싸 'A', '8' 등과 같이 표현하고 문자열 상수는 "Korea"와 같이 겹 따옴표로 감싼다.

연산자(Operator)

계산을 지시하는 기호들을 연산자라고 한다. 실생활에서 많이 사용하는 +, -, *, / 같은 사칙 연산자들도 있고 이외에 관계, 대입, 논리 연산자 등 다양한 연산자가 있다. 또한 C 언어만의 고유한 포인터 연산자, 삼항 연산자 등 나름대로 복잡한 연산자들도 많이 있는데 연산자에 대해서는 5장에서 따로 상세하게 배울 것이다.

구두점(Punctuator)

자연어에는 마침표, 쉼표, 물음표, 느낌표같은 것들이 있어서 단어들을 구분하고 뜻을 좀 더 분명히 전달하는 역할을 한다. C언어도 마찬가지로 구성 요소를 구분하여 좀 더 분명한 의미를 가지도록 하는 구두점이 있다. 쉼표, 따옴표, 괄호, 세미콜론 등이 구두점으로 사용된다.

공백 문자(White Space)

스페이스와 탭, 개행 코드 등이 공백이다. 공백 문자는 눈에 보이지 않지만 구성 요소들을 구분하는 아주 중요한 역할을 한다. int num;이라는 선언에서 int라는 키워드와 명칭 num이 공백에 의해 분리되어 있다. 만약 공백이 없다면 intnum;이 되어 버리므로 컴파일러는 어디까지가 키워드이고 어디서부터 명칭인지를 구분하지 못할 것이다. 주석도 일종의 공백으로 인정된다.

주석(Comment)

설명을 위해 삽입되는 문자열이다. 컴파일러는 주석을 완전히 무시하므로 프로그램 실행에는 아무런 영향을 주지 않는다. 주석은 소스를 읽는 사람이 의미를 쉽게 파악할 수 있도록 설명을 붙여 놓는 것이다. 좀 어려운 부분이거나 추가 작업이 필요한 부분 등에 대해서는 주석으로 간단한 설명을 달아 놓을 수 있다.

주석은 /*로 시작해서 */로 끝나거나 한줄내에서만 주석을 쓰고 싶을 때는 //를 사용한다. 구형 C 컴파일러는 /* */만 주석으로 인정하지만 최신 컴파일러들은 모두 //도 주석으로 인정한다. 주석은 어디까지나 문자열일 뿐이므로 한글이나 기호 등도 자유롭게 사용할 수 있다. 다음이 주석의 예이다.

/* 별표를 사용하여 삼각형을 출력하는 놀라운 예제

만든 사람 : 김 상형 */

#include <stdio.h>

void main()

{

     int i,j;

 

     for (i=1;i<=15;i++) {

          for (j=0;j<i;j++) {

              printf("*");               // 별표 하나를 출력한다.

          }

          printf("\n");                // 한줄이 끝나면 개행한다.

     }

}

주석은 또한 설명을 달아 놓는 용도 외에도 코드를 임시적으로 삭제할 때도 사용한다. 잠시만 코드를 없애 보고 싶다면 이 부분을 지우는 대신 주석으로 묶어 두면 된다. 컴파일러는 주석을 무시하므로 주석으로 묶어 놓은 부분은 없는 코드와 마찬가지가 되며 실제로 지운 것은 아니므로 이 코드가 다시 필요할 때 주석을 풀기만 하면 된다.

이상으로 C언어를 구성하는 일곱 개의 구성 요소에 대해 알아보았다. 모든 C 코드는 이 일곱 개의 구성 요소들로 이루어진다.

사용자 삽입 이미지
자연어의 품사마다 특성이 있듯이 C언어를 구성하는 요소들도 고유한 특성들을 가지고 있다. 그래서 구성 요소를 빨리 파악하면 소스의 구조를 좀 더 쉽게 볼 수 있으며 복잡한 구문도 정확하게 해석할 수 있다. 반면 구성 요소를 잘못 파악하면 코드를 엉뚱하게 해석할 위험이 있는데 특히 연산자와 구두점을 잘 구분해야 한다. 위 코드의 = 은 연산자처럼 보이지만 구두점이다.

Posted by 테티스
,

이번에는 텍스트 모드에서 실행되는 아주 간단한 게임을 만들어보자. 단순히 출력만 하는 것이 아니라 사용자와 상호작용을 한다는 점에서 앞의 예제들과는 조금 다르다. RandNum이라는 이름으로 프로젝트를 만들고 다음 소스를 입력한다. 좀 길기는 하지만 타이핑 연습하는 셈치고 직접 입력해 보기 바란다.

: Triangle

#include <Turboc.h>

void main()
{
    int num;
    int input;


    randomize();
    for (;;) {
         num=random(100)+1;
         printf("\n제가 만든 숫자를 맞춰보세요.\n");
         do {
             printf("숫자를 입력하세요(끝낼 떄는 999) : ");
             scanf("%d",&input);
             if (input==999) {
                   exit(0);
             }
             if (input==num) {
                  printf("맞췄습니다.\n");
             } else if (input>num) {
                  printf("입력한 숫자보다 더 작습니다.\n");
             } else {
                  printf("입력한 숫자보다 더 큽니다.\n");
              }
         } while (input!=num);
    }
}

난수 생성문과 사용자로부터 입력 코드, 이중 루프 등의 기법을 사용했기 때문에 뭔가 더 복잡해 보인다. 난수 함수를 사용하므로 표준 헤더 파일인 stdio.h 대신 이 책을 위해 별도로 작성해 놓은 Turboc.h를 포함시켰다. 만약 Turboc.h 헤더 파일을 찾을 수 없다는 에러가 발생하면 1장에서 설명한 실습 준비를 안한 것이다. Turboc.h 파일을 반드시 개발툴의 Include 디렉토리에 복사해 놓도록 하자.

앞으로 예제들은 Turboc.h 헤더 파일을 사용할 것이다. 왜 표준도 아닌 이런 이상한 헤더 파일을 써야 하는지는 6장에 가서나 설명이 가능하므로 당분간은 그냥 실습을 위해 필요한 파일이겠거니 생각해 주기 바란다. 실행해보자.

제가 만든 숫자를 맞춰보세요.
숫자를 입력하세요(끝낼 떄는 999) : 50
입력한 숫자보다 더 큽니다.
숫자를 입력하세요(끝낼 때는 999) : 70
입력한 숫자보다 더 작습니다.
숫자를 입력하세요(끝낼 때는 999) : 60
입력한 숫자보다 더 작습니다.
숫자를 입력하세요(끝낼 때는 999) : 55
입력한 숫자보다 더 작습니다.
숫자를 입력하세요(끝낼 때는 999) : 53
입력한 숫자보다 더 큽니다.
숫자를 입력하세요(끝낼 때는 999) : 54
맞췄습니다.

제가 만든 숫자를 맞춰보세요.
숫자를 입력하세요(끝낼 때는 999) :

컴퓨터가 임의의 난수 하나를 생성하고 사용자로 하여금 그 수를 맞추도록 한다. 커서가 깜박거리면 여기에 1~100까지의 수 중 하나를 입력한다. 컴퓨터는 자신이 만든 숫자가 입력된 수보다 큰지, 작은지를 힌트로 알려 주는데 이 힌트를 참고하여 최소 회수만에 숨겨진 숫자를 찾아내는 것이 이 게임의 목적이다.

게임 규칙도 간단하고 그래픽이 나오는 것도 아니어서 아주 재미없다고 생각되겠지만 화려한 대형 게임들도 이런 작은 프로그램을 확장해서 만들어지는 것이다. 비록 겉모습은 초라하지만 그래도 초보자에게는 쉬운 예제가 아니므로 시시하다고 생각하지 말자. 이 예제들 외에도 뒷부분에 인쓴 좀 더 긴 예제들도 입력해서 실행해 보도록 하자. 몇 번만 더 연습해 보면 개발툴에 금방 익숙해질 수 있다. 다음 절부터 C언어의 문법에 대해 본격적으로 연구해본다.

참고

소스를 빨리, 정확하게 입력할 수 있는 능력도 개발자에게는 무척 중요한 능력이다. 머리속에 떠오로는 코드를 신속하게 입력할 수 있어야 원활한 개발이 가능한데 몸이 안따라 주면 좋은 아이디어를 놓쳐 버리기 십상이다. 머리는 빌 게이츠인데 손가락은 독수리라면 어떻게 되겠는가? 공부가 잘 안되는 날에는 영타 연습을 틈틈히 미리 해두도록 하고 이 책의 예제들도 가급적이면 직접 입력해보는 것이 좋다.
Posted by 테티스
,