코딩/C와 C++

[C++ 기초 강좌] 1. C++ 프로그램의 구조

드리프트 2021. 3. 6. 21:18
728x170

 

 

C++로 작성되는 프로그램은 한 개 이상의 함수로 구성된다. 한 번쯤은 우리는 단순히 main() 함수로만 구성되는 샘플을 보았다. 여기서 main은 함수의 이름이다. 그 프로그램은 콘솔(console) 프로그램이었다. 콘솔 환경에 있는 모든 C++ 프로그램은 main()이라는 함수를 포함하고 있으며, 모든 C++ 프로그램은 몇 가지의 함수로 이루어진다. 함수라는 것은 단순히 특유의 이름을 가진 독립적인 코드의 집합으로서 그 함수의 이름을 통하여 실행된다.

 

전형적인 콘솔 프로그램은 다음과 같은 구조를 가진다.

위의 그림은 프로그램의 실행이 main() 함수로부터 시작되고 있음을 나타내고 있다. main()으로부터 프로그램의 실행은 input_names() 함수로 이어지며, 이 함수는 즉각적으로 프로그램의 실행을 자기가 main() 안에서 호출되었던 장소 바로 그다음으로 전달한다. 그러면 sort_names()라는 함수가 main()으로부터 호출된다. 그리고 일단 프로그램 제어가 main()에게로 넘어가면 마지막 함수인 output_names()가 호출된다. 드디어 출력이 완성되면 프로그램 실행은 다시 main()에게로 간다. 그리고 프로그램은 종료된다.

 

물론, 콘솔 환경에서의 다른 프로그램은 이와는 전혀 다른 함수 구조를 가진다. 그러나 그것들도 모두 main() 함수에서 실행이 시작된다. 프로그램을 이렇게 여러 개의 함수로 나눌 때의 이점은 여러분이  각각의 단편들을 개별적으로 작성하고 실험해 볼 수 있다는 것이다. 또 다른 이점도 있다. 즉, 어떤 특정한 작업을 수행하도록 작성된 함수는 다른 프로그램 안에서 재활용될 수 있다는 것이다. C++와 함께 오는 라이브러리는 여러분의 프로그램 안에서 사용될 수 있는 많은 종류의 표준 함수들을 제공한다. 그러한 함수는 여러분이 많은 작업을 해야 하는 수고를 덜어준다.

 

C++ 예제

// EX1.cpp
// 프로그램의 간단한 샘플
#include <iostream>

using namespace std;

int main()
{
    int apples, oranges;
    int fruit;

    apples = 5; oranges = 6;
    fruit = apples + oranges;

    cout << endl;
    cout << "Oranges are not the only fruit... " << endl
        << "- and we have " << fruit << " fruits in all.";
    cout << endl;

    return 0;
}

 

프로그램 주석

코드에 있는 처음의 두 줄은 주석이다. 주석은 모든 프로그램에 있어서 중요한 부분이다. 그러나 주석은 실행 코드가 아니다. 주석은 읽는 사람의 편의를 위해 존재한다. 모든 주석은 컴파일러에 의해 무시된다. 코드의 모든 줄에서 텍스트 문자열 안에 포함되지 않은 두 개의 연속적인 슬래시는 그 뒤의 줄이 주석이라는 사실을 나타낸다.

 

여러분은 프로그램의 몇몇 줄이 프로그램 문장뿐만 아니라, 주석도 포함하고 있다는 것을 보게 될 것이다. 또한, /*과 */로 묶이는 다른 형식의 주석을 사용할 수 있다. 예를 들어, 프로그램의 첫 번째 줄은 다음과 같이 작성될 수도 있다.

/* EX1.cpp */

//를 사용하는 주석은 단지 두 개의 연속적인 슬래시 다음에 나타나는 줄만을 포함한다. 반면에, /*..*/ 형식은 그 안에 묶여 있는 것을 모두 주석으로서 정의한다. 그리고 여러 줄에 걸쳐 표시될 수도 있다. 예를 들어, 다음과 같이 작성할 수 있다.

/*
	EX1.cpp
   	간단한 프로그램 샘플
*/

위의 네 줄은 모두 주석이다. 만약 여러분이 어떤 특정한 주석 줄을 강조시키고 싶다면 여러분은 설명을 나타내는 프레임을 사용하여 그 줄을 장식할 수 있다.

/***********************
* EX1.cpp              *
***********************/

하나의 규칙으로서 프로그램을 이해하기 쉽도록 여러분은 항상 주석을 써야 한다. 주석은 다른 프로그래머 또는 여러분이 나중에 코드의 특정 부분의 목적과 그것이 어떻게 작동하는지를 충분히 이해할 수 있도록 자세하게 써야 한다.

 

 

#include 명령 - 헤더 파일

