본문 바로가기
C/기초(두들낙서)

[C기초] 구조체 포인터, 구조체에 함수 집어넣기

by Meaning_ 2022. 1. 11.
728x90
반응형

구조체 포인터

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
struct ProductInfo {
    int num; 
    char name[100]; 
    int cost; 
};
 
 
 
int main() {
    
    ProductInfo myProduct = { 47900,"제주 한라봉",19900 };
    ProductInfo *ptr_product = &myProduct;
    
    printf("상품번호=%d\n", (*ptr_product).num);
    printf("상품이름=%s\n", (*ptr_product).name);
    printf("가격=%d\n", (*ptr_product).cost);
 
    
 
}
cs

 

 

구조체 포인터는 *ptr_prodcut인데 이걸 쓸때 주의점은 

printf("상품번호=%d\n", (*ptr_product).num); <-- 이 코드 처럼 괄호의 위치가 중요하다

그냥 *ptr_product.num을 하면 num은 포인터가 아닌데 별표를 붙이니까 에러가 뜬다.

(*ptr_product).num을 하게 되면 ptr_product가 가리키는 즉, myProduct.num과 똑같은 출력값을 가진다.

 

하지만(*ptr_product).num을 쓰면 쉬프트키를 여러번 누르게 되어 매우 불편하다 그래서 나온방식이

 

이런 화살표를 이용하는 방식이다. (*a).b 는 a->b와 같은 의미이다. 

 

이젠 좀더 심화해서 상품의 값을 할인해주는 함수를 따로 만들어보자 

productSale이라는 함수에 매개변수로 ProductInfo와 할인되는 퍼센트를 넣어줄거다 

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
#include <stdio.h>
 
struct ProductInfo {
    int num; 
    char name[100]; 
    int cost; 
};
 
//할인해주는 함수
 
void productSale(ProductInfo p, int percent) {
    p.cost -= p.cost * percent / 100; ;//call by value여서 가격 안바뀜
}
 
int main() {
    
    ProductInfo myProduct = { 47900,"제주 한라봉",20000 };
    ProductInfo *ptr_product = &myProduct;
    
    productSale(myProduct, 10);
    
    printf("상품번호=%d\n", ptr_product->num);
    printf("상품이름=%s\n", (*ptr_product).name);
    printf("가격=%d\n", (*ptr_product).cost);
 
    
 
}
cs

 

가격이 할인되지 않고 그대로인 것을 알 수 있다.

그 이유는 productSale 함수가 call-by value이기 때문이다. 이걸 해결하기 위해서 포인터를 사용해줄거다 

call-by reference로 바꾸면

 

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
#include <stdio.h>
 
struct ProductInfo {
    int num; 
    char name[100]; 
    int cost; 
};
 
//할인해주는 함수
 
void productSale(ProductInfo *p, int percent) {
    (*p).cost -= p->cost * percent / 100
}

int main() {
    
    ProductInfo myProduct = { 47900,"제주 한라봉",20000 };
    ProductInfo *ptr_product = &myProduct;
    
    productSale(&myProduct, 10);
    
    printf("상품번호=%d\n", ptr_product->num);
    printf("상품이름=%s\n", (*ptr_product).name);
    printf("가격=%d\n", (*ptr_product).cost);
 
    
 
}
cs

 

 

가격이 바뀐 것을 알 수 있다.

 

11번째부터 13번째 줄 코드

void productSale(ProductInfo *p, int percent) {

 

    (*p).cost -= p->cost * percent / 100; //p->cost-=p->cost*percent/100;

 

}
 
--> 여기를 자세히보면 myProduct의 주소값을 받아와서 구조체 포인터를 사용하는 것을 확인할 수 있다.

 

구조체에 함수 집어넣기

시간과 분을 모두 초 단위로 바꿔주는 프로그램을 만들려한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
struct Time {
    int h, m, s;
};
 
int totalSec(Time t) {
    return 3600 * t.h + 60 * t.m + t.s;
}
 
int main() {
    Time t = { 1,22,48 };
 
    printf("%d\n", totalSec(t));
}
cs

Time구조체와 totalSec 함수는 밀접한 연관이 있기 때문에 둘을 합쳐주려 한다.

합쳐줬을 때 totalSec는 Time 구조체의 멤버 함수라 부른다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
struct Time {
    int h;
    int m;
    int s;
    int totalSec() {
        return 3600 * h + 60 * m + s;
    }
 
};
 
int main() {
    Time t;
    printf("%d\n", t.totalSec());
}
cs

totalSec의 return값에서 구조체의 이름 없이 (t.h)이런거 없이 그냥 h만 써줘도 된다. 어차피 Time 안의 멤버함수가 되었기 때문에 같은 구조체의 멤버변수인 h도 바로 쓸 수 있는 것이다. 

 

 

 

구조체에 함수를 집어넣은 예시 2

x,y좌표를 상하좌우로 움직여주는 함수 4개를 만들어봤다.

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 x;
    int y;
    
    void moveRight() {
        x++;
    }
    void moveLeft() {
        x--;
    }
    void moveUp() {
        y++;
    }
    void moveDown() {
        y--;
    }
 
};
 
int main() {
    Point p = { 4,5 };
    p.moveDown();
    p.moveLeft();
    printf("%d,%d\n", p.x, p.y);
}
cs

 

출력값은 3,4가 나온다.

구조체 연습문제

1. 출력값을 구하시오

 

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
typedef int Point[2];
typedef Point *PointPtr;
 
int main() {
    Point p = { 3,4 }; 
    PointPtr pp = &p; 
    printf("%d %d %d"**pp, (*pp)[0], (*pp)[1]);
    
}
 
cs

 

Point p={3,4} 는 사실상 int p[2]={3,4};

Pointptr pp=&p는 Point *pp=&p; 이다.

 

**pp는 *(*pp)로 생각해줄 수 있는데 , pp가 배열을 가리키는 포인터인 배열포인터이다.

그래서 *pp가 가리키는 값은 p이고, 최종적으로 *p만 구하면 되는데 이는 *(p+0)인데 이는 p[0]이기 때문에 첫번째 출력값은 3이다.

 

(*pp)[0]을 보면 *pp는 p를 가리키기 때문에 p[0]이므로 두번째 출력값도 3이다.

 

 

(*pp)[1]은 p[1]이기 때문에 세번째 출력값은 4이다.

 

 

2. x와 y값이 swap되도록 함수를 구현해라

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
struct Point {
    int x, y;
};
 
 
 
int main() {
    Point pos = { 3,4 };
    
    printf("%d,%d", pos.x, pos.y);
}
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
struct Point {
    int x, y;
};
 
void pSwap(Point *p) {
    int tmp = (*p).x;
    p->= p->y;
    p->= tmp;
}
 
int main() {
    Point pos = { 3,4 };
    pSwap(&pos);
    printf("%d,%d", pos.x, pos.y);
}
cs

 

cf) swap함수를 구조체안에 넣으면?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
 
struct Point {
    int x, y;
    void pSwap() {
        int tmp = x;
        x = y;
        y = tmp;
    }
};
 
 
 
int main() {
    Point pos = { 3,4 };
    pos.pSwap();
    printf("%d,%d", pos.x, pos.y);
}
 
cs

 

나는 pos.pswap(&pos) void pswap(Point *p)를 했는데 굳이 그렇게 할 필요없었다. 물론 둘다 출력값은 같게 나옴 

728x90
반응형

댓글