본문 바로가기

C언어

Chapter 17. 구조체와 포인터

Chapter17.구조체와포인터

구조체의 정의하면 다음과 같이 2가지로 말할 수 있겠다.

  1. 변수들이 모여 있는 집합체이다.
  2. 변수들은 다른 타입을 가질 수 있다.

이 집합체는 논리적으로 관련이 있으며 하나의 이름으로 통칭한다.

사실 구조체를 사용하지 않고 배열을 사용할 수도 있다.

하지만, 구조체를 사용하면 변수들이 논리적으로 하나가되기 때문에 인식하기가쉽고 프로그래밍을 하기도 편하다.

구조체와 배열의 차이

주소록에는 이름과 생년월일, 주소, 전화 번호 등이 포함되어 있다.이를배열로 표현하면 아래와 같다.

char name[20],address[100], birthday[11], phone[15];

위의 배열 정의는 한 사람만 저장할 수 있으며, 만약 50명을 저장하려 한다면 2차원 배열을 이용해야 한다.

또한, 그 이상일 경우에는 프로그램이 수정되어야하며 프로그램은 재 컴파일이 필요하며 실행파일도 모든 사용자에게 재배포 해야 한다.

이를 구조체로 정의해보자.

structjuso {

char name[20];

char address[100];

char birthday[11];

char phone[15];

} address;

위의 주소록 구조체는 연관된 테이터들을 하나로 묶어줌으로써 개념적으로 쉽게 와 닿는다.

address라는 이름으로 주소록의 내용을 마음대로 조작하거나 바꿀 수있으며 다른 구조체로 복사도 가능하다.

구조체 선언과 정의

구조체를 선언한다는 것은 메모리 할당이 이루어지지 않는 것을 말하며 정의는 메모리 할당이 이루어지는 것이다.

1.구조체 선언

struct imsi {

char company[20];

char name[20];

int age;

};

이러한구조체를 생성하겠다는 것을 시스템에 암시만 하기 때문에 메모리 할당이 이루어지지 않는다.

따라서,3번을 같이 수행해야 한다. 그렇지 않으면 선언한 구조체를 사용할 수 없다.

2.구조체 선언과정의

struct{

char company[20];

char name[20];

int age;

} business_card;

구조체 태그가 빠져 있으므로 반드시 선언과 동시에 정의가 이루어져야 한다.

struct imsi {

charcompany[20];

char name[20];

int age;

} business_card;

역시 선언과 정의를 동시에 하면서 구조체 태그를생략하지 않았기 때문에 나중에 언제든지 다시 정의할 수 있다.

3.구조체 정의

struct imsi business_card;

이미 선인된 구조체에 대해서 정의하는 형식이다.

사실 위의 구조체 정의보다는 typedef문을 이용한 아래와 같은 방식을 더 선호한다.

처음에는 struct라는 단어가 빠져 있어보기에 불편할지 모르나 익숙해지면 typedef을 이용하는 것이 편리하다는 것을 알 수 있다.

struct imsi {

char company[20];

charname[20];

int age;

};

typedef struct imsi address_book;

address_bookaddress1, address2, ...

address_book address[100];

address_book *address;

구조체 연산

17_1.c

#include <stdio.h>
#include <string.h>

struct grades {
char name[20];
int kor;
int eng;
int mat;
};

main()
{
typedef struct grades grade;

grade student[2];

strcpy(student[0].name, "Kang Dong Nam");
student[0].kor = 72;
student[0].eng = 85;
student[0].mat = 43;

strcpy(student[1].name, "Kang Chun Gil");
student[1].kor = 56;
student[1].eng = 93;
student[1].mat = 84;

printf("name : %s\n", student[0].name);
printf("kor : %d\n", student[0].kor);
printf("eng : %d\n", student[0].eng);
printf("mat : %d\n", student[0].mat);
printf("total : %d\n\n", student[0].kor+student[0].eng+student[0].mat);

printf("name : %s\n", student[1].name);
printf("kor : %d\n", student[1].kor);
printf("eng : %d\n", student[1].eng);
printf("mat : %d\n", student[1].mat);
printf("total : %d\n\n", student[1].kor+student[1].eng+student[1].mat);
}

