profile image

L o a d i n g . . .

Unit 48. 구조체 사용하기

구조체는 struct 키워드로 정의하며 data structure(자료 구조)의 약어로 struct를 사용한다. 

구조체는 관련 정보를 하나의 의미로 묶을 때 사용한다.

 

48.1 구조체를 만들고 사용하기

struct 구조체이름 {
    자료형 멤버이름;
};

구조체는 struct 키워드로 정의한다.

구조체는 정의만 해서는 사용을 할 수가 없다. 따라서 구조체도 변수로 선언해서 사용한다.

  • struct 구조체이름 변수이름;
#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

struct Person {   // 구조체 정의
    char name[20];        // 구조체 멤버 1
    int age;              // 구조체 멤버 2
    char address[100];    // 구조체 멤버 3
};

int main()
{
    struct Person p1;     // 구조체 변수 선언

    // 점으로 구조체 멤버에 접근하여 값 할당
    strcpy(p1.name, "홍길동");
    p1.age = 30;
    strcpy(p1.address, "서울시 용산구 한남동");

    // 점으로 구조체 멤버에 접근하여 값 출력
    printf("이름: %s\n", p1.name);       // 이름: 홍길동
    printf("나이: %d\n", p1.age);        // 나이: 30
    printf("주소: %s\n", p1.address);    // 주소: 서울시 용산구 한남동

    return 0;
}

다음은 인적 정보를 표현하는 구조체이다.

구조체는 보통 main 함수 바깥에 정의하는데, 정의할 때 } (닫는 중괄호) 뒤에는 반드시 ; (세미콜론)을 붙여준다.

 

정의한 구조체를 사용하려면 구조체 변수를 선언해야 한다. 이때는 구조체 이름 앞에 반드시 struct 키워드를 붙여준다. 

그리고 일반 변수로 선언한 구조체의 멤버에 접근할 때는 . (점)을 사용한다.

 

+ 닫는 중괄호와 세미콜론 사이에 변수를 지정해주면 구조체를 정의하는 동시에 변수를 선언할 수 있다.

struct 구조체이름 {
    자료형 멤버이름;
} 변수;

 

+ 구조체 변수를 선언하는 동시에 값을 초기화하려면 중괄호 안에 . (점)과 멤버 이름을 적고 값을 할당한다.

  • struct 구조체이름 변수이름 = { .멤버이름1 = 값1, .멤버이름2 = 값2 };

 

 

48.2 typedef로 struct 키워드 없이 구조체 선언하기

typedef로 구조체를 정의하면서 별칭(alias)을 지정해주면 구조체 변수를 선언할 때 struct를 붙이지 않아도 된다.

typedef struct 구조체이름 {
    자료형 멤버이름;
} 구조체별칭;

 

typedef로 구조체의 별칭을 만들었다면 변수는 다음과 같이 선언한다.

  • 구조체별칭 변수이름;
#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

typedef struct _Person {   // 구조체 이름은 _Person
    char name[20];            // 구조체 멤버 1
    int age;                  // 구조체 멤버 2
    char address[100];        // 구조체 멤버 3
} Person;                  // typedef를 사용하여 구조체 별칭을 Person으로 정의

int main()
{
    Person p1;    // 구조체 별칭 Person으로 변수 선언

    // 점으로 구조체 멤버에 접근하여 값 할당
    strcpy(p1.name, "홍길동");
    p1.age = 30;
    strcpy(p1.address, "서울시 용산구 한남동");

    // 점으로 구조체 멤버에 접근하여 값 출력
    printf("이름: %s\n", p1.name);       // 이름: 홍길동
    printf("나이: %d\n", p1.age);        // 나이: 30
    printf("주소: %s\n", p1.address);    // 주소: 서울시 용산구 한남동

    return 0;
}

구조체를 정의할 때 맨 앞에 typedef를 붙여주고 구조체를 정의한다. 그리고 } (닫는 중괄호)와 ; (세미콜론) 사이에 구조체 별칭을 지정하면 된다. 

그리고 구조체 별칭을 정의했으므로 struct 키워드는 생략하고 구조체 별칭으로 바로 변수를 선언하면 된다.

 

 

