#define PI 3.14

 

#define전처리기 지시자 라고 하고,

PI매크로 상수라고 한다.

 

#Define 는 식별자 또는 매개 변수화 된 식별자와 토큰 문자열을 연결 하는 매크로 를 만듭니다. 매크로가 정의된 후 컴파일러는 소스 파일에서 발생하는 각 식별자를 토큰 문자열로 대체할 수 있습니다.

 

ex)

 

#define max 100#define _CRT_SECURE_NO_WARNINGS#define ARRAY_SIZE 10

 

#include <stdio.h>

#define ARRAY_SIZE 10    // 10을 ARRAY_SIZE로 정의

int main()
{
    char s1[ARRAY_SIZE];    // 10 대신 ARRAY_SIZE 매크로 사용

    for (int i = 0; i < ARRAY_SIZE; i++)    // 10 대신 ARRAY_SIZE 매크로 사용
    {
        s1[i] = 97 + i;
    }

    for (int i = 0; i < ARRAY_SIZE; i++)    // 10 대신 ARRAY_SIZE 매크로 사용
    {
        printf("%c ", s1[i]);
    }

    return 0;
}

실행결과
a b c d e f g h i j

#define 뒤에 함수 정의도 가능하다.

#define multiply( f1, f2 ) ( f1 * f2 )
#include <stdio.h>


int main()
{
	printf("5 X 5 = %d\n", multiply(5, 5));
}

실행결과

5 X 5 = 25
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> 

#include <stdlib.h> 



struct tnode {

    int item;		/* number */

    struct tnode* left;	/* left child */

    struct tnode* right;	/* right child */

};


struct tnode* addtree(struct tnode*, int);  // addtree 함수

void deletetree(struct tnode **, int);  // deletetree 함수 

void treeprint(struct tnode*);  // treeprint 함수 (중위 순회)


main()

{

    struct tnode* root;

    int cond;
    
    int num;

    root = NULL;  // 초기화 

    while (1) {

        printf("1 : 삽입   2 : 삭제   3 : 출력   4 : 종료\n");

        scanf("%d", &cond);

        if (cond == 1) {

            printf("Add Number\n");

            scanf("%d", &num);

            root = addtree(root, num);

        }

        else if (cond == 2) { 

                printf("Delete Number\n");

                scanf("%d", &num);

                deletetree(&root, num); 

         } 

        else if (cond == 3)
        {
            treeprint(root);
        }

        else if (cond == 4)
        {
            break;
        }

        else {

            printf("Wrong Input\n");

            exit(1);

        }

    }

    return 0;

}

struct tnode* addtree(struct tnode* p, int num)

{

    if (p == NULL) {

        p = (struct tnode*)malloc(sizeof(struct tnode));

        p->item = num;

        p->left = p->right = NULL;

    }

    else if (num == p->item)

        printf("존재하는 숫자 입니다\n");

    else if (num < p->item) 

        p->left = addtree(p->left, num);

    else

        p->right = addtree(p->right, num);

    return p;

}



// 중위 순회 

void treeprint(struct tnode* p)

{
    if (p != NULL) {

        treeprint(p->left);

        printf("%d\n", p->item);

        treeprint(p->right);

    }

}


void deletetree(struct tnode** root, int num)

{

    struct tnode* prev, * deleted, * parent, * move;

    prev = parent = move = NULL;

    deleted = *root;



    while (deleted) {           // 삭제 할 숫자 찾으러 가는 부분 

        if (num == deleted->item)   // 삭제를 입력한 숫자와 입력된 데이터 값이 같은 경우 

            break;  // while문 빠져나온다.

        else if (num < deleted->item) {     // 삭제를 입력한 숫자 <<< 입력된 데이터 값 인 경우 , if 왼쪽서브트리문을 수행할 예정.  

            prev = deleted;

            deleted = deleted->left;

        }

        else {  // 삭제를 입력한 숫자 >>>> 입력된 데이터 값 인 경우 , if 오른쪽서브트리문을 수행할 예정.

            prev = deleted;

            deleted = deleted->right;

        }

    }



    if (deleted == NULL) {      // 노드에 입력 된 데이터 이외의 값을 입력하는 경우

        printf("삭제 하고자 하는 숫자가 존재 하지 않습니다\n");

        exit(1);

    }



    if (deleted->left) {   //왼쪽 서브 트리에서 조정 하는 경우 
        
        parent = deleted; // parent 변수의 기준

        move = deleted->left; // move 변수의 기준, parent에서 왼쪽 자식에게 접근

        while (move->right) // 삭제 트리 기준 왼쪽 서브 트리 중 가장 큰 숫자
        {
            parent = move; // move 주소를 parent 주소에 대입
            move = move->right; // move 노드를 move의 오른쪽 노드 주소로 변경 

        }

        if (parent == deleted) // (move노드의 오른쪽이 없는 경우)
         {
            parent->left = move->left; // 왼쪽노드가 새로운 parent이고 삭제될 부분을 대체한다.
        }
        else    // 그외의 경우 (오른쪽 노드가 있는 경우)
        {
            parent->right = move->left; // 오른쪽 노드가 새로운 parent이고 삭제될 부분을 대체한다.
        }
        deleted->item = move->item; //  새로운 parent 데이터를 노드에 copy한다 
        free(move); // copy한 move 숫자말고 기존의 원본 move 숫자 제거 
    }

    else  if (deleted->right) // 오른쪽 서브 트리에서 조정 
    {

        parent = deleted; // parent 변수 기준
       
        move = deleted->right; // move 변수의 기준 

        while (move->left) // 삭제 트리 기준 오른쪽 서브 트리 중 가장 작은 숫자 
        {
            parent = move;  // move가 parent가 된다.
            move = move->left; // move를 왼쪽자식으로 바꾼다.
        }
        if (parent == deleted)
        {
            parent->right = move->right; 
        }
        else
        {
            parent->left = move->right; 
        }
        deleted->item = move->item;
        free(move);
    }

    else  if (prev == NULL) {  // 마지막으로 하나 남은 노드 삭제 일 경우  

        free(deleted);

        *root = NULL;    // 공백 트리가 되었음을 알려 주는 부분  

    }
    else if (deleted == prev->left) {  // 왼쪽 단말 노드 삭제일 경우 

        prev->left = NULL;

        free(deleted);

    }

    else  if (deleted == prev->right) { // 오른쪽 단말 노드 삭제일 경우 

        prev->right = NULL;

        free(deleted);

    }

}


