Home [C++ 프로그래밍] 3강 - C++ 언어의 기초
Post
Cancel

[C++ 프로그래밍] 3강 - C++ 언어의 기초

💡해당 게시글은 방송통신대학교 이병래 교수님의 'C++ 프로그래밍' 강의를 개인 공부 목적으로 메모하였습니다.



학습 개요


  • 흐름 제어 구문, 구조체 및 클래스, 배열과 포인터, 동적 메모리 할당, 참조 등 C++ 프로그램의 기본적인 구문에 대하여 소개함
  • 클래스 선언문에 대해서 C언어의 구조체와 비교하는 수준에서 학습함
  • 포인터 및 동적 메모리 할당에 대한 내용은 이해가 쉽지 않으며, 문법적으로는 잘 이해하고 있다 해도 실제 활용 과정에서 에러를 유발하기 쉬우므로 많은 실습을 통해 깊이 있는 학습을 하는 것이 필요함



학습 목표


  • 흐름 제어 구문을 이용하여 구현하고자 하는 논리에 맞게 문장의 흐름 제어를 할 수 있음
  • 구조체와 클래스의 차이점을 설명할 수 있음
  • 배열을 이용하여 여러 개의 데이터 집합에 대해 반복적 처리를 할 수 있음
  • 메모리를 필요한 시기에 필요한 만큼 동적으로 할당하거나 반환할 수 있음
  • 동적으로 할당된 메모리 공간을 포인터를 이용하여 액세스할 수 있음
  • l-value 참조를 활용할 수 있음



주요 용어


  • 구조체
    • 여러 가지 자료형의 데이터 집합을 저장할 수 있는 새로운 자료형을 정의한 것
  • 클래스(class)
    • 객체 지향 프로그래밍에서 표현하고자 하는 대상(객체)의 데이터(속성)와 함께 그 대상이 할 수 있는 동작을 나타내는 함수(행위)들을 묶어서 선언한 것
  • 배열(array)
    • 동일한 자료형의 값을 여러 개 저장할 수 있는 연속적으로 할당된 공간을 묶어 하나의 이름을 갖는 변수로 만든 것
  • 포인터(pointer)
    • 어떠한 대상이 위치한 곳을 가리키는(주소를 저장하는) 변수
  • 동적 메모리 할당
    • 프로그램 동작 중에 기억 공간의 필요성 및 소요 량을 결정하여 필요한 공간을 할당하는 것
  • 참조(reference)
    • 프로그램에서 어떤 데이터를 간접적으로 액세스할 수 있도록 그 데이터를 가리키는 값(주소)



강의록


흐름 제어 구문

기본적인 흐름 제어 구조

  • 순차 구조
    • 문장이 나열 된 순서에 따라 차례로 실행하는 구조
  • 조건 제어 구조
    • 지정 된 조건에 따라 실행 흐름을 제어하는 구조
    • if문, switch
  • 반복 제어 구조
    • 정해진 범위의 문장을 반복적으로 실행하게 하는 구조
    • for문, while문, do while

조건문 - if

  • if문 사용 형식

    1
    2
    3
    4
    
      if (조건)
          문장1; // 조건이 참일 때 실행할 문장
      else
          문장2; // 조건이 거짓일 때 실행할 문장
    
    • ex) 변수 a와 b에 저장 된 값 중 큰 값을 출력하기

      1
      2
      3
      4
      
        if (a > b)
            cout << a << endl;
        else
            cout << b << endl;
      

조건문 - switch

  • switch문 사용 형식

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      switch (정수형_수식) {
      case 1 :
          문장1; // 정수형_수식 == 값1 일 때 실행할 문장들 나열
          break; // switch문을 빠져 나가게 함
      case 2 :
          문장2; // 정수형_수식 == 값2 일 때 실행할 문장들 나열
          break; // switch문을 빠져 나가게 함
      default: // 정수형_수식의 값과 일치하는 case 값이 없을 때
          문장n; // 실행할 문장들을 나열
      }
    
  • switch문 사용 예

    • ex) int형 변수 score의 값에 따라 A ~ F의 학점 부여하기

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        switch (score / 10) {
        case 10: // score가 100인 경우
        case 9: grade = 'A'; // score가 90~99인 경우
            break;
        case 8: grade = 'B'; // score가 80~89인 경우
            break;
        case 7: grade = 'C'; // score가 70~79인 경우
            break;
        case 6: grade = 'D'; // score가 60~69인 경우
            break;
        default: grade = 'F'; // score가 59 이하인 경우
        }
      

