2011년7월8일_구조체원형과 정의(typedef), 구조체선언, 간단한 Linked list(자기참조포인터(자기참조구조체), 노드 연결, 노드 엑세스, 구조체포인터와 반복문을 사용하여 쉽게 엑세스하기
구조체의 원형과 정의(typedef) 그리고 선언 |
● 구조체의 원형과 선언
1: //구조체의 원형
2: struct _node //_node는 tag명
3: {
4: int iNum; //구조체멤버변수
5: };
6:
7: //_node는 구조체원형의 tag일 뿐 자료형은 아니다. 그래서 아래와 같이 선언하면 에러가 난다.
8: _node A;
_node가 선언되지 않았다는 에러메세지를 출력한다.
그러므로 다음과 같이 type을 정해준다.
1: #include <stdio.h>
2:
3: struct _node
4: {
5: int iNum;
6: };
7:
8: int main()
9: {
10: struct _node A;
11:
12: A.iNum = 100;
13: printf("%d\n", A.iNum);
14:
15: return 0;
16: }
1: //typedef [old type] [new type];
2: typedef struct _node {} NODE; // NODE를 구조체 _node형으로 정의
3: //상기문은 복잡하므로 하기와 같이 풀어 쓴다.
4: typedef struct _node
5: {
6: int iNum;
7: } NODE; // NODE를 구조체 _node형으로 정의
typedef 지시어의 사용법은 상기와 같고 꼭 외울 것. 끝에 세미콜론은 꼭 넣어야 함.
4행 부터 7행까진 2행을 풀어 쓴 것으로 자주 사용하므로 꼭 외울 것. (자주 사용하면 자연스럽게 외워지므로 걱정하지 말자.)
1: #include <stdio.h>
2:
3: typedef struct _node
4: {
5: int iNum;
6: } NODE;
7:
8: int main()
9: {
10: NODE A;
11:
12: A.iNum = 100;
13: printf("%d\n", A.iNum);
14:
15: return 0;
16: }
간단히 NODE를 struct _node type으로 정의하고 NODE형 구조체 A를 선언한 뒤에,
A구조체의 멤버변수 A에 100을 대입한 뒤에 그대로 출력하는 예제소스코드이다.
간단한(단일) Linked list |
● 기본적인 Linked list
1: #include <stdio.h>
2:
3: //구조체 원형 + 정의를 풀어 놓은 것. 4: typedef struct _node 5: {
6: int iNum; 7: struct _node *next; 8:
9: } NODE;
10:
11: int main() 12: {
13: NODE one;
14: NODE two;
15: NODE three;
16: NODE *p;
17: int iLoop; 18:
19: //대입 20: one.iNum = 1;
21: two.iNum = 2;
22: three.iNum = 3;
23:
24: //값 확인 25: printf("one.iNum = %d\n", one.iNum); 26: printf("two.iNum = %d\n", two.iNum); 27: printf("three.iNum = %d\n", three.iNum); 28: putchar('\n'); 29:
30: //링크 31: one.next = &two; //첫 링크 32: two.next = &three; //두 번째 링크 33: three.next = NULL; //Ground? 34:
35: //NODE *p를 쓰지않고 하는 법 36: printf("\x1b[43m\x1b[30mNODE *p사용하지 않는 법\x1b[0m\n"); 37: printf("%d -> ", one.iNum); 38: printf("%d -> ", one.next->iNum); 39: printf("%d -> ", one.next->next->iNum); 40: //printf("%d -> ", one.next->next->next); //0출력됨. 41: printf("NULL\n"); 42: putchar('\n'); 43:
44: return 0; 45: }
|
13~17행..
one, two, three를 NODE형 구조체로 선언하고 그 구조체들를 가리킬 포인터변수 p도 선언하였다.
int형 iLoop와 구조체포인터 p는 이 소스에선 불필요하다. (왜 넣었나?)
20~28행…
각 구조체이름에 맞게 값을 대입한 후 값을 확인하기 위해 화면에 출력한다.
31~33행...
각 구조체의 자기참조포인터변수 next는 다음 구조체를 가리키도록함.
마지막 three구조체는 끝이므로 NULL을 가리키게 한다.
포인터변수는 쓰레기값으로 두면 매우 위험하므로 아무것도 가리키지 않을 때는 NULL로 초기화해야 한다.
37~39행..
one은 시작이니 iNum값을 출력하고,
다음 값을 출력하기 위해 one구조체의 next가 가리키는 구조체의 iNum의 값을 출력하게 한다.
그 다음 값은 one구조체의 next가 가리키는 구조체의 next가 가리키는 구조체의 iNum의 값을 출력하게 한다.
이를 도식으로 나타내면 다음과 같다.
one구조체의 자기참조포인터 next는 two구조체를 가리키고 있고, two구조체의 자기참조포인터 next는 three구조체를 가리킨다.
one, two, three구조체이름 자체의 주소는 그 구조체의 첫 멤버의 주소이므로 next는 iNum을 가리킨다.
마지막 three구조체는 NULL값을 가지므로 GND(?)되었다. 또는 박스모양에 사선을 그어 표시하기도 한다.
<실행결과>
● NODE형 구조체포인터 p를 선언하여 Linked list를 가리키게 하고 쉽게 접근하기
1: #include <stdio.h>
2:
3: //구조체 원형 + 정의를 풀어 놓은 것. 4: typedef struct _node 5: {
6: int iNum; 7: struct _node *next; 8:
9: } NODE;
10:
11: int main() 12: {
13: NODE one;
14: NODE two;
15: NODE three;
16: NODE *p;
17: int iLoop; 18:
19: //대입 20: one.iNum = 1;
21: two.iNum = 2;
22: three.iNum = 3;
23:
24: //값 확인 25: printf("one.iNum = %d\n", one.iNum); 26: printf("two.iNum = %d\n", two.iNum); 27: printf("three.iNum = %d\n", three.iNum); 28: putchar('\n'); 29:
30: //링크 31: one.next = &two; //첫 링크 32: two.next = &three; //두 번째 링크 33: three.next = NULL; //Ground? 34:
35: //NODE *p사용. 똑같은게 반복되어 반복문사용가능.(이 방법 추천) 36: printf("\x1b[43m\x1b[30mNODE *p사용\x1b[0m\n"); 37: p = &one; //one을 가리킴. 38: printf("%d -> ", p->iNum); 39: p = p->next; //next의 주소값 -> two 40: printf("%d -> ", p->iNum); 41: p = p->next; //next의 주소값 -> three 42: printf("%d -> NULL\n", p->iNum); 43: putchar('\n'); 44:
45: //NODE *p를 쓰지않고 하는 법 46: printf("\x1b[43m\x1b[30mNODE *p사용하지 않는 법\x1b[0m\n"); 47: printf("%d -> ", one.iNum); 48: printf("%d -> ", one.next->iNum); 49: printf("%d -> ", one.next->next->iNum); 50: //printf("%d -> ", one.next->next->next); //0출력됨. 51: printf("NULL\n"); 52: putchar('\n'); 53:
54: //반복문사용 + NODE *p 55: printf("\x1b[46m\x1b[30mNODE *p사용하고 반복문사용.\x1b[0m\n"); 56: //for(iLoop = 0 ; 3 > iLoop ; ++iLoop) //제어변수필요 57: for(p = &one ; NULL != p ; p = p->next) //제어변수불필요 58: {
59: printf("%d -> ", p->iNum); 60: }
61:
62: printf("NULL\n"); 63:
64: putchar('\n'); 65:
66: return 0; 67: }
|
57~60행..
NODE형의 구조체를 가리키는 포인터변수 p는 최초구조체인 one을 가리키도록 초기화된다.
p가 가리키는 iNum은 one구조체의 멤버변수 iNum이고 그 값을 출력한다.
p는 다음 구조체에 링크된대로 다음 구조체의 next가 가리키는 곳의 값을 받는다.
다음 p가 가리키는 iNum은 one구조체 다음 구조체인 two구조체의 멤버변수 iNum이 되고 그 값을 출력한다.
이렇게 반복하다가...
p가 NULL값을 갖게 되면 연결리스트의 끝이므로 반복문을 종료한다.
최초 구조체포인터 p는 one구조체를 가리키고 있다.
파란색링크는 예전 소스와 같이 서로 다음 구조체를 가리키고 있다. (지렁이와 같다)
빨간색링크가 계속 변화하나 그 변화를 표현할 수 없어 초기값만 표시하였다.
p는 반복문이 반복될 때 마다 다음 구조체를 가리키도록 되어 있다.
<실행결과>
자기참조포인터 |
1: //구조체 원형 + 정의를 풀어 놓은 것.
2: typedef struct _node
3: {
4: int iNum;
5: struct _node *next;
6:
7: } NODE;
상기의 구조체정의의 안에 next의 자료형은 그 자신인 _node구조체에 대한 포인터이다.
이렇게 스스로를 참조하는 구조체를 자기참조포인터 또는 자기참조구조체라고 한다.
노드연결 |
1: //링크
2: one.next = &two; //첫 링크
3: two.next = &three; //두 번째 링크
4: three.next = NULL; //Ground?
노드엑세스 |
1: //NODE *p사용. 똑같은게 반복되어 반복문사용가능.(이 방법 추천)
2: printf("\x1b[43m\x1b[30mNODE *p사용\x1b[0m\n");
3: p = &one; //one을 가리킴.
4: printf("%d -> ", p->iNum);
5: p = p->next; //next의 주소값 -> two
6: printf("%d -> ", p->iNum);
7: p = p->next; //next의 주소값 -> three
8: printf("%d -> NULL\n", p->iNum);
9: putchar('\n');
10:
11: //NODE *p를 쓰지않고 하는 법
12: printf("\x1b[43m\x1b[30mNODE *p사용하지 않는 법\x1b[0m\n");
13: printf("%d -> ", one.iNum);
14: printf("%d -> ", one.next->iNum);
15: printf("%d -> ", one.next->next->iNum);
16: //printf("%d -> ", one.next->next->next); //0출력됨.
17: printf("NULL\n");
18: putchar('\n');
구조체포인터와 반복문을 사용하여 쉽게 엑세스하기 |
1: //반복문사용 + NODE *p
2: printf("\x1b[46m\x1b[30mNODE *p사용하고 반복문사용.\x1b[0m\n");
3: //for(iLoop = 0 ; 3 > iLoop ; ++iLoop) //제어변수필요
4: for(p = &one ; NULL != p ; p = p->next) //제어변수불필요
5: {
6: printf("%d -> ", p->iNum);
7: }
참조(Reference) |