gcc-o17_1 17_1.c

./17_1

name : Kang Dong Nam
kor : 72
eng : 85
mat : 43
total : 200

name : Kang Chun Gil
kor: 56
eng : 93
mat : 84
total: 233

구조체를 선언하고 이를 배열로 정의하였으며 크기는 2이므로 두 사람 분의 자료를 저장할 수 있다.

구조체의 멤버를 접근하기 위해서는 '.' 연산자를 사용하는데 직관적으로 이해하기 쉬운 연산자이다.

구조체와 포인터
int imsi[] = {7, 4, 9};
printf("%#010x\n", imsi);

배열명은 주소를 뜻하므로 구조체도 같이 생각하기 쉽다. 하지만, 이것은 상당히곤란한 생각이다.

imsi는 주소를 뜻한다. printf()를 이용하면 주소 값이 출력된다.

struct grades {

char name[20];

intkor;

int eng;

int mat;

};

printf(%#010x\n", grades);

error : 'grades' undeclared (firstuse in this function)

배열명과 구조체명은완전히 별개의 것이다.

그러므로 배열명 +1이 현재 가리키고 있는 배열 요소의 다음을 가리키는 반면에 구조체명 + 1은 전혀 의미가 없다.

struct grades {

char name[20];

int kor;

int eng;

int mat;

};

main()

{

typedef struct gradesgrade;

grade *student;

...

}

student라는 구조체 포인터 변수를 정의한 것 이외에는 이전의 프로그램과 크게 다르지 않다.

하지만, 메모리에 할당되는 형식이 크게 다르다.

"gradestudent"를정의함으로써 할당되는 메모리는 모두 32byte(name + kor +eng + mat)이며,

"grade *student"에의해서 할당된 메모리는딱 4byte이다.

즉, 구조체를 가리킬 수 있는 영역이 메모리에 할당될 뿐 구조체 자체가 할당되는 것이 아니다.

17_1_1.c

#include <stdio.h>
struct grades {
char name[20];
int kor;
int eng;
int mat;
};
main()
{
typedef struct grades grade;
grade student;
grade *studentp;
printf("student : %d\n", sizeof(student));
printf("*student : %d\n", sizeof(studentp));
}
gcc -o 17_1_1 17_1_1.c
./17_1_1
student : 32
*student : 4

위와 같이 sizeof()로 쉽게 확인할 수 있다.

구조체를 가리킬 수 있는 영역4byte를 생성했으므로 실질적인 구조체가 당연히 존재해야한다. 이것은malloc()으로 만든다.

student = (grade *)malloc(sizeof(grade));

위 식의 수행으로 메모리의 어딘가에 32byte가 할당되고 이 주소를student에 넘기고 있다.

프로그램이끝나기 전에는 절대 메모리가 해제되지 않는다.메모리 할당 후에는 사용자가 반드시 해제해 주어야 한다.

멤버 초기화

malloc()에 의해서 할당된 영역에 값을 할당해보자.

strcpy((*student).name, "ChaHong Suk");

(*student).kor =63;

괄호와 '*'연산자를 사용해야만 구조체 멤버에 접근하여 값을 할당할수 있다. 연산 우선순위를 생각하면 괄호는 생략할 수 없다.

하지만, 이런 번거로움을 대신하는 연산자가 "->"연산자이다.

화살표 연산자(arrow operator)라 불리는 이 연산자는 구조체 포인터 연산을 좀더 직관적으로 보기 편하도록 한다.

위의 수식을 다시 작성해보면 다음과 같다.

strcpy(student->name, "Cha HongSuk");

student->kor = 63;

주의 사항

초보자들이많이 틀리는 부분중하나이니 주의 깊게살펴보자.

17_2.c

#include <string.h>
#include <stdio.h>

struct grades {
char *name;
int kor;
int eng;
int mat;
};

main()
{
typedef struct grades grade;
grade *student;

student = (grade *)malloc(sizeof(grade));

//strcpy(student->name, "Jung Kang Hun");
student->name = "Jung Kang Hun";
student->kor = 73;
student->eng = 23;
student->mat = 85;

printf("name : %s\n", student->name);
printf("kor : %d\n", student->kor);
printf("eng : %d\n", student->eng);
printf("mat : %d\n", student->mat);
}

gcc -o17_217_2.c

./17_2

name : Jung Kang Hun
kor : 73
eng : 23
mat : 85

눈에 잘 보이지 않는 대표적인 에러인데 그것은 바로 구조체 안에 있는name이라는 변수에서 발생한다.

name은 포인터 변수이다. 포인터 변수에 문자열을 할당할 때는 strcpy()가 아니라바로 할당해야 한다.

만약 strcpy()를 사용하여 할당하려면 다음과 같이 해야 한다.

student->name = (char *)malloc(sizeof(char) * 20);

strcpy(student->name, "Jung KangHun");

에러가 나는 이유를 정확히 알았을 것이다. 바로 name에 대한 메모리 할당을 해주지 않았기 때문이다.

student에 대해서 malloc()을 해주었는데하고 반문할지도 모르겠다.

하지만, 그것은name에 해당하는16byte만 할당될 뿐name이 가리키는 영역에 대해서는 메모리 할당이 이루어지지 않는다.

name이 포인터 변수이며 가리키는대상에 대한 메모리 할당은 이루어지지 않았다는 것이다.

이 상태에서 strcpy()를 이용하여 문자열을 복사하면name이 가리키는 이상한 영역에복사가 이루어지고 시스템에 문제일 일으키게 된다.

이를 해결하기 위해서는 name이가리키는 영역을 초기화 해주어야 하며 그 방법은문자열을 바로 할당하는 것malloc을 통해 초기화를해주는것이다.

따라서, 구조체 안에서 문자열을 저장할 일이 생긴다면 배열을 사용하는 것이 좋다. 특히 초보자에게.

위의 프로그램은malloc()을 사용하지 않아도 프로그램이 동작할 때가있어 그 피해는 더 심각해질 수 있다.

중첩 구조체

구조체를 중첩해서 사용함으로써 프로그램에 상당한 융통성을 발휘할 수 있다.

17_3.c

#include <stdio.h>
#include <stdlib.h>

struct privates {
char *name;
int age;
};

struct scores {
int kor;
int eng;
int mat;
};

struct grades {
struct privates *private;
struct scores *score;
};

main()
{
typedef struct grades grade;
grade *student;
int total;

student = (grade *)malloc(sizeof(grade));
student->private = (struct privates *)malloc(sizeof(struct privates));
student->score = (struct scores *)malloc(sizeof(struct scores));

student->private->name = "Cha Ju Min";

//student->private->name = (char *)malloc(sizeof(char) * 20);

//strcpy(student->private->name, "Cha Ju Min");

student->private->age = 23;

student->score->kor = 87;
student->score->eng = 42;
student->score->mat = 17;

total = student->score->kor + student->score->eng + student->score->mat;

printf("name : %s\n", student->private->name);
printf("age : %d\n", student->private->age);
printf("total : %d\n", total);
}

gcc -o17_3 17_3.c

./17_3

name : Cha Ju Min
age : 23
total : 146

중첩된 구조체를 정의한 후에는 메모리 할당에 있어서 상당한 주의를 요한다.

각각의 구조체를 모두malloc()을 이용해메모리 할당을 해주어야 한다.

메모리 할당이 정상적으로 처리되면 초기화가 진행되는데 private의name은 따로malloc()을 하지 않았기 때문에 strcpy() 함수를 사용하려면malloc()을해야한다.

구조체 복사

구조체에 있는 모든 멤버들의 값들을 다른 구조체로 할당하기 위해서는 "구조체 =구조체"라고 하면된다.

함수로 넘겨서 ㅓ리할 때도 같은 동작이 일어난다.

17_4.c

#include <stdio.h>

struct imsi {
int x;
int y;
};

main()
{
struct imsi struct_copy(struct imsi);
struct imsi one, two;

one.x = 10;
one.y = 1024;

two = struct_copy(one);

printf("x = %d\ny = %d\n", two.x, two.y);
}

struct imsi struct_copy(struct imsi temp)
{
return temp;
}

gcc -o17_4 17_4.c

./17_4

x = 10
y = 1024

위의 프로그램은 상당히 황당한 코드로 되어 있다. 구조체가 복사되는 형태이기 때문이다.

만약 구조체가 몇 백만 바이트라면 복사되면서 낭비되는 시간은 생각보다 크게 된다.

위의 프로그램은 예제일 뿐 사용되기 힘든 코드이다.

보통 구조체 포인터 변수를 이용하여 처리한다.

struct imsione;

structimsi*onep;

one.x = 10;

one.y =1024;

onep= &one;

조심할 것은 구조체명은 포인터가 아니라는것이다.

배열명이나함수명이 주소 값을 함유하고 있어 혼돈의 여지가 있을 수 있다.

다음 예제는x와y에 들어있는 값을 변경하는데 포인터변수를 이용하고 있다.

17_5.c

#include <stdio.h>

struct imsi {
int x;
int y;
};

main()
{
void swap_struct(struct imsi *);
struct imsi one;

one.x = 10;
one.y = 1024;

swap_struct(&one);

printf("x = %d\ny = %d\n", one.x, one.y);
}

void swap_struct(struct imsi *temp)
{
int sample;

sample = temp->x;
temp->x = temp->y;
temp->y = sample;
}

gcc -o 17_5 17_5.c

./17_5

x = 1024
y = 10

매개변수가 구조체 배열인 함수

17_6.c

#include <stdio.h>

struct grades {
//char name[20];
char *name;
int kor;
int eng;
int mat;
};

typedef struct grades grade;

main()
{
void insert_struct(grade *);
void print_struct(grade *);
grade student[3];

insert_struct(student);
print_struct(student);
}

void insert_struct(grade *imsi)
{
imsi[0].name = "Kim Dae Jin";
imsi[0].kor = 93;
imsi[0].eng = 73;
imsi[0].mat = 28;

imsi[1].name = "Kim Sun Wol";
imsi[1].kor = 39;
imsi[1].eng = 80;
imsi[1].mat = 92;

imsi[2].name = "Kim Su Jin";
imsi[2].kor = 77;
imsi[2].eng = 20;
imsi[2].mat = 93;
}

void print_struct(grade *imsi)
{
int i;

for(i=0;i<3;i++, imsi++)
{
printf("name : %s\n", imsi->name);
printf("kor : %d\n", imsi->kor);
printf("eng : %d\n", imsi->eng);
printf("mat : %d\n", imsi->mat);

if(i < 2) puts("-------------------");
}
}

gcc -o17_6 17_6.c

./17_6

name : Kim Dae Jin
kor : 93
eng : 73
mat : 28
-------------------
name : Kim Sun Wol
kor : 39
eng : 80
mat : 92
-------------------
name : Kim Su Jin
kor : 77
eng : 20
mat : 93

배열로정의된 구조체를 함수가 받아 이를 어떻게 출력하는지다방면으로 알아보면 구조체와 포인터를 이해하는데 상당한 도움을 줄 것이다.

printf("name : %s\n", imsi[0].name);

구조체 포인터 변수로 받아서 이를배열처럼 사용한 예이며 다음은 포인터 연산자로 사용한 예이다.

printf("name : %s\n", imsi->name);

포인터 변수로 받아 출력하는 중 난위도 예제들을 통해 구조체와 포인터의 개념을 완벽히 이해해보자.

1) 중 난위도 예제들