실행결과 
1번 누르고 아래 데이터 삽입 시 

70
30
50
60
5
40
90
100
95

3번 누르고 출력결과

5
30
40
50
60
70
90
95
100


2번 누르고 데이터 삭제 시 
하나하나씩 삭제 되는 것 확인.

구조체 변수를 이용하여 구조체 원소에 접근할 때는 도트연산자 .을 사용

포인터를 사용하여 구조체 원소에 접근할 때는 화살표 연산자(->) 사용 

#include <stdio.h>

struct GameInfo {
    char * name;
    int year;
    int price;
    char * company;

    struct GameInfo * friendGame; // 연관 업체 게임
};

int main(void)
{

// 구조체 사용 
struct GameInfo gameInfo1;
gameInfo1.name="나도게임";
gameInfo1.year=2017;
gameInfo1.price=50;
gameInfo1.company="나도회사";

struct GameInfo gameInfo2 = {"너도게임", 2017, 100, "너도회사"};

// 구조체 포인터
struct GameInfo * gamePtr; // 미션맨
gamePtr = &gameInfo1;
printf("\n\n-- 미션맨의 게임 출시 정보 --\n");
printf("  게임명  : %s\n", (*gamePtr).name);
printf("  발매년도  : %d\n", (*gamePtr).year);
printf("  가격  : %d\n", (*gamePtr).price);
printf("  제작사  : %s\n", (*gamePtr).company);

printf("\n\n-- 미션맨의 게임 출시 정보 --\n");
printf("  게임명  : %s\n", gamePtr->name);
printf("  발매년도  : %d\n", gamePtr->year);
printf("  가격  : %d\n", gamePtr->price);
printf("  제작사  : %s\n", gamePtr->company);

// 연관 업체 게임 소개 
gameInfo1.friendGame = &gameInfo2;

// 연관 업체의 게임 출시 정보
printf("\n\n-- 미션맨 친구의 게임 출시 정보 --\n");
printf("  게임명  : %s\n", gameInfo1.friendGame->name);
printf("  발매년도  : %d\n", gameInfo1.friendGame->year);
printf("  가격  : %d\n", gameInfo1.friendGame->price);
printf("  제작사  : %s\n", gameInfo1.friendGame->company);

}

실행결과 

-- 미션맨의 게임 출시 정보 --
  게임명  : 나도게임
  발매년도  : 2017
  가격  : 50
  제작사  : 나도회사


-- 미션맨의 게임 출시 정보 --
  게임명  : 나도게임
  발매년도  : 2017
  가격  : 50
  제작사  : 나도회사


-- 미션맨 친구의 게임 출시 정보 --
  게임명  : 너도게임
  발매년도  : 2017
  가격  : 100
  제작사  : 너도회사

 

 

도트연산자와 ( . ) 화살표연산자 ( -> ) 모두 접근이라는 의미로 사용된다. 

 

(*gamePtr).name       프린트하면 "나도게임"

gmaePtr -> name    프린트하면 "나도게임"

gameInfo1.friendgame-> name    프린트하면 "너도게임"

 

보통은 도트연산자 ( . )를 사용해서 맴버에 접근하지만

구조체 포인터의 맴버에 접근할 때는 화살표로 접근해야한다. 

+ Recent posts