주석 다음에 우리는 #include 명령을 다룬다.

#include <iostream>

위의 코드는 컴파일 작업을 하기 전에 컴파일러로 하여금 iostream이라는 파일의 내용을 프로그램 안에 삽입하도록 한다. 이 파일은 헤더 파일로 불리는데, 그것은  이 파일이 보통 프로그램 파일의 맨 위에 삽입되기 때문이다. 이러한 특정한 헤더 파일은 여러분이 C++에서 입력과 출력 문장을 사용하는 데 필요한 정의를 포함하고 있다. 만약 우리가 iostream을 프로그램 안에 포함시키지 않으면 컴파일을 할 수 없다. 왜냐하면, 우리는 이 파일 안에 있는 몇 가지의 정의를 기반으로 하여 출력 문장을 사용하기 때문이다. 다양한 기능을 제공하는 많은 종류의 헤더 파일이 최신 C++에서 제공된다. 우리가 언어의 기능을 알아보는 과정에서 그러한 헤더 파일들을 다룰 것이다.

 

#include 문장은 몇 가지의 전처리기(preprocessor) 명령 중의 하나이다. 최신 C++ 편집기는 그러한 명령을 인식하여 여러분의 편집 윈도에 파란색으로 표시한다. 전처리기 명령은 컴파일러에 의해서 실행되는 명령으로, 일반적으로 여러분의 소스 코드가 컴파일되기 전에 소스 코드에 어떠한 방식으로 작용하게 된다. 그 명령들은 모두 # 문자로 시작한다. 우리가 필요한 경우에는 다른 종류의 전처리기 명령에 대해서도 알아볼 것이다.

 

 

using 명령 - 네임 공간

표준 라이브러리는 많은 종류의 공통적인 작업을 수행하기 위해서 작성된 상당한 분량의 루틴의 집합이다. 예를 들어, 입력과 출력을 다루고, 기본적인 산술 연산을 처리하는 등등. 그러한 루틴의 개수가 매우 많기 때문에 여러분이 우연히 그 라이브러리 루틴 이름과 동일한 이름을 여러분만의 목적으로 사용할 확률이 높다. 네임 공간은 C++ 안에 있는 메커니즘으로서 프로그램에서 중복된 이름을 사용할 때 발생할 수 있는 문제를 해결한다. 네임 공간 안에 나타나는 코드 안에서 사용되는 모든 이름들은 그것들과 연관된 네임 공간 이름을 가진다. 모든 표준 라이브러리 루틴들은 std라는 네임 공간 이름 안에 포함된다. 그러므로 그 네임 공간 안에 있는 모든 루틴은 자기만의 이름과 네임 공간 이름을 가진다. 그렇기 때문에 iostream에 대한 #include 명령 다음에 다음과 같은 줄을 포함시켜야 한다.

using namespace std;

이것은 using 명령으로서 우리가 네임 공간 이름(다시 말해서, 표준 라이브러리의 이름)을 지정하지 않고, std 네임 공간으로부터의 이름을 사용할 것이라는 사실을 컴파일러에게 알린다. 그러면 컴파일러는 프로그램 안에 있는 표준 라이브러리의 이름을 찾는다. 그러므로 표준 라이브러리에 있는 루틴과의 접속이 이루어지는 것이다. 네임 공간에 대해서는 다음에 자세히 살펴본다.

 

 

main() 함수

위의 샘플에 있는 main() 함수는 그것을 main()으로서 정의하는 헤더 함수와 첫 번째 중괄호({)와 그에 해당하는 마지막 중괄호(}) 사이의 모든 것으로 구성되어 있다. 중괄호는 함수 안에 있는 실행 코드를 감싼다. 둘러싸이는 그 부분을 함수의 본문(body)이라고 부른다.

 

우리가 보게 되겠지만, 모든 함수는 (그중에서도 특히) 함수 이름을 정의하는 헤더와 중괄호로 묶인 많은 프로그램 문장으로 구성되어 있는 함수의 본문으로 구성된다. 함수의 본문은 전혀 문장을 포함하지 않을 수도 있다. 그러한 경우에 함수는 어떠한 작업도 하지 않는다.

 

아무것도 하지 않는 함수는 약간 불필요한 것으로 보일 수도 있다. 그러나 여러분이 커다란 프로그램을 작성할 때 여러분은 완벽한 프로그램 구조를 짜야한다. 그러나 처음에는 코드의 많은 부분을 비어 있는 본문으로 놔두게 된다. 이렇게 한다는 것은 자기의 모든 함수를 가지고 있는 전체 프로그램을 여러분이 어느 때이든 컴파일하여 실행시킬 수 있으며, 또한 각 함수에 대한 자세한 코드를 단계적으로 추가할 수도 있다는 것을 의미한다.

 

 