반복문 - for문 루프

  • for문 사용 형식

    1
    2
    
      for ( 초기화_문장 ; 반복조건 ; 증감_문장 )
          반복할_문장;
    

    image.png

    • ex) 10개의 정수 값을 입력하여 합계 구하기

      1
      2
      3
      4
      5
      6
      
        int val, total = 0;
              
        for (int i = 0 ; i < 10 ; i++) {
            cin >> val;
            total += val;
        }
      
  • 범위 기반 for루프

    1
    2
    
      for (원소선언 : 데이터집합)
          반복할_문장;
    
    • ex) 배열 안의 모든 값을 합산 하기

      1
      2
      3
      4
      5
      6
      7
      
        int arr[5] = {2, 3, 9, 4, 7};
        int sum = 0;
              
        for (int a : arr)
            sum += a;
              
        cout << "합계 = " << sum << endl;
      

반복문 - while루프

  • while문 사용 형식

    1
    2
    
      while (반복조건)
          반복할_문장;
    

    image.png

    • ex) for루프를 while루프로 표현 하기

      1
      2
      3
      4
      5
      6
      
        int val, total = 0;
              
        for (int i = 0 ; i < 10 ; i++) {
            cin >> val;
            total += val;
        }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
        int val, total = 0;
        {
            int i=0;
            while (i < 10) {
                cin >> val;
                total += val;
                i++;
            }
        }
      

반복문 - do ~ while루프

  • do ~ while문 사용 형식

    1
    2
    3
    
      do
          반복할_문장;
      while (반복조건 );
    

    image.png

구조체와 클래스

구조체

  • 구조체
    • 여러 가지 자료형 데이터 집합을 저장할 수 있는 새로운 자료형을 정의한 것
  • 구조체 선언문 형식

    1
    2
    3
    4
    
      struct StructName {
          Type1 item1;
          Type2 item2;
      };
    
  • 구조체의 예
    • 2차원 좌표

      image.png

      1
      2
      3
      
        struct C2dType {
            double x, y;
        };
      
    • image.png

      1
      2
      3
      4
      
        struct CircleType {
            C2dType center;
            double radius;
        };
      
  • 구조체 데이터를 처리하는 함수
    • C 언어에서는 구조체와는 별개의 함수로 정의함
    • ex) 원의 면적 구하기

      image.png

      1
      2
      3
      4
      
        double circleArea(CircleType c)
        {
            return c.radius * c.radius * PI;
        }
      
      1
      2
      3
      4
      
        int main() {
            CircleType c1 = { {0, 0}, 10};
            cout << " 원의 면적 : " << circleArea(c1) << endl;
        }
      

클래스

  • 클래스
    • 표현하고자 하는 대상(객체)의 데이터(속성)와 함께 그 대상이 할 수 있는 동작을 나타내는 함수(행위)들을 묶어서 선언한 것
    • ex) 원 클래스

      행위init: 원의 초기화
       area: 원의 면적을 계산
       chkOverlap: 다른 원과 중첩 여부 검사
       display: 원의 정보 디스플레이
      속성center: 중심 좌표
       radius: 반경
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      
        class CircleClass { // 원 클래스
            C2dType center; // 중심 좌표
            double radius; // 반경
              
        public:
            // 중심 (cx, cy), 반경 r로 원을 초기화
            void init(double cx, double cy, double r) {
                center.x = cx;
                center.y = cy;
                radius = r;
            }
                  
            // 원의 면적 계산
            double area() const {
                return radius * radius * PI;
            }
                  
            bool chkOverlap(const CircleClass& c) const {
                double dx = center.x - c.center.x;
                double dy = center.y - c.center.y;
                double dCntr = sqrt(dx*dx + dy*dy);
                return dCntr < radius + c.radius;
            }
                  
            void display() const {
                  
            }
        };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
        int main()
        {
            CircleClass c1, c2;
            c1.init(0, 0, 10); // 중심(0, 0), 반경 10으로 초기화
            c2.init(30, 10, 5); // 중심(30, 10), 반경 5로 초기화
                  
            cout << "원1" << endl;
            c1.display();
            cout << " 원1의 면적 : " << c1.area() << endl;
            cout << "원2" << endl;
            c2.display();
            cout << " 원2의 면적 : " << c2.area() << endl << endl;
        }
      

구조체와 클래스의 비교

image.png

배열

배열

  • 동일한 자료형의 값을 여러 개 저장할 수 있는 연속적으로 할당 된 공간을 묶어 하나의 이름을 갖는 변수로 만든 것
  • 각각의 원소는 0번부터 시작하여 차례로 부여 된 번호(첨자, 인덱스)를 이용하여 액세스 함
  • 배열의 차원
    • 배열의 첨자 개수

1차원 배열

  • 1차원 배열의 선언

    image.png

  • 1차원 배열의 사용

    1
    2
    3
    4
    5
    
      float fArray[4];
      int i = 0;
      fArray[i] = 10.0f;
      cin >> fArray[1] >> fArray[2] >> fArray[3];
      cout << fArray[1] * fArray[2];
    

