C++

C++ UserDataType(구조체, 열거형, 형변환) - 24.11.18

부어잉 2024. 11. 18. 15:51
반응형

* 형변환

 - 변수나 값을 한 데이터 타입에서 다른 데이터 타입으로 변환하는 작업니다.

 

크게 두 가지의 형변환으로 분류할 수 있다.

 

1. 암시적(묵시적) 형변환

 - 컴파일러가 자동으로 자료형을 반환

 - 주로 작은 자료형이 큰 자료형으로 변환

 - 큰 자료형을 작은 자료형으로 변환은 가능하지만, 데이터 손실이 발생할 가능성이 있다.

 

int a = 1;
double b = a;	//int -> double 형태로 형변환 된다.

 

 

2. 명시적 형변환

- 사용자가 직접 형변환을 한다.

 

  • C 스타일의 명시적 형변환

-  문법적으로 간단하다. 괄호 안에 원하는 데이터 타입을 명시하여 변수나 값을 반환한다.

-  (target_type) value         target_type -> 변환하려는 데이터 타입     value -> 변환 대상 값.

- 포인터, 기본형, 사용자 정의 타입 등 거의 모든 데이터 타입에 대해 적용이 가능하다.

- C++ 형변환 방식에 비해 어떤 변환이 이루어지는지 명확하지 않을 수 있음.

- 잘못된 형변환으로 인해 런타임 오류나 데이터 손실이 발생될 수 있다.

 

double dValue = 10.3;
int iValue = (int)a;

 

 

  • C ++ 명시적 형변환

- 형변환을 더 안전하고 명확하기 하기 위해 캐스트 연산자를 제공한다.

- C 스타일 보다는 안정적으로 사용 가능하다.

 

 

 

  * C++ 캐스팅 종류

 

1. static_cast
- 컴파일 타임에 타입을 변환하는데 사용한다. 주로 기본 타입 간의 변환에 컴파일러가 변환이 가능한지
   검사하기 때문에, 잘못된 변환을 방지할 수 있다.
- UpCasting 때도 사용하기는 한다. 
- 복잡한 상속 구조에서 타입 변환이 혼동을 줄 수 있을 때, 명시적으로 붙히는게 가독성에 도움이 될 수 있다.

 

int value = 40;
double dValue = static_cast<double>(value);		
//int- > double로 명시적 형변환

 

 

 

2. dynamic_cast

 - 상속관계에서 사용한다. 런타임에 타입 변환을 수행. 주로 DownCasting 사용.
 -  안정성을 보장하여 타입이 맞지 않는다면 nullptr을 반환시킨다.
 - RTTI(RunTime Type Information)을 기반으로 작동한다.


※ RTTI (RunTime Type Information) 란?
 : 프로그램 실행 중에 실시간으로 데이터의 형식을 가져오는 매커니즘
   런타임 중,  포인터가 가리키는 객체의 타입을 알 수 있게 해준다.

 

 

3. const_cast 
: 객체의 상수성을 제거하나 추가할 때 사용한다. 
  타입 변환이 아닌, 상수성만 변환할 때 사용된다.

 


4. reinterpret_cast
: 잘 사용하지는 않는 캐스팅 종류. 매우 강력하지만 잘못 사용하게 되면 상당한 위험을 초래할 수 있음.

 

 

 

 

 

 

** 구조체

 : 여러 개의 변수를 묶어, 하나의 데이터 단위로 정의하는 사용자 정의 데이터 형식.

   구조체는 각각의 변수를 멤버로 가지고 이러한 멤버들은 서로 다른 데이터 타입일 수 있다.

   C++에서는 함수도 포함이 가능하다.

   

* 형태 

struct 구조체이름 {  여러 멤버 변수  } ;

struct Student
{
    int age;
    int phoneNumber;
    string name;
    
    void Print();	
};

 

C++ 에서는 함수도 구조체의 멤버로 참여할 수 있다.

구조체는 선언 후 데이터 형식으로 변수를 생성해 사용할 수 있다.

{ } 를 이용해, 멤버 변수를 순서대로 초기화할 수 있다.

구조체 내 멤버 변수에게 접근하기 위해서는 . 연산자를 사용하여 접근한다.

 

struct Student
{
    int age;
    int phoneNumber;
    string name;
    
    void Print();	
};

int main()
{
    Student st;
    st = { 17, 2356, "학생1" };
    
    cout<<st.name << "의 나이는 " <<st.age<<"살 입니다."<<endl;
    //결과 : 학생1의 나이는 17살 입니다.
}

 

 

