programming/C

C // 구조체와 사용자 정의 자료형 1

깨래 2017. 12. 29. 14:47

구조체 ?


구조체는 하나 이상의 변수를 묶어서 새로운 자료형을 정의하는 도구, 즉 구조체를 기반으로 우리는 새로운 자료형을 정의할 수 있다.


int xpos;    // 마우스의 x 좌표

int ypos;    // 마우스의 y 좌표


위의 문장들은 마우스의 위치 정보를 표현하기 때문에, 언제든 항상 함께해야한다. 그래서 이 둘을 묶어버리는 방법이 있는데 그것이 구조체이다.


struct point        // point라는 이름의 구조체 정의

{

int xpos;    // point 구조체를 구성하는 멤버 xpos

int ypos;    // point 구조체를 구성하는 멤버 ypos

};


위의 코드가 구조체를 정의하는 코드인데 point라는 이름이 int나 double과 같은 자료형의 이름이 되는 것이다. 이는 기본 자료형이 아닌 사용자가 정의하여 만든 ' 사용자 정의 자료형 ' 이다.


ex) 사람의 이름과 나이와 전화번호


struct person                       // person이라는 이름의 구조체 정의

{

char name[20];            // 이름 저장을 위한 멤버

char phoneNum[20];   // 전화번호 저장을 위한 멤버

int age;                        // 나이 저장을 위한 멤버

};


구조체 변수의 선언방법


struct point pos;    // 구조체 변수선언의 기본 형태


struct person man;     // 구조체 변수선언의 기본 형태


맨 앞에 struct 선언을 추가해야 하고, 이어서 구조체의 이름과 구조체 변수의 이름을 선언해야 한다.


위처럼 구조체 변수가 선언되면, 이 둘은 각각 다음의 형태로 존재한다.



구조체에 존재하는 멤버에 접근하는 방법


구조체 변수의 이름 . 구조체 멤버의 이름 


pos.xpos = 20;


구조체 변수의 멤버에 접근할 때에는 . 연산자를 사용한다.


ex) 두 점 사이의 거리 계산

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
29
#include<stdio.h>
#include<math.h>
 
struct point
{
    int xpos;
    int ypos;
};
 
int main()
{
    struct point pos1, pos2;
    double distance;
    
    fputs("point1 pos: ",stdout);
    scanf("%d %d",&pos1.xpos, &pos1.ypos);
    
    fputs("point2 pos: ",stdout);
    scanf("%d %d",&pos2.xpos, &pos2.ypos);
    
    /* 두 점간의 거리 계산 공식 */
    distance = sqrt((double)((pos1.xpos - pos2.xpos) * (pos1.xpos - pos1.xpos) + 
            (pos1.ypos - pos2.ypos) * (pos1.ypos - pos2.ypos)));
    
    printf("두 점의 거리는 %g 입니다. \n",distance);
    
    return 0;
}
 

cs

출력결과

point1 pos: 1 3

point2 pos: 4 5

점의 거리는 3.60555 입니다.


ex) person구조체

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
29
30
31
32
#include<stdio.h>
#include<string.h>
 
struct person
{
    char name[20];
    char phoneNum[20];
    int age;
};
 
int main()
{
    struct person man1, man2;
    strcpy(man1.name, "김태현");
    strcpy(man1.phoneNum, "010-1234-1234");
    man1.age = 26;
    
    printf("이름 입력: "); scanf("%s", man2.name);
    printf("번호 입력: "); scanf("%s", man2.phoneNum);
    printf("나이 입력: "); scanf("%d"&man2.age);
    
    printf("이름: %s \n", man1.name);
    printf("번호: %s \n", man1.phoneNum);
    printf("나이: %d \n", man1.age);
    
    printf("이름: %s \n", man2.name);
    printf("번호: %s \n", man2.phoneNum);
    printf("나이: %d \n", man2.age);
    
    return 0;
}
 

cs

 출력결과

이름 입력: gorapaduk

번호 입력: 0107942-5295

나이 입력: 23

이름: 김태현 

번호: 010-1234-1234 

나이: 26 

이름: gorapaduk 

번호: 0107942-5295 

나이: 23 


14,15행 : name과 phoneNum은 배열이기 때문에 문자열 저장을 위해서는 strcpy함수를 호출해야 한다.


- 구조체의 멤버로 배열이 선언되면 배열의 접근방식을, 포인터 변수가 선언되면 포인터 변수의 접근방식을 취하면 된다. -


구조체를 정의함과 동시에 변수를 선언할 수도 있다.


ex)

struct point

{

int xpos;

int ypos;

} pos1, pos2, pos3;     // 구조체 정의함과 동시에 변수 선언


구조체 변수를 선언과 동시에 초기화 할 수 있다.


ex)

struct point

{

int xpos;

int ypos;

}


struct person

{

char name[20];

int age;

}


int main()

{

struct point pos = {10, 20};

struct person man = {"강동원", 39};

. . . . 

}


초기화 과정에서는 문자열 저장을 위해 strcpy함수를 호출하지 않아도 된다.


구조체와 배열


전화번호부를 구현하기 위해서는 여러 사람의 정보를 저장할 수 있어야 하며, 이를 위해 다수의 구조체 변수를 선언해야 한다.


다수의 구조체 변수를 선언할 때에는 구조체 배열을 선언한다.


int형 변수의 선언과 int형 배열선언의 관계