다차원 배열

  • 2차원 배열
    • 1차원 배열이 원소인 배열

      1
      
        int Arr2D[4][3];
      

      image.png

배열의 활용

  • 배열의 초기화

    1
    2
    3
    4
    
      int a[5] = { 1, 2, 3, 4, 5 }; // '='는 생략할 수 있음
      int b[5] = { 1, 2, 3 }; // b[3]와 b[4]는 0으로 초기화됨
      int c[] = { 1, 2, 3, 4, 5 }; // 배열의 크기는 5임
      int d[2][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } }; // 2차원 배열의 초기화
    
  • 여러 개의 데이터 중 최댓 값 구하기

    image.png

    • MaxValue.cpp

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      
        int main()
        {
            int max;
            int data[10] = { 10, 23, 5, 9, 22, 48, 12, 10, 55, 31 };
                  
            max = data[0]; // data의 0번 값을 max로 가정함
            cout << "데이터 : " << data[0]; // 0번 데이터 출력
                  
            for (int i = 1; i < 10; i++) { // 나머지 9개의 데이터 비교
                cout << " " << data[i]; // i번 데이터 출력
                if (max < data[i]) max = data[i]; // i번 데이터 비교
            }
                  
            cout << "\n\n배열의 최댓값 : " << max << endl;
            return 0;
        }
      

포인터와 동적 메모리 할당

포인터의 활용

  • 포인터
    • 어떠한 대상이 위치한 곳을 가리키는(주소를 저장하는) 변수
      • 가리키는 대상
        • 포인터에 지정 된 자료형에 해당 되는 변수, 동적으로 할당 된 메모리, 함수 등
  • 포인터 선언 형식

    1
    
      TypeName* ptrVar;
    
    • TypeName
      • 가리킬 값의 자료형
    • ptrVar
      • 포인터 변수의 이름
    1
    
      int* iPtr;
    
  • 포인터의 사용
    • 포인터가 유효한 대상을 가리키게 한 후 사용해야 함

      1
      2
      
        ptrVar = &var; // ptrVar이 var을 가리키게 함
        *ptrVar = value; // ptrVar을 이용하여 var을 액세스
      
      • &
        • 주소 계산 연산자
      • *ptrVar
        • 포인터 ptrVar가 가리키는 곳
      1
      2
      3
      
        int a;
        int* iPtr = &a;
        *iPtr = 10;
      
  • 포인터의 사용 예
    • SimplePt.cpp

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
        #include <iostream>
        using namespace std;
              
        int main()
        {
            int a = 10;
            int* ptr;
                  
            ptr = &a; // ptr에 a의 주소를 넣는다.
            cout << "ptr이 가리키는 값 : " << *ptr << endl; // 출력되는 값 : 10
            *ptr = 20;
            cout << "변수 a의 값 : " << a << endl; // 출력되는 값 : 20
            return 0;
        }
      

      image.png

동적 메모리 할당

  • 동적 메모리 할당이란?
    • 프로그램 동작 중에 기억 공간의 필요성 및 소요 량을 결정하여 필요한 공간을 할당하는 것
      • 기억 공간의 생성 시점
        • new연산자의 실행 시점
      • 기억 공간의 소멸 시점
        • delete연산자의 실행 시점
    • 포인터 변수가 할당 된 기억 공간을 가리키게 함
  • 메모리 할당 연산자

    1
    
      ptrVar = new TypeName;
    
    1
    
      ptrVar = new TypeName[n];
    
  • 메모리 반납 연산자

    1
    
      delete ptrVar;
    
    1
    
      delete [] ptrVar;
    
  • 단일 데이터 공간의 할당 및 반환

    1
    2
    3
    
      int* intPtr;
      intPtr = new int;
      *intPtr = 10;
    

    image.png

    1
    2
    3
    4
    5
    6
    
      int* intPtr;
      intPtr = new int;
      *intPtr = 10;
        
      delete intPtr;
      intPtr = nullptr; // 아무 것도 가리키지 않는 포인터
    

    image.png

  • 배열 데이터 공간의 할당 및 반환

    1
    2
    3
    4
    5
    
      int* intPtr;
      intPtr = new int[4];
      *intPtr = 10;
      *(intPtr+1) = 20;
      intPtr[2] = 30;
    

    image.png

    1
    2
    3
    4
    5
    6
    7
    8
    
      int* intPtr;
      intPtr = new int[4];
      *intPtr = 10;
      *(intPtr+1) = 20;
      intPtr[2] = 30;
        
      delete [] intPtr;
      intPtr = nullptr;
    

    image.png

참조