프로그램 문장

main() 함수의 본문을 구성하는 프로그램 문장은 각각 세미콜론으로 끝난다. 프로그램 문장은 프로그램이 하는 것을 정의하는 데 있어서 기본적인 단위가 된다. 이것은 문단에 포함되어 있는 문장과 약간 비슷하다. 이때 각각의 문장은 하나의 동작 또는 생각을 자기 스스로 표현하고 있다. 이때 각각의 문장은 하나의 동작 또는 생각을 자기 스스로 표현하고 있다. 그러나 좀 더 일반적인 생각을 나타내는 경우엔 문단 안에 있는 다른 문장과 연관되고 결합된다. 하나의 문장은 컴퓨터가 수행하는 작업에 대한 독립적인 정의이다. 그러나 그것은 좀 더 복잡한 행동 또는 계산을 정의하기 위해서 다른 문장과 결합될 수 있다.

 

함수의 행동은 항상 많은 문장으로 표현된다. 그 각각의 문장은 세미콜론으로 끝난다. 우리가 방금 작성했던 샘플 안에 있는 각각의 문장이 어떻게 작동하는지에 대한 감을 잡기 위해서 그 문장들을 간단하게 살펴본다. 문장의 각 형식에 대해서는 나중에 이 장에서 자세하게 살펴볼 것이다.

 

프로그램 안에 있는 첫 번째 문장

int apples, oranges;
int fruit;

는 apples와 oranges라는 두 개의 변수를 선언한다. 변수라는 것은 이름이 붙어있는 컴퓨터 메모리의 비트로서 여러분이 데이터를 저장하는 데 사용할 수 있는 것이다. 변수의 이름을 소개하는 문장을 변수 선언문이라고 한다. int라는 키워드는 그 변수가 정수 값을 저장한다는 것을 나타낸다. 다음 문장은 다른 정수 변수인 fruit를 선언한다. apples와 oranges에서처럼 동일한 하나의 문장에서 여러 개의 변수를 선언할 수 있지만, 일반적으로 변수들을 개별적으로 선언하는 것이 좋다. 그렇게 하면 여러분이 각각의 변수에 대해 개별적인 주석을 붙일 수 있다.

 

샘플에서 다음과 같은 줄

apples = 5; oranges = 6;

은 두 개의 문장을 포함하고 있는데, 각 문장은 세미콜론으로 끝나고 있다. 필 수 사항은 아니지만, 하나의 줄에는 하나의 문장만을 쓰는 것이 좋은 프로그래밍 습관이다. 두 개의 문장은 apples와 oranges 변수에 대해 각각 5와 6을 저장하고 있다. 이러한 문장을 할당 문이라고 한다. 왜냐하면, 그 문장은 변수에게 새로운 값을 할당하고 있기 때문이다.

다음 문장

fruit = apples + oranges;

도 역시 할당 문이다. 이 문장은 apples와 oranges 안에 저장되어 있는 값을 더하여 그 결과를 fruit 변수에 저장한다.

 

다음의 세 개의 문장은

cout << endl;
    cout << "Oranges are not the only fruit... " << endl
        << "- and we have " << fruit << " fruits in all.";
    cout << endl;

모드 출력문이다. 첫 번째 문장은 endl이라는 단어로 표시되는 개행 문자(newline character)를 화면에 보내고 있다. C++에서 입력 소스나 출력이 되는 목적지를 스트림(stream)이라고 한다. cout라는 단어는 "표준" 출력 스트림을 나타내고, << 연산자는 그 연산자의 오른쪽에 나타나는 것을 출력 스트림인 cout에게 전달한다. 연산자는 데이터가 흐르는 방향(즉, 오른쪽에 있는 변수나 문자열로부터 왼쪽에 있는 출력 목표 쪽으로)을 가리킨다.

 

cout 단어와 << 연산자의 의미는 여러분이 프로그램의 맨 위에 있는 #include 명령에서 프로그램 소스에 추가했던 iostream이라는 헤더 파일 안의 내용에 의해서 정의된다. cout는 표준 라이브러리 안에 있는 이름이다. 그러므로 그것은 std 네임 공간 안에 있다. using 명령을 사용하지 않으면 그것은 인식되지 않을 것이다. cout라는 이름은 여러분의 디스플레이 화면을 나타내며, 이것이 출력에 대한 표준 장소가 된다. cout는 이러한 목적으로 정의되었기 때문에 여러분은 cout를 다른 목적으로 사용해서는 안된다. 예를 들어, 여러분 프로그램 안에서 변수로 사용해서는 안된다.

 

