13. [C++] C++에서의 구조체

2024. 4. 12. 11:36[C++]/C++ 언어 기초

구조체란?

  • 연관있는 데이터를 하나로 묶으면, 프로그램 구현 및 관리를 용이하게 한다.
  • 연관있는 데이터를 묶을 수 있는 문법적 장치

 

  • 구조체의 예시) 자동차
    • 소유주
    • 연료량
    • 현재 속도
struct Car{
    char gamerID[ID_LEN];
    int fuelGauge;
    int curSpeed;
}

 


C++에서의 구조체 변수 선언

c++에서는 별도의 typedef 선언 없이도 다음과 같이 변수를 선언할 수 있다.

Car basicCar;
Car simpleCar;
Car run99={"run99", 100, 0};

 

RacingCar.cpp

#include <iostream>
using namespace std;

//구조체 Car와 관련된 정보 상수화
#define ID_LEN  20
#define MAX_SPD 200
#define FUEL_STEP   2
#define ACC_STEP    10
#define BRK_STEP    10

//구조체 Car
struct Car
{
    char gamerID[ID_LEN];	// 소유자 ID
    int fuelGauge;		// 연료량
    int curSpeed;		// 현재속도
};

//차량 정보(const로 값 변경 불가하게 만든다)
void ShowCarState(const Car &car)
{
    cout<<"소유자ID: "<<car.gamerID<<endl;
    cout<<"연료량: "<<car.fuelGauge<<"%"<<endl;
    cout<<"현재속도: "<<car.curSpeed<<"km/s"<<endl<<endl;
}

void Accel(Car &car)
{
    if(car.fuelGauge<=0)
        return;
    else
        car.fuelGauge-=FUEL_STEP;

    if(car.curSpeed+ACC_STEP>=MAX_SPD)
    {
        car.curSpeed=MAX_SPD;
        return;
    }

    car.curSpeed+=ACC_STEP;
}

void Break(Car &car)
{
	if(car.curSpeed<BRK_STEP)
	{
		car.curSpeed=0;
		return;
	}

	car.curSpeed-=BRK_STEP;
}

int main(void) {
    Car run99 = {"run99", 100, 0};
    Accel(run99);
    Accel(run99);
    ShowCarState(run99);
    Break(run99);
    ShowCarState(run99);

    Car sped77 = {"sped77", 100, 0};
    Accel(sped77);
    Break(sped77);
    ShowCarState(sped77);
    return 0;
}
소유자ID: run99
연료량: 96%
현재속도: 20km/s

소유자ID: run99
연료량: 96%
현재속도: 10km/s

소유자ID: sped77
연료량: 98%
현재속도: 0km/s
  • 위 함수들은 구조체 Car와 함께 부류를 형성해, Car와 관련된 데이터의 처리를 담당하는 함수들이다.
  • 위 함수들은 구조체 Car에 종속적인 함수라 할 수 있지만, 전역함수의 형태를 띈다. 따라서 다른 영역에서 이 함수를 호출하는 실수를 범할수도 있다.

구조체 안에 함수 삽입

  • 구조체 Car에 종속적인 함수를 구조체 안에 함께 묶는다.
  • C++에서는 구조체 안에 함수를 삽입하는 것이 가능하다.
struct Car
{
	char gamerID[ID_LEN];	// 소유자 ID
	int fuelGauge;		// 연료량
	int curSpeed;		// 현재속도

    void ShowCarState()
    {
        cout<<"소유자ID: "<<gamerID<<endl;
        cout<<"연료량: "<<fuelGauge<<"%"<<endl;
        cout<<"현재속도: "<<curSpeed<<"km/s"<<endl<<endl;
    }

    void Accel()
    {
        if(fuelGauge<=0)
            return;
        else
            fuelGauge-=FUEL_STEP;

        if(curSpeed+ACC_STEP>=MAX_SPD)
        {
            curSpeed=MAX_SPD;
            return;
        }

        curSpeed+=ACC_STEP;
    }

    void Break()
    {
        if(curSpeed<BRK_STEP)
        {
            curSpeed=0;
            return;
        }
        curSpeed-=BRK_STEP;
    }
};

 

구조체 밖과 구조체 안 함수 선언의 차이

void ShowCarState(const Car &car)
{
	cout<<"소유자ID: "<<car.gamerID<<endl;
	cout<<"연료량: "<<car.fuelGauge<<"%"<<endl;
	cout<<"현재속도: "<<car.curSpeed<<"km/s"<<endl<<endl;
}
void ShowCarState()
{
	cout<<"소유자ID: "<<gamerID<<endl;
	cout<<"연료량: "<<fuelGauge<<"%"<<endl;
	cout<<"현재속도: "<<curSpeed<<"km/s"<<endl<<endl;
}
  • 함수가 구조체 밖에 있을 때에는 'car.'을 앞에 덧붙여 직접참조를 하고 있다.
  • 함수를 구조체 안에 삽입하게 되면 구조체 내에 선언된 변수에 "직접접근"이 가능해져 'car.'을 붙힐 필요가 없어진다.

 

따라서 다음과 같이 구조체 변수를 각각 선언하면, 다음의 형태로 구조체 변수가 생성된다.

Car run99 = {"run99", 100, 0};
Car sped77 = {"sped77", 100, 0};

 

 


구조체 안에 enum 상수의 선언