48.3 익명 구조체 사용하기

익명 구조체(anonymous structure)를 사용하면 구조체 이름을 지정하지 않아도 된다. 즉, typedef로 구조체를 정의하면서 이름을 생략할 수 있다.

typedef struct {
    자료형 멤버이름;
} 구조체별칭;

 

변수는 구조체 별칭으로 선언하면 된다.

  • 구조체별칭 변수이름;
#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

typedef struct {   // 구조체 이름이 없는 익명 구조체
    char name[20];        // 구조체 멤버 1
    int age;              // 구조체 멤버 2
    char address[100];    // 구조체 멤버 3
} Person;          // typedef를 사용하여 구조체 별칭을 Person으로 정의

int main()
{
    Person p1;    // 구조체 별칭 Person으로 변수 선언

    // 점으로 구조체 멤버에 접근하여 값 할당
    strcpy(p1.name, "홍길동");
    p1.age = 30;
    strcpy(p1.address, "서울시 용산구 한남동");

    // 점으로 구조체 멤버에 접근하여 값 출력
    printf("이름: %s\n", p1.name);       // 이름: 홍길동
    printf("나이: %d\n", p1.age);        // 나이: 30
    printf("주소: %s\n", p1.address);    // 주소: 서울시 용산구 한남동

    return 0;
}