1.imsi[0].name

2.imsi->name

3.(*imsi).name

imsi->name과완전히 같은 표기라고 봐도 무방하다.

4. *imsi.name

괄호생략했을 때는 우선순위에 변화가 생기게 된다.

'*' 연산자 보다는 '.' 연산자의 우선순위가 높기 때문에 이 표기는 말 자체가 되지 않는다.

imsi는 현재 구조체 포인터 변수이기 때문에 가리키는 곳으로 가서 그곳에 있는 멤버들을 참조해야 한다. 화살표 연산자나 '*' 연산자가 이를 가능하게 해준다.

5. *(imsi.name)

4번과같은 이유로 허용되지않는 연산이다.

6.*imsi->name

'*'연산자 보다는 '->' 연산자의 우선순위가 높기때문에 이 연산은 허용된다.

하지만, 문져열을 출력하려고 하였다면 위 수식은 안된다. '*' 연산자에 의해서 하나의 문자만을 취하고 있기 때문이다.

이를 이용하여다음과 같이 name에 있는 문자열을 모두 출력할 수는 있다.

for(;*imsi->name;*(imsi->name)++)

putchar(*imsi->name);

7.*(imsi->name)

6번과 같은 수식이다.

8.(*imsi)->name

이 문장을 풀이하면(*(*imsi).name).imsi가 가리키는 구조체로가고 그 구조체 중에서 name 멤버를 찾는다. 그리고 하나의 문자를 취한다.허용되지 않는다.