l-value 참조

  • 참조(reference)
    • 어떠한 대상을 가리키는 값
      • 포인터와 유사함
    • 참조 변수는 참조 대상의 별명처럼 사용할 수 있음
    • I-value 참조
      • 실체가 있는 대상(I-value)에 대한 참조
  • l-value 참조 변수의 선언 형식

    1
    
      TypeName& refVar = varName;
    
    • TypeName
      • 참조 대상의 자료형
    • refVar
      • 참조 변수의 이름
    • varName
      • 참조 대상
  • l-value 참조 변수의 사용 예

    image.png

  • const참조
    • 참조 변수가 참조하는 대상의 값을 바꿀 수 없음

      1
      2
      3
      4
      
        int x { 10 };
        const int& xRef = x;
        cout << xRef << endl; // x의 값을 읽어 출력함
        xRef += 10; // 오류: const 참조로 값을 수정할 수 없음
      
  • 참조가 포인터와 다른 점
    • 참조 변수를 이용하여 값을 읽거나 저장할 때 참조 대상 변수를 사용하는 형식과 동일함
    • 참조 변수는 초기화를 통해 반드시 어떤 대상을 참조해야 함
      • 초기화 되지 않은 상태로 인해 무엇을 참조하고 있는지 알 수 없는 상황은 발생하지 않음
    • 참조 변수는 초기화를 통해 지정 된 참조 대상을 바꿀 수 없어 참조의 유효 기간 동안 하나의 대상만 참조할 수 있음

r-value 참조

  • r-value 참조
    • 사용한 후에는 그 값을 더 이상 가지고 있을 필요가 없는 대상을 참조
  • r-value 참조의 용도
    • 객체의 값을 다른 객체로 이동



연습 문제


  1. 위 지문에서 배열의 항목에 cin으로 부터 입력된 값을 넣으려고 한다. 공란에 넣을 내용은?

    1
    2
    3
    4
    
     int arr[10];
        
     for ( // _______ : arr)
       cin >> a;
    

    a. int& a

    • 범위 기반 for루프에서 arr의 각 원소를 나타내는 선수를 선언함
    • 이때 arr의 값을 입력을 통해 변경해야 하므로 참조형으로 선언함
  2. C++ 에서 클래스와 구조체의 차이점을 바르게 설명한 것은?

    a. 클래스의 항목들은 공개 여부를 지정하지 않은 경우 공개되지 않는 것이 기본이나, 구조체의 항목들은 공개되는 것이 기본이다.

    • 구조체는 내부 데이터 항목들을 외부에서 자유롭게 사용하도록 공개하는 것이 디폴트임
    • 클래스의 경우는 내부의 구현을 감추는 것이 디폴트임
  3. 10개의 int형 값을 저장하는 공간을 동적 할당하는 명령을 바르게 사용한 것은?

    a. int *iPtr = new int[10];

    • new 명령으로 할당 받을 자료형 이름을 쓰고 그 뒤에 [크기]의 형식으로 할당 크기를 지정함
  4. 위 지문에서 int형 포인터 iPtr의 선언이 올바르게 사용된 것은?

    a.

    1
    2
    
     int a;
     int *iPtr = &a;
    
    • 포인터는 동일한 자료형의 데이터를 가리키도록 해야 함
    • 어떠한 변수를 가리키도록 하려면 변수의 주소를 계산하는 &연산자를 사용함
  5. 다음 중 l-value 참조 ref를 선언하는 문장으로 올바른 것은? 단, a는 int형 변수이다.

    a. int& ref = a;

    • l-value 참조는 & 기호를 이용하여 선언함
    • 이때 참조 대상을 지정하여 초기화해야 함
    • l-value 참조의 대상은 l-value여야 하며, 참조 대상과 자료형이 같아야 함
    • auto& ref = 10;에서는 참조 대상이 int형 리터럴이므로 const참조로 선언해야 참조할 수 있음



정리 하기


  • if문 및 switch문을 이용하여 조건 제어 구조를 만들 수 있으며, for, while, do while문을 이용하여 반복 제어 구조를 작성할 수 있음
  • 클래스를 이용하여 표현 대상이 어떤 일을 할 수 있는가(행위)와 이를 위해 어떤 데이터를 저장하는가(속성)를 선언함
  • 배열을 이용하여 동일한 자료형의 값을 여러 개 연속적 저장 공간에 저장하고 첨자를 지정하여 개별 원소를 액세스할 수 있는 변수를 만들 수 있음
  • 포인터를 이용하여 값이 저장되어 있는 곳이나 함수를 가리키게 하여 간접적으로 액세스할 수 있음
  • new연산자를 이용하여 메모리를 동적으로 할당하여 사용할 수 있으며, delete연산자를 이용하여 사용이 끝난 메모리를 반납할 수 있음
  • 참조형 변수를 이용하여 변수 등을 참조할 수 있으며, 초기화에 의해 지정된 참조 대상을 교체할 수 없음

[C++ 프로그래밍] 2강 - C++ 언어의 기초

[C++ 프로그래밍] 4강 - 함수