두 번째 문장은 텍스트 문자열(인용 부호 사이에서 정의된)을 화면에 전달한다. 그 뒤에는 또 다른 개행 문자(endl)가 따라붙는다. 그런 다음에 다른 텍스트 문자열이 오고, 그 뒤에 fruit 변수 안에 저장된 값이 출력된다. 마지막으로, 또 다른 텍스트 문자열이 출력된다. 여러분이 출력하고자 하는 것을 이러한 방법으로 순서대로 연달아 지정해도 괜찮다. 이 문안은 왼쪽으로부터 오른쪽으로 실행되면서 각 항목이 차례로 cout에게로 전달된다. 이때 각 항목 앞에는 그것만의 << 연산자가 붙는다는 것을 명심하라.

 

세 번째 문장은 다른 개행 문자를 화면에 전달한다. 이러한 모든 문장들은 여러분이 보게 되는 프로그램으로부터 출력을 생성한다. 두 번째 문장은 두 줄에 걸쳐 있다. 연속되는 줄은 문장의 끝임을 알리는 세미콜론을 컴파일러가 찾을 때까지 하나의 문장으로 인식된다. 이것은 여러분이 문장에서 세미콜론을 사용하는 것을 잊으면 컴파일러는 그다음 줄도 동일한 하나의 문장으로 인식하여 그것들을 하나로 엮는다는 것을 의미한다. 보통, 이것의 결과는 컴파일러가 이해할 수 없는 것이 되므로 에러가 발생한다.

 

프로그램의 마지막 문장

return 0;

은 프로그램의 실행을 중단시키며, 제어를 운영체제에게 넘긴다. 우리는 이러한 모든 문장에 대해서 나중에 자세히 살펴볼 것이다.

 

프로그램 안에 있는 문장은 프로그램의 자연적인 실행 순서를 특별히 중단시키는 문장이 없는 한 그것들이 작성되어 있는 순서에 따라서 실행된다.

 

 

공간(whitespace)

공간이라는 용어는 C++에서 빈칸, 탭, 개행 문자, 그리고 주석을 표현하는 데 사용된다. 여백은 문장의 한 부분을 다른 것과 구별한다. 그렇게 함으로써, 컴파일러가 문장 안에 있는 int와 같은 하나의 요소가 어디서 끝나고 그다음 요소가 어디서 시작되는지를 구별할 수 있도록 한다. 그러므로 다음과 같은 문장

int fruit;                   // 정수 fruit를 선언

은 int와 fruit 사이에 적어도 하나의 공간 문자(보통은 빈칸)를 가져야 컴파일러가 그 둘을 구별할 수 있는 것이다. 반면에, 다음과 같은 문장

fruit = apples + oranges;

은 fruit와 = 사이에, 또는 =과 apples 사이에 공간 문자가 필요하지 않다. 그러나 여러분이 원할 때는 공간 문자를 써도 상관없다. 그 이유는, =은 문자 또는 숫자가 아니기 때문에 컴파일러가 그것을 다른 것과 구별할 수 있기 때문이다. 그와 비슷하게 + 기호 앞, 뒤에도 공간 문자가 필요 없다.

 

공간 문자가 문장 안에 있는 혼동될 여지가 있는 요소들을 구별하는 분리자의 역할을 하는 것 외에, 공간 문자는 컴파일러에 의해서 무시된다(물론, 인용 기호 사이에 있는 문자열은 제외하고). 그러므로 우리가 아까의 마지막 샘플에서 출력 문장을 몇 줄에 걸쳐서 확장시켰던 것처럼 여러분은 프로그램을 더욱 읽기 쉽도록 하기 위해서 필요한 만큼의 공간 문자를 넣을 수 있다. 다른 프로그래밍 언어에서는 문장의 마지막이 줄의 마지막에 위치하지만, C++에서의 문장의 마지막은 세미콜론이 나타나는 곳이 된다.

 

변수 이름은 하나의 단어로 구성되어야 하기 때문에 여러분은 변수 이름 안에 공간을 넣어서는 안 된다. 만약 그렇게 한다면 컴파일러는 변수 이름을 인식하지 못하여 그 프로그램은 올바르게 해석되지 않을 것이다.

 

 

문장 블록

우리는 몇 개의 문장을 한 쌍의 중괄호로 묶을 수 있다. 그러한 경우, 그 문장들은 블록 또는 복합 문장(compound statement)이 된다. 함수의 본문은 블록의 한 예이다. 그러한 복합 문장을 하나의 문장으로 생각할 수 있다. 사실, 여러분이 하나의 문장을 C++ 안에 입력할 수 있다는 것은 중괄호 사이에 문장 블록을 넣을 수 있다는 것과 동일하다. 그 결과로써 블록은 다른 블록 안에 위치할 수 있다. 사실, 블록은 다른 블록 안에 몇 겹이고 중첩될 수 있다.

 

그리드형