#define ID_LEN  20
#define MAX_SPD 200
#define FUEL_STEP   2
#define ACC_STEP    10
#define BRK_STEP    10
  • 이 상수들은 구조체 Car에게만 사용되는 상수들이다.
  • 즉, 다른 영역에서는 사용되지 않으니 이 상수들도 구조체 내에 포함시키는 것이 좋다.
  • 따라서 이러한 경우에는 열거형 enum을 이용해 구조체 내에서만 유효한 상수를 정의하면 된다.
struct Car
{
	enum {
        ID_LEN = 20,
        MAX_SPD = 200,
        FUEL_STEP = 2,
        ACC_STEP = 10,
        BRK_STEP = 10
        };
	char gamerID[CAR_CONST::ID_LEN];	// 소유자 ID
	int fuelGauge;		// 연료량
	int curSpeed;		// 현재속도

    void ShowCarState(){ . . . . }
    void Accel(){ . . . . }
    void Break(){ . . . . }
};
  • 상수, 함수를 전부 구조체 안에 넣었더니 구조체가 너무 커진다.
namespace CAR_CONST {
    enum {
        ID_LEN = 20,
        MAX_SPD = 200,
        FUEL_STEP = 2,
        ACC_STEP = 10,
        BRK_STEP = 10
    };
}
  • 이름 공간을 통해 구조체 밖으로 빼줄 수 있다.

함수는 외부로 뺄 수 있다.

C++의 구조체를 보는 순간, 다음 정보들이 쉽게 눈에 들어와야 코드 분석이 용이하다.

  • 선언되어 있는 변수정보
  • 정의되어 있는 함수정보

 

struct Car {
    . . . . .
    void ShowCarState();
    void Accel();
    . . . . .
};

void Car::ShowCarState() {
 	. . . . .
}
void Car::Accel() {
	.
  • 이와 같이 함수의 원형은 구조체에 두고, 함수의 정의를 밖으로 뺄 수 있다.
  • 다만, 빼낸 다음 해당 함수가 어디에 정의되어 있는지 범위지정연산자(::)를 이용해 추가해줘야 한다.
#include <iostream>
using namespace std;

//상수는 namespace로 구분한다.
namespace CAR_CONST {
    enum {
        ID_LEN = 20,
        MAX_SPD = 200,
        FUEL_STEP = 2,
        ACC_STEP = 10,
        BRK_STEP = 10
    };
}

//구조체 형태
struct Car
{
    char gamerID[CAR_CONST::ID_LEN];	// 소유자 ID
    int fuelGauge;		// 연료량
    int curSpeed;		// 현재속도

    void ShowCarState();
    void Accel();
    void Break();

};

//함수 정의
void Car::ShowCarState()
{
    cout<<"소유자ID: "<<gamerID<<endl;
    cout<<"연료량: "<<fuelGauge<<"%"<<endl;
    cout<<"현재속도: "<<curSpeed<<"km/s"<<endl<<endl;
}

void Car::Accel()
{
    if(fuelGauge<=0)
        return;
    else
        fuelGauge-=CAR_CONST::FUEL_STEP;

    if(curSpeed+CAR_CONST::ACC_STEP>=CAR_CONST::MAX_SPD)
    {
        curSpeed=CAR_CONST::MAX_SPD;
        return;
    }
    
    curSpeed+=CAR_CONST::ACC_STEP;
}

void Car::Break()
{
    if(curSpeed<CAR_CONST::BRK_STEP)
    {
        curSpeed=0;
        return;
    }

    curSpeed-=CAR_CONST::BRK_STEP;
}

int main(void) {
    Car run99 = {"run99", 100, 0};
    run99.Accel();
    run99.Accel();
    run99.ShowCarState();
    run99.Break();
    run99.ShowCarState();

    Car sped77 = {"sped77", 100, 0};
    sped77.Accel();
    sped77.Break();
    sped77.ShowCarState();
    return 0;
}
소유자ID: run99
연료량: 96%
현재속도: 20km/s

소유자ID: run99
연료량: 96%
현재속도: 10km/s

소유자ID: sped77
연료량: 98%
현재속도: 0km/s

 


문제

2차원 평면상에서의 좌표를 표현할 수 있는 구조체를 다음과 같이 정의하였다

struct Point

{

        int xpos;

        int ypos;

};

위의 구조체를 기반으로 다음의 함수를 정의하고자 한다(자세한 기능은 실행의 예를 통해서 확인)

void MovePos(int x, int y); //점의 좌표이동

void AddPoint(const Point &pos); //점의 좌표증가

void ShowPosition(); //현재 x, y 좌표정보 출력

 

int main(void)

{

        Point pos1={12, 4};

        Point pos2={20, 30};

 

        pos1.MovePos(-7, 10);

        pos1.ShowPosition(); //[5, 14] 출력

 

        pos1.AddPoint(pos2);

        pos1.ShowPosition(); //[25, 44] 출력

        return 0;

}

 

내 풀이

#include "stdafx.h"
#include <iostream>
#include <cstring>

using namespace System;
using namespace std;

struct Point{
	int xpos;
	int ypos;

	void MovePos(int x, int y){
		xpos += x;
		ypos += y;
	};
	void AddPoint(const Point &pos){
		xpos += pos.xpos;
		ypos += pos.ypos;
	};
	void ShowPosition(){
		cout<<"["<<xpos<<","<<ypos<<"]"<<endl;
	};

};

int main (void)
{
	Point pos1 = {12, 4};
	Point pos2 = {20, 30};

	pos1.MovePos(-7, 10);
	pos1.ShowPosition();

	pos1.AddPoint(pos2);
	pos1.ShowPosition();
	return 0;
}

반응형