§ 두 점 사이의 거리를 계산하는 함수

struct Point
{
    int x;
    int y;
};


double CalculateDistance(const Point& p1, cont Point& p2)
{
    double deltaX = p2.x - p1.x;
    double deltaY = p2.y - p1.y;
    return sqrt((deltaX*delta) + (deltaY * deltaY));
}

 * sqrt는 제공된 값에 루트를 씌워 반환한다. sqrt(9) -> 루트9 -> 3이 반환된다

 

* 열거형

 - 상수 집합에 이름을 붙여서 사용하는 데이터 타입

 - 코드의 가독성을 높일 수 있다.

 - 기본적으로  int 타입으로 처리되며, 자동으로 첫 번째 값이 0부터 시작하여 1씩 증가합니다.

 - 명시적으로 값을 지정할 수 있다.

 

열거형(enum)의 형태

enum 열거형 이름 {  } ;

enum Color
{
  	// 0,  1,  2
	Red,Green,Black
};

 

열거형 내에 멤버들에게 접근하기 위해서는 범위 지정 연산자 ( :: ) 를 사용해야 한다.

 

cout<<Color::Red<<endl;		//0

 

 

* enum  vs  enum class

 

- enum 은 서로 다른 enum 들과 멤버의 이름이 중복되어서는 안되지만,

      enum class 에서는 서로 다른 객체 사이에서도 멤버 이름이 중복될 수 있다. 

- enum 은 특정 멤버를 따로 선언 및 초기화하지 않고 사용가능하기 때문에, 오류가 발생하거나 불분명한 값을 가지게 될 수도 있다. 
       enum class는 class 라는 타입이 생겼기때문에 소속이 명확하고, 그에 따라 자신의 범위를 지정해주어야 한다.

- enum은 묵시적으로 해당 값들을 int형의 정수로 변환시켜 비교 연산이 가능하지만, enum class는 형변환을 하지 않는 이상 서로 다른 enum class 타입끼리 비교할 수 없다.

 

enum Color 
{
    Red, Green, Black
};

enum class Location
{
    lnven,
    Town,
    Shop
};


int main()
{
    Color c = Red;
    Location l = Location::Town;	//범위를 명확하게 지정해주어야 한다.
    
    if(c == 1)
    {
    	cout<<"Red 는 1이다."<<endl;	//enum은 비교가 가능하다.
    }
}

 

 

문자열 함수 (str- )

 

※ 대표적인 무자열 관련 함수들

 - strlen(const char* str) : 문자열의 길이를 반환한다.

 - strcpy(char* dest, const char* src) : 문자열 src를 dest에 복사하여 넣는다.( copy )

 - strcat(char* dest, const char* src) : src를 dest 문자열 끝에 이어 붙인다. 문자열 연결.

 - strcmp(const char* str1, const char* str2) : str1 과 str2 문자열을 비교한다.

    ㄴ 동일하면 0 반환. str1 이 str2 보다 작으면 음수, 크면 양수를 반환한다.

 

const char* str = "Hello";
char str1[10] = "abcd"

cout<<strlen(str);			//5
cout<<strlen(str1);			//4

const char* cmp1 = "aab"		//아스키코드 -> 97 97 98
const char* cmp2 = "aac"		//아스키코드 -> 97 97 99

cout<<strcmp(cmp1, cmp2);		// cmp1이 더 작기 때문에 음수(-1) 반환

char cpy1[10] = "hi,";
char cpy2[10] = "Tom.";			//복사해 넣을 배열의 크기는 복사할 내용의 배열보다 크기가 커야한다.
					//문자열 배열 끝에는 null값도 있기 때문에, null값도 고려해야한다.

strcpy_s(cpy2, cpy1);			//cpy2에 cpy1을 복사하여 넣는다.
cout<<cpy2;				//hi, 출력

char s1[10] = "Mr.M";
char s2[20] = "Hi, ";

strcat_s(s2,s1);		// s2에 s1을 이어 붙인다. 
cout<<s2<<endl;			// Hi, Mr.M

 

 

 

§ 문자열 뒤집기 함수

void ReverseStr(char str[])
{
    int len = strlen(str);
    char temp;
    
    for(int i = 0; i < len/2;i++)	//문자열의 절반까지만 반복
    {
    	temp = str[i];
        str[i] = str[len-i-1];	//문자열의 뒤쪽 부터 앞으로 넣어준다
        str[len-i-1] = temp;
    }
}

 

728x90