17_6_1.c

#include <stdio.h>

struct grades {
char *name;
int kor;
int eng;
int mat;
};

typedef struct grades grade;

main()
{
grade imsi[2];

imsi[0].name = "Kim Dae Jin";
imsi[0].kor = 93;
imsi[0].eng = 73;
imsi[0].mat = 28;

printf("imsi[0].name : %s\n", imsi[0].name);
printf("imsi->name : %s\n", imsi->name);
printf("(*imsi).name : %s\n", (*imsi).name);
//printf("*imsi.name : %s\n", *imsi.name);
//printf("*(imsi.name) : %s\n", *(imsi.name));
printf("*imsi->name : %c\n", *imsi->name);
printf("*(imsi->name) : %c\n", *(imsi->name));
//printf("(*imsi)->name : %s\n", (*imsi)->name);
}

gcc -o 17_6_1 17_6_1.c
./17_6_1
imsi[0].name : Kim Dae Jin
imsi->name : Kim Dae Jin
(*imsi).name : Kim Dae Jin

//17_6_1.c: 24: error: request for member 'name' in something not a structure or union

//17_6_1.c: 25: error: request for member 'name' in something not a structure or union

*imsi->name : K
*(imsi->name) : K

//17_6_1.c: 28: error: invalid type argument of '->'