int형 변수 : int num -> int형 배열 : int arr[10]


point형 변수의 선언과 point형 배열선언의 관계


point형 변수 : struct point pos -> point형 배열 : struct point arr[10]


따라서 다음과 같이 poiint형 구조체 배열을 선언하면


struct point arr[4];


다음의 구조로 배열이 할당된다.



ex)

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
#include<stdio.h>
 
struct point
{
    int xpos;
    int ypos;
};
 
int main()
{
    struct point arr[3];
    int i;
    
    for(i=0;i<3;i++)
    {
        printf("점의 좌표 입력:");
        scanf("%d %d",&arr[i].xpos, &arr[i].ypos);
    }
 
    for(i=0;i<3;i++)
    {
        printf("[%d, %d]",arr[i].xpos, arr[i].ypos);
    }
    
    return 0;
}
 

cs

출력결과

점의 좌표 입력:3 5

점의 좌표 입력:2 4

점의 좌표 입력:1 3

[3, 5][2, 4][1, 3]


구조체 변수를 선언과 동시에 초기화할 수 있는데 중괄호를 통해 하면 가능하다.(2차원배열처럼)


struct point arr[3]={

{1, 5},

{2, 6},

{3, 7}

}


구조체 변수와 포인터


point형 구조체의 포인터 변수 선언과 초기화


struct point pos = {10, 20};    // xpos, ypos를 각각 11,12로 초기화

struct point * pptr = &pos;     // 포인터 변수 pptr이 구조체 변수 pos를 가리킴


point형 포인터 변수를 이용해 구조체 변수에 접근할 때에는


(*pptr).xpos = 10;    // pptr이 가리키는 구조체 변수의 멤버 xpos에 10 저장

(*pptr).ypos = 20;    // pptr이 가리키는 구조체 변수의 멤버 ypos에 20 저장


위의 문장은 다음과 같이 쓸 수 있다.


pptr -> xpos = 10;

pptr -> ypos = 20;


완전 동일한 문장!


ex)

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
#include<stdio.h>
 
struct point
{
    int xpos;
    int ypos;
};
 
int main()
{
    struct point pos1={1,2};
    struct point pos2={100,200};
    struct point * pptr=&pos1;
    
    (*pptr).xpos += 4;
    (*pptr).ypos += 5;
    printf("[%d, %d] \n", pptr->xpos,pptr->ypos);
    
    pptr=&pos2;
    
    pptr->xpos += 1;
    pptr->ypos += 2;
    printf("[%d, %d] \n", (*pptr).xpos, (*pptr).ypos);
    
    return 0;
}
 

cs

출력결과

[5, 7] 

[101, 202] 


1. ex) 포인터 변수를 구조체의 멤버로 선언하기

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
#include<stdio.h>
 
struct point
{
    int xpos;
    int ypos;
};
 
struct circle
{
    double radius;
    struct point * center;
};
 
int main()
{
    struct point cen={2,7};
    double rad=5.5;
    
    struct circle ring={rad,&cen};
    printf("원의 반지름: %g \n",ring.radius);
    printf("원의 중심 [%d, %d] \n", (ring.center)->xpos, (ring.center)->ypos);
    
    return 0;
}
 

cs

출력결과

원의 반지름: 5.5 

원의 중심 [2, 7] 


위 예제에서 선언한 구조체 변수 ring과 cen의 관계



type형 구조체 멤버로 type형 포인터 변수를 둘 수 있다.

다음과 같은 선언이 가능하다.


struct point

{

int xpos;

int ypos;

struct point * ptr;    // 구조체 point의 포인터 변수 선언

}


2. ex) type형 구조체 멤버로 type형 포인터 변수를 둘 수 있다.

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
#include<stdio.h>
 
struct point
{
    int xpos;
    int ypos;
    struct point *ptr;
};
 
int main()
{
    struct point pos1 = {11};
    struct point pos2 = {22};
    struct point pos3 = {33};
    
    pos1.ptr = &pos2;   // pos1과 pos2를 연결
    pos2.ptr = &pos3;   // pos2와 pos3을 연결
    pos3.ptr = &pos1;   // pos3과 pos1을 연결
    
    printf("점의 연결관계 . . . \n");
    printf("[%d, %d]와 [%d, %d] 연결 \n",pos1.xpos, pos1.ypos, pos1.ptr->xpos, pos1.ptr->ypos);
    printf("[%d, %d]와 [%d, %d] 연결 \n",pos2.xpos, pos2.ypos, pos2.ptr->xpos, pos2.ptr->ypos);
    printf("[%d, %d]와 [%d, %d] 연결 \n",pos3.xpos, pos3.ypos, pos3.ptr->xpos, pos3.ptr->ypos);
    
    return 0;
}
 

cs

출력결과

점의 연결관계 . . . 

[1, 1] [2, 2] 연결 

[2, 2] [3, 3] 연결 

[3, 3] [1, 1] 연결 


3. ex) 구조체 변수의 주소 값은 구조체 변수의 첫 번째 멤버의 주소 값과 동일하다.


struct point

{

int xpos;

int ypos;

};


int main()

{

struct point pos1 = {10, 20};

. . . .

}


위의 코드에서 &pos1과 &pos1.xpos는 동일하다. ( 구조체 변수의 주소값과 구조체 변수의 첫 번째 멤버의 주소 값은 동일하다.)