typedef struct 뒤에 이름을 지정하지 않고 바로 { (여는 중괄호)를 시작하면 된다. 단, 이때는 반드시 구조체 별칭을 지정해주어야 한다.

 

 

 

Unit 49. 구조체 포인터 사용하기

49.1 구조체 포인터를 선언하고 메모리 할당하기

다른 자료형과 마찬가지로 구조체도 포인터를 선언할 수 있으며 구조체 포인터에는 malloc 함수를 사용하여 동적 메모리를 할당할 수 있다.

  • struct 구조체이름 *포인터이름 = malloc(sizeof(struct 구조체이름));
#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

struct Person {    // 구조체 정의
    char name[20];        // 구조체 멤버 1
    int age;              // 구조체 멤버 2
    char address[100];    // 구조체 멤버 3
};

int main()
{
    struct Person *p1 = malloc(sizeof(struct Person));    // 구조체 포인터 선언, 메모리 할당

    // 화살표 연산자로 구조체 멤버에 접근하여 값 할당
    strcpy(p1->name, "홍길동");
    p1->age = 30;
    strcpy(p1->address, "서울시 용산구 한남동");

    // 화살표 연산자로 구조체 멤버에 접근하여 값 출력
    printf("이름: %s\n", p1->name);       // 홍길동
    printf("나이: %d\n", p1->age);        // 30
    printf("주소: %s\n", p1->address);    // 서울시 용산구 한남동

    free(p1);    // 동적 메모리 해제

    return 0;
}

먼저 struct Person *p1과 같이 struct 키워드와 구조체 이름을 사용하여 구조체 포인터를 선언한다. 이때 일반 변수가 아닌 포인터 변수이므로 반드시 *을 붙인다. 그리고 malloc 함수로 메모리를 할당할 때 크기를 알아야 하므로 sizeof(struct Person)과 같이 구조체 크기를 구하여 넣어준다.

 

+ 구조체 포인터의 멤버에 접근할 때는 -> (화살표 연산자)를 사용한다.

 

+ 마지막으로 free(p1);처럼 할당한 메모리를 해제해준다.

 

 

49.2 구조체 별칭으로 포인터를 선언하고 메모리 할당하기

 typedef로 정의한 구조체 별칭으로도 포인터를 선언하고 메모리를 할당할 수 있다.

  • 구조체별칭 *포인터이름 = malloc(sizeof(구조체별칭));
#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

typedef struct _Person {    // 구조체 이름은 _Person
    char name[20];             // 구조체 멤버 1
    int age;                   // 구조체 멤버 2
    char address[100];         // 구조체 멤버 3
} Person;                   // typedef를 사용하여 구조체 별칭을 Person으로 정의

int main()
{
    Person *p1 = malloc(sizeof(Person));    // 구조체 별칭으로 포인터 선언, 메모리 할당

    // 화살표 연산자로 구조체 멤버에 접근하여 값 할당
    strcpy(p1->name, "홍길동");
    p1->age = 30;
    strcpy(p1->address, "서울시 용산구 한남동");

    // 화살표 연산자로 구조체 멤버에 접근하여 값 출력
    printf("이름: %s\n", p1->name);       // 홍길동
    printf("나이: %d\n", p1->age);        // 30
    printf("주소: %s\n", p1->address);    // 서울시 용산구 한남동

    free(p1);    // 동적 메모리 해제

    return 0;
}

구조체 별칭을 사용하면 포인터를 선언하고 메모리를 할당하는 방법이 좀 더 간단하다. Person *p1과 같이 구조체 별칭으로 포인터를 바로 선언한 뒤 malloc 함수로 메모리를 할당한다. 이때 할당할 메모리 크기도 sizeof(Person)처럼 구조체 별칭으로 구하면 된다.

 

 

49.3 구조체 포인터에 구조체 변수의 주소 할당하기

지금까지 malloc 함수로 구조체 포인터에 동적 메모리를 할당했다. 그럼 동적 메모리를 할당하지 않고 구조체 포인터를 사용하는 방법은 없을까? 이때는 구조체 변수에 & (주소 연산자)를 사용하면 된다.

  • 구조체포인터 = &구조체변수;
#include <stdio.h>

struct Person {    // 구조체 정의
    char name[20];        // 구조체 멤버 1
    int age;              // 구조체 멤버 2
    char address[100];    // 구조체 멤버 3
};

int main()
{
    struct Person p1;      // 구조체 변수 선언
    struct Person *ptr;    // 구조체 포인터 선언

    ptr = &p1;    // p1의 메모리 주소를 구하여 ptr에 할당

    // 화살표 연산자로 구조체 멤버에 접근하여 값 할당
    ptr->age = 30;

    printf("나이: %d\n", p1.age);      // 나이: 30: 구조체 변수의 멤버 값 출력
    printf("나이: %d\n", ptr->age);    // 나이: 30: 구조체 포인터의 멤버 값 출력

    return 0;
}

구조체 변수는 주소 연산자 &를 사용하여 메모리 주소를 구할 수 있으며 이렇게 구한 메모리 주소는 구조체 포인터에 할당할 수 있다.

ptr은 구조체 포인터이므로 ->로 멤버에 접근하여 값을 할당하였다. 그리고 printf 함수로 p1의 멤버와 ptr의 멤버를 출력해보면 같은 값이 나오는 것을 알 수 있다.

 

 

Unit 50. 두 점 사이의 거리 구하기

이번에는 구조체를 활용하여 2차원 평면에서 위치를 표현한 뒤 두 점 사이의 거리를 구해보겠다.

두 점의 거리를 구하려면 피타고라스의 정리를 이용하면 된다.

  • 임의의 직각삼각형에서 빗변을 한 변으로 하는 정사각형의 넓이는 다른 두 변을 각각 한 변으로 하는 정사각형의 넓이의 합과 같다.
  • a2 + b2 = c2

 

이때 c의 길이를 계산하려면 제곱근을 구해야 한다.

그리고 √(루트)는 C 언어에서 제공하는 sqrt 함수를 사용하면 편리하다. sqrtmath.h 헤더 파일에 선언되어 있다.

  • sqrt(값)
#include <stdio.h>
#include <math.h>    // sqrt 함수가 선언된 헤더 파일

struct Point2D {
    int x;
    int y;
};

int main()
{
    struct Point2D p1;    // 점1
    struct Point2D p2;    // 점2

    // 점1 위치
    p1.x = 30;
    p1.y = 20;

    // 점2 위치
    p2.x = 60;
    p2.y = 50;

    int a = p2.x - p1.x;    // 선 a의 길이
    int b = p2.y - p1.y;    // 선 b의 길이

    double c = sqrt((a * a) + (b * b));    // (a * a) + (b * b)의 제곱근을 구함

    printf("%f\n", c);       // 42.426407

    return 0;
}

 

복사했습니다!