2)중 난위도 예제들

1.*imsi++.name

*((imsi++).name)와 같다.

++ 후위 연산자가 붙었기 때문에현재의 연산에는 아무영향을 미치지 않는다.

그런데, 우선순위에 의해imsi.name이 먼저 연산되어 에러가 된다.

2.*++imsi.name

*((++imsi).name)과 같다.

1번과 같은 방식으로 에러가 난다. imsi가 가리키는 구조체로 이동하기위해서는 '->' 연산자나 '*' 연산자가 필요하다.

3.++*imsi.name

++(*(imsi.name))과 같다.

1, 2번과 같은 방식으로에러가 난다.

4.++(*imsi).name

++((*imsi).name)과 같다. 정상적인 수식이다.

(*imsi).name은imsi가 가리키는 구조체 중에서name멤버를 말하고다시 전치 연산자가 있어 name이 가리키는포인터를 하나 증가시킨다.

따라서, 문자열을 출력하면'i'부터 마지막 문자열까지 출력될 것이다.

5.(*imsi)++.name

((*imsi)++).name과 같다.

4번과유사하다. 후치연산이기 때문에 출력에는 아무런 영향이없다.

또한, imsi는 포인터 변수가 아니기 때문에다음imsi구조체를 만나는 순간 문제를 발생한다.

6.*imsi.name++

(*(imsi.name))++와 같다.

imsi.name이라는 수식을 보는 순간 잘못 되었다는 것을 알아야 한다.

7.*imsi.++name

*(imsi.(++name))와 같다.

6번과 마찬가지로 imsi.name이 결합됨을 알 수 있다.

8.imsi++->name

(imsi++)->name ==(*(imsi++))->name과 같다.

'->'연산자는괄호와 '*'로 늘여 사용할 수 있으므로(*(imsi++)).name이 될 것이다.

후위 연산자를 포함하고 있으므로현재의 출력에는아무런 영향이 없다. imsi->name과 같은 결과를 출력하지만 imsi->name과 같은것은 아니다.

9. ++imsi->name

++(imsi->name)== ++((*imsi).name)과같다.

전치 연산가 있기 때문에 현재의 대상체인name의 1byte가 증가하여'i'부터 마지막 문자열까지 출력된다.

10.*++imsi->name

++(*imsi->name) ==*(++(imsi->name)==*(++((*imsi).name)) 와 같다.

imsi->name은"Kim Dae Jin"의 'K'를 가리키고 있다.

++ 전치 연산자에 의해 포인터가1byte 증가하여 'i'가 되며 '*'로 'i'가 출력될 것이다.

11. (*imsi->name) + 1

(*((*imsi).name) + 1 과 같다.

imsi->name은 'K'를 가리키고 있고 '*'로 'K' 문자가추출되고 그 문자에 1을 더했기 때문에문자 'L'이된다.

자기 참조 구조체

구조체의 백미라고 할 수 있는 분야이다. 이것을 자유자재로 사용하는 순간C언어의 또 다른 묘미를 만끽할 수있을 것이다.

구조체를 배열로 정의하면 첨자를 지정하지 않을수없다. 그런데 첨자를 지정하면 그 첨자의 범위를 넘어설 때 수정을 가하고 다시 컴파일해야 하는 문제점이 있다.

이를 해결할 수 있는 방법이 자기 참조 구조체이다. 자기 참조 구조체의사용 용도는 무궁 무진 하지만 여기서는간단히 알아보기로 하자.

structlist{

char *name;

int grade;

structlist *next;

};

struct list one;

구조체 자체가 자신을 참조하는 포인ㅌ를 가진다면 이 구조체를 자기 참조 구조체라 한다.

이와 같이 one을 정의하면 name, grade, next가 메모리에 각각1byte, 4byte, 4byte씩 할당된다.

next는 주소를 저장할수 있는 공간이며 현재 쓰레기 주소 값을 갖고 있다.

구조체 one은현재한 사람 분량의 정보만을 저장할수 있고 그 이상의 분량의 정보를 저장하기 위해서는 다른 변수를 정의해야 했다.

하지만, 자기 참조 구조체를이용하면다른변수를 지정하지 않아도 가능하게 된다.

17_7.c

#include <stdio.h>
#include <stdlib.h>

struct list {
char *name;
int grade;

struct list *next;
};

main()
{
struct list *make_first_node();
void connect_node(struct list *);
void print_node(struct list *);
struct list *one;

one = make_first_node();
connect_node(one);

print_node(one);
}

struct list *make_first_node()
{
struct list *temp;

temp = (struct list *)malloc(sizeof(struct list));

temp->name = "first";

temp->grade = 0;

temp->next = NULL;

return temp;

}

void connect_node(struct list *one)
{
struct list *imsi;

imsi = (struct list *)malloc(sizeof(struct list));

imsi->name = "second";
imsi->grade = 75;
imsi->next = NULL;

one->next = imsi;
}


void print_node(struct list *one)
{
while(1)
{
puts(one->name);
if(one->next == NULL) break;
one = one->next; /* 자기 참조 구조체의 핵심*/
}

/*for(;one->next;one=one->next)
puts(one->name);*/

}

gcc -o 17_7 17_7.c

./17_7

first
second

make_first_node() 함수를make_first_node(one) 이렇게 사용하면 안된다.

만약, 포인터 변수를 넘겨서 처리하기 위해서는함수를 호출하기 전에 one 구조체를malloc()을 통해 초기화를 해주어야 하는데 불편함이 있다.

그렇지 않고 함수내에서malloc()을 통해 초기화를 하여 처리한다면make_first_node() 함수가 끝나는 동시에 메모리에서 삭제가 되기 때문에

함수에 전달된 원본 구조체에는 아무런 변화가 없다.chapter 12에서 call by value와 call by reference 에 대한 부분을 기억하자.

자기 참조 구조체는 소위 세 박자가 맞아야 정확한 결과를 얻을 수 있다.

첫번째는 초기화이다. 초기화가 잘못되면 그 뒤는 불을 보듯뻔하다.

두번째는 연결이다. 연결 고리를 제대로 설정하지않으면 값이 제대로 할당되었다 할지라도 나중에 출력할 수 없다.

세번째는 출력이다. 초기화와 여결고리까지 제대로 했지만 출력을 잘못하면 메모리 에러가 난다. 시스템이 멈추거나 버벅거리기 일쑤다.

위의 while()문을 for()문으로 수정하여 결과 값을 보면 "second"는 출력되지 않는다.for()문의 결과는 항상 하나가 모자르게 출력된다.

for()문의 "one=one->next"로 인해서 one 구조체의 각 멤버 name = "second", grade = 75, next = NULL을 갖게 된다. 즉, second에 저장되어 있는 next는 NULL이다.

따라서, one->next의 값이 NULL이 되어 for() 루프를 빠져나오게 되기 때문에 "second"가 출력되지 않는다.

리스트

17_8.c

#include <stdio.h>
#include <stdlib.h>

#define OFF 0
#define ON 1

#define V {}

typedef struct lists {
char *name;
int grade;

struct lists *next;
} list;

static list *HEAD;
static list *student;

main()
{
void init_node();
void insert_node(char *, int);
void print_node();
void end_node();

V init_node();
insert_node("archie", 75);
insert_node("Park Mi Kyung", 94);
insert_node("Park Une Ju", 63);
insert_node("Park Une Young", 72);
insert_node("Park Mi Ra", 86);
insert_node("Park Jung Suk", 32);
V end_node();
V print_node();

return 0;
}

void init_node()
{
HEAD = (list *)malloc(sizeof(list));
HEAD->next = NULL;
}

void insert_node(char *name, int grade)
{
static int flag = OFF;
list *imsi;

if(flag == OFF)
{
student = (list *)malloc(sizeof(list));
student->name = name;
student->grade = grade;
student->next = NULL;

HEAD = student;
flag = ON;
}
else
{
imsi = (list *)malloc(sizeof(list));
imsi->name = name;
imsi->grade = grade;
imsi->next = NULL;
student->next = imsi;
student = student->next;
}
}

void end_node()
{
list *imsi;

imsi = (list *)malloc(sizeof(list));

imsi->next = NULL;

student->next = imsi;
}

void print_node()
{
for(student = HEAD;student->next;student = student->next)
printf("%d %s\n", student->grade, student->name);
}

gcc -o17_8 17_8.c

./17_8

75 archie
94 Park Mi Kyung
63 Park Une Ju
72 Park Une Young
86 Park Mi Ra
32 Park Jung Suk

'C언어' 카테고리의 다른 글

Chapter 15. 함수 인자 포인터  (0) 2011.10.16
Chapter 16. 함수 포인터  (0) 2011.10.16
Chapter 13. (int *)pointer  (0) 2011.10.16
Chapter 14. void형 포인터  (0) 2011.10.16
Chapter 10. 바로알자 getchar()  (0) 2011.10.16