구조체 사용하기

  • 55 minutes to read

하나의 이름으로 서로 다른 데이터 타입을 묶어서 관리해주는 구조체에 대해서 살펴보겠습니다.

> // 구조체(Struct): 하나의 이름으로 서로 다른 데이터들을 묶어 관리하는 데이터 구조

C 언어에서의 구조체 사용하기: Point 예제

"구조체(structure)"는 여러 개의 변수를 하나의 새로운 타입으로 묶어 사용할 수 있는 데이터 구조입니다. 구조체를 사용하면 관련된 데이터를 그룹으로 묶어 저장하고 관리하기 편리해집니다.

구조체를 선언하려면, 먼저 구조체 타입을 정의한 후에 구조체 변수를 선언해야 합니다. 구조체 타입은 struct 키워드를 사용하여 정의하며, 구조체 변수는 구조체 타입의 이름을 사용하여 선언할 수 있습니다.

구조체는 다음과 같이 정의합니다.

struct structure_name 
{
   type member1;
   type member2;
   .
   .
   type member_n;
};

위와 같이 구조체를 정의하면, structure_name이라는 새로운 자료형이 생성됩니다. 구조체의 각 멤버는 member1, member2, ... 입니다. 구조체 안의 각각의 변수들을 멤버 변수라고 합니다.

예를 들어, Point 구조체를 정의해보겠습니다:

struct Point 
{
    int x; // x 좌표 값
    int y; // y 좌표 값
};

Point 구조체는 다음 그림과 같은 형태를 가지고 있습니다.

       Point 구조체
  ┌─────────────────┐
  │        x        │
  ├─────────────────┤
  │        y        │
  └─────────────────┘

새로운 자료형으로 정의된 구조체는 다음과 같이 변수를 선언하여 사용할 수 있습니다.

struct Point p1;

구조체의 멤버에 접근하려면 점(.) 연산자를 사용합니다.

p1.x = 10;
p1.y = 20;

다음은 구조체를 사용한 예제입니다.

코드: point_example.c

#include <stdio.h>

struct Point
{
    int x;
    int y;
};

int main(void)
{
    struct Point p1;

    p1.x = 10;
    p1.y = 20;

    printf("(%d, %d)\n", p1.x, p1.y);

    return 0;
}
(10, 20)

위의 예제에서는 구조체 Point를 정의하였으며, 구조체 변수 p1을 선언하여 사용했습니다. 구조체의 멤버 변수에 접근하려면 구조체 변수의 이름과 멤버 변수의 이름을 점(.) 연산자로 연결하여 사용할 수 있습니다. 예를 들어, p1.xp1.y는 구조체 변수 p1x, y 멤버 변수에 접근하는 것입니다.

구조체 변수를 선언할 때, 구조체 내부의 멤버 변수에 값을 할당할 수도 있습니다. 예를 들어, 다음과 같이 구조체 변수를 선언할 수 있습니다:

struct Point p2 = {30, 40};

구조체는 함수의 매개변수로 전달하거나, 함수의 반환 값으로 사용할 수도 있습니다.

구조체는 유연한 데이터 구조를 제공하여, 복잡한 데이터 관리에 매우 유용한 기능입니다. 여러 개의 데이터 항목을 관리하는데 효율적으로 사용할 수 있습니다.

구조체 정의, 변수 선언 및 별칭 사용

이번에는 구조체를 정의하고 변수를 선언하는 방법에 대해 다룹니다. 또한, typedef 키워드를 사용하여 구조체의 별칭을 지정하는 방법과 익명 구조체를 정의하는 방법을 살펴봅니다.

구조체 정의와 변수 선언

앞서 살펴본 것처럼 구조체를 선언하는 가장 기본적인 방법은 다음과 같습니다.

struct Point 
{
    int x;
    int y;
};

이렇게 정의한 후에, 구조체 변수를 선언할 수 있습니다.

struct Point p1;

하지만, 구조체 선언과 구조체 변수 선언을 한 번에 할 수도 있습니다.

struct Point 
{
    int x;
    int y;
} p1;

구조체의 멤버 변수를 한 줄에 선언할 수도 있지만, 권장되지는 않습니다.

struct Point 
{
    int x, y;
};

변수를 선언하고 초기화하는 방법에는 여러 가지가 있습니다.

struct Point p1; // 구조체 변수 선언
struct Point p1 = {3, 10}; // 초기화 가능
struct Point p1 = {.y = 10, .x = 3}; // C99 도입, 순서 없이 멤버 지정으로 초기화 가능
struct Point p2 = {.x = 10}; // C99, 부분 초기화도 가능. C++에서는 동작 안 함.

typedef 키워드와 구조체 별칭

typedef 키워드를 사용하는 간단한 예제는 다음과 같습니다.

코드: integer_example.c

#include <stdio.h>

// int 타입의 별칭으로 integer를 정의합니다.
typedef int integer;

int main(void)
{
    // integer 타입의 변수 a를 선언하고 10으로 초기화합니다.
    integer a = 10;

    // 변수 a의 값을 출력합니다.
    printf("a = %d\n", a); // a = 10

    return 0;
}
a = 10

위의 코드에서 typedef int integer;integer 타입을 int 타입으로 정의합니다. 이렇게 정의한 후, integer 타입으로 변수를 선언할 수 있습니다. 예제에서는 integer a = 10;처럼 integer 타입의 변수 a를 선언하였습니다.

C 언어에서 구조체를 별칭으로 정의하는 간단한 예제는 다음과 같습니다:

코드: point_example_typedef.c

#include <stdio.h>

// point 구조체 선언
struct point
{
    int x; // x 좌표를 저장하는 정수형 변수
    int y; // y 좌표를 저장하는 정수형 변수
};

// struct point를 Point로 별칭(alias) 지정
typedef struct point Point;

int main(void)
{
    Point p1; // Point 구조체 변수 p1 선언

    p1.x = 10; // p1의 x 좌표에 10 할당
    p1.y = 20; // p1의 y 좌표에 20 할당

    // p1의 x, y 좌표 출력
    printf("(%d, %d)\n", p1.x, p1.y);

    return 0;
}
(10, 20)

위 예제에서는 구조체 point를 정의한 후, typedef 키워드와 struct 키워드를 사용하여 구조체 point의 별칭인 Point를 정의하였습니다. 이제 Point 타입을 사용하여 구조체 변수를 선언할 수 있습니다.

별칭을 정의하면 구조체 이름이 길거나 복잡할 때, 코드의 가독성을 높일 수 있습니다.

typedef를 사용한 익명 구조체

typedef를 사용하여 익명 구조체를 정의하면, 구조체의 이름을 명시하지 않고도 구조체를 사용할 수 있습니다. 이를 통해 코드가 간결해지며 가독성이 향상됩니다. 아래 예제는 typedef를 사용한 익명 구조체를 정의하고 사용하는 방법을 보여줍니다.

코드: anonymous_structure.c

#define _CRT_SECURE_NO_WARNINGS // Visual Studio의 보안 경고를 무시하기 위한 매크로 정의
#include <stdio.h>
#include <string.h> // 문자열 관련 함수를 사용하기 위해 string.h 헤더 파일 포함

// Person 구조체 정의
typedef struct
{
    char name[100]; // 이름을 저장할 문자 배열
    int age;        // 나이를 저장할 정수형 변수
} Person;

int main(void)
{
    Person person; // Person 구조체 변수 person 선언

    // person의 이름 필드에 "John Doe"를 복사
    strcpy(person.name, "John Doe");
    person.age = 30; // person의 나이 필드에 30 할당

    // person의 이름과 나이 출력
    printf("Name: %s\n", person.name);
    printf("Age: %d\n", person.age);

    return 0; 
}
Name: John Doe
Age: 30

위의 코드에서 typedef struct {...} Person; 부분이 익명 구조체를 정의하고, 이를 Person이라는 별칭으로 사용할 수 있게 합니다. 이후 Person 타입의 변수를 선언하고 멤버에 접근할 수 있습니다.

구조체와 scanf 함수 사용하기

아래 코드는 구조체를 사용하여 이름과 나이를 입력받고 출력하는 예제입니다.

코드: person_info.c

#define _CRT_SECURE_NO_WARNINGS // Visual Studio의 보안 경고를 무시
#include <stdio.h>

// person 구조체 정의
struct person
{
    char name[20]; // 이름을 저장할 문자 배열
    int age;       // 나이를 저장할 정수형 변수
};

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

    // 이름 입력 받기
    printf("이름을 입력하세요: ");
    scanf("%s", p1.name);

    // 나이 입력 받기
    printf("나이를 입력하세요: ");
    scanf("%d", &p1.age);

    // 입력받은 이름과 나이 출력하기
    printf("이름: %s\n", p1.name);
    printf("나이: %d\n", p1.age);

    return 0;
}
이름을 입력하세요: Lisa
나이를 입력하세요: 21
이름: Lisa
나이: 21
+--------------+
| person 구조체 |
+--------------+
|              |
| name: "Lisa" |
|              |
| age: 21      |
|              |
+--------------+

이 예제에서는 person이라는 구조체를 정의하고, 구조체 변수 p1을 선언하여 구조체 내부의 멤버 변수인 nameage에 값을 입력받습니다.

구조체 멤버에 값을 저장할 때도 scanf를 사용할 수 있습니다.

예제에서는 문자열을 입력받기 위해 %s 서식 지정자를 사용하며, p1.name이 배열이기 때문에 &를 사용하지 않고 그대로 scanf 함수의 인자로 전달합니다.

정수를 입력받기 위해 %d 형식 지정자를 사용하고, p1.age는 정수형 변수이므로 주소를 전달하기 위해 &를 사용합니다.

scanf 함수를 통해 구조체 멤버에 값을 쉽게 저장할 수 있어 사용자 입력을 효과적으로 관리할 수 있습니다.

C# 교과서 22장 구조체 사용하기 동영상 강의

C 언어 강의가 완료되면 C# 강의에서 C 언어 강의로 대체됩니다. 다만, 개념은 동일하기에 C 언어를 학습하고 있어도 맛보기로 보는 걸 추천합니다.

구조체 소개

구조체(Struct)는 하나의 데이터 묶음을 하는 레코드 역할을 합니다.

앞서 배운 변수는 하나의 이름으로 하나의 공간을 갖고, 배열은 하나의 이름으로 동일한 데이터 타입을 갖는 여러 개의 공간을 갖습니다.

변수와 배열을 확장하여 하나의 이름으로 여러 개의 데이터 타입을 한 개 또는 여러 개 보관하는 그릇 역할을 하는 것이 바로 구조체(Struct)입니다.

구조체는 int, char[] 등의 서로 다른 자료를 하나의 집단으로 정의하여 하나의 이름으로 지정할 수 있는 여러 항목들의 모임으로, 데이터베이스에서 말하는 레코드(Record) 개념으로 볼 수 있습니다.

구조체 변수란 하나의 이름으로 하나 이상의 데이터 타입을 하나 보관해 놓는 그릇 역할이고, 구조체 배열은 하나의 이름으로 하나 이상의 데이터 타입을 여러 개 보관해 놓는 그릇 역할을 하는 것으로 볼 수 있습니다.

구조체 만들기

구조체를 만드는 방법은 다음과 같습니다. 구조체를 의미하는 struct 키워드를 사용하여 구조체를 만들고 중괄호 안에 구조체의 멤버들을 생성할 수 있습니다.

struct 구조체명
{
    데이터타입 변수1;
    데이터타입 변수2;
    데이터타입 변수3; 
};

위에서 구조체명은 새로운 데이터 타입이 되며, 변수를 선언할 때 구조체 이름을 사용할 수 있습니다. 구조체를 가리켜 사용자 정의 데이터 타입으로 부르기도 합니다.

구조체를 사용하여 하나 이상의 변수 또는 배열을 묶어서 관리

구조체를 사용하여 하나 이상의 변수를 묶어서 사용하는 방법에 대해서 예제로 먼저 살펴보겠습니다.

다음 예제 코드는 Point 이름으로 X와 Y를 담을 수 있는 구조체를 만들고 값을 저장 후 이를 다시 출력하는 내용입니다.

코드: StructDemo.c, struct_demo.c

//[?] 구조체: 하나 이상의 변수 또는 배열을 묶어서 관리
#include <stdio.h>

struct Point
{
    int X;
    int Y;
};

int main(void)
{
    struct Point point; // Point 구조체 형식의 변수 선언
    point.X = 100; // 점을 구분해서 X 변수에 값을 할당
    point.Y = 200; // 점을 구분해서 Y 변수에 값을 할당
    printf("X: %d, Y: %d\n", point.X, point.Y); // X: 100, Y: 200

    return 0;
}
X: 100, Y: 200

구조체를 선언할 때에는 struct 키워드를 사용합니다. struct Point {}; 형태로 Point 이름의 구조체를 만듭니다.

만들어진 구조체는 int, char 형식의 변수 선언과 동일한 방법으로 선언 후 사용할 수 있습니다.

다만, 변수와의 차이점은 변수는 하나의 값만 저장하는 대신에 구조체는 점(.)을 구분으로 구조체 선언 시 사용한 여러 개의 변수를 하나의 이름(point)으로 묶어서 사용할 수 있는 장점을 가집니다.

이처럼 구조체를 사용하면 하나의 이름으로 여러 데이터를 저장하여 사용할 수 있습니다.

구조체 사용하기

아래는 구조체를 사용한 간단한 예제입니다:

#include <stdio.h>

struct person {
    char name[20];
    int age;
};

int main() {
    struct person p1;

    printf("이름을 입력하세요: ");
    scanf("%s", p1.name);

    printf("나이를 입력하세요: ");
    scanf("%d", &p1.age);

    printf("이름: %s\n", p1.name);
    printf("나이: %d\n", p1.age);

    return 0;
}

위 예제에서는 구조체 person을 정의하였으며, 구조체 변수 p1을 선언하여 구조체 내부의 멤버 변수인 name과 age에 값을 입력받습니다. 그리고 입력받은 값을 출력합니다.

변수, 배열, 구조체 비교

코드: struct_description.c, StructDescription.c

// 구조체(Structure;Struct): 하나의 이름으로 서로 다른 데이터 타입을 묶어서 관리
#include <stdio.h>

//[!] 구조체 선언: 회원 관리
struct Member
{
    char* Name; // 이름
    int Age; // 나이
    double Weight; // 몸무게
};

int main(void)
{
    //[1] 변수(Variable): 하나의 이름으로 하나의 데이터 타입을 하나만 보관해 놓는 그릇
    int num = 10;

    //[2] 배열(Array): 하나의 이름으로 동일한 데이터 타입을 하나 이상 보관
    int data[5] = { 10, 20, 30, 40, 50 };

    //[3] 구조체(Struct) 
    struct Member objMember;	//[a] 구조체 형식의 변수 선언
    objMember.Name = "홍길동";	//[b] 구조체 각각의 멤버 변수(Member)를 초기화
    objMember.Age = 21;
    objMember.Weight = 100.05;
    printf("이름: %s, 나이: %d, 몸무게: %.2f\n",
        objMember.Name, objMember.Age, objMember.Weight); //[c] 구조체 참조

    return 0;
}
이름: 홍길동, 나이: 21, 몸무게: 100.05

구조체 선언, 초기화, 참조

코드: 구조체_member.c

// 구조체 : 서로 다른 데이터형식을 하나의 이름으로 묶어서 관리
#include <stdio.h>

// 구조체 선언 : 새로운 데이터 형식인 member 형을 선언
struct member
{
	char* name;		// 이름
	int		age;		// 나이
	long	money;		// 연봉
};

int main(void)
{
	// 구조체 형 변수 선언 : 개체의 인스턴스 생성(C#/C++)
	struct member m;

	// 구조체의 각각의 멤버를 초기화
	m.name = "박용준";
	m.age = 21;
	m.money = 2100000000; // 21억

	// 구조체 참조
	printf("이름 : %s, 나이 : %d, 연봉 : %ld원\n", m.name, m.age, m.money);
}
이름 : 박용준, 나이 : 21, 연봉 : 2100000000원

구조체 선언과 동시에 초기화

코드: StructInitializer.c

#include <stdio.h>

//[?] 구조체 선언: 회원 관리
struct Member
{
    char* Name;	// 이름
    int		Age; // 나이
    double	Weight;	// 몸무게
} objMember = { "백두산", 100, 70.05 };

int main(void)
{
    //[!] 구조체(Struct) 참조 
    printf("이름: %s, 나이: %d, 몸무게: %.2f\n",
        objMember.Name, objMember.Age, objMember.Weight);

    return 0;
}
이름: 백두산, 나이: 100, 몸무게: 70.05

typedef 키워드

C 언어에서 typedef 키워드를 사용하는 간단한 예제는 다음과 같습니다.

#include <stdio.h>

typedef int integer;

int main() {
  integer a = 10;
  printf("a = %d\n", a);
  return 0;
}

위의 코드에서 typedef int integer;integer 타입을 int 타입으로 정의합니다. 이렇게 정의한 후, integer 타입으로 변수를 선언할 수 있습니다. 예제에서는 integer a = 10; 처럼 integer 타입의 변수 a를 선언하였습니다.

구조체 별칭

C 언어에서 구조체를 별칭으로 정의하는 간단한 예제는 다음과 같습니다:

#include <stdio.h>

struct point {
    int x;
    int y;
};

typedef struct point Point;

int main() {
    Point p1;

    p1.x = 10;
    p1.y = 20;

    printf("(%d, %d)\n", p1.x, p1.y);
    return 0;
}

위 예제에서는 구조체 point를 정의한 후, typedef 키워드와 struct 키워드를 사용하여 구조체 point의 별칭인 Point를 정의하였습니다. 이제 Point 타입을 사용하여 구조체 변수를 선언할 수 있습니다.

별칭을 정의하면 구조체 이름이 길거나 복잡할 때, 코드의 가독성을 높일 수 있습니다.

typedef를 사용한 익명 구조체

C 언어에서 typedef를 사용한 익명 구조체를 정의하고 사용하는 예제는 다음과 같습니다.

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

typedef struct {
  char name[100];
  int age;
} Person;

int main() {
  Person person;
  strcpy(person.name, "John Doe");
  person.age = 30;
  printf("Name: %s\n", person.name);
  printf("Age: %d\n", person.age);
  return 0;
}

위의 코드에서 typedef struct {...} Person;Person 타입의 익명 구조체를 정의합니다. 이렇게 정의한 후, Person 타입으로 변수를 선언할 수 있습니다. 예제에서는 Person person; 처럼 Person 타입의 변수 person을 선언하였습니다.

C 언어에서 구조체를 사용한 회원 정보 표시

이 글에서는 C 언어에서 구조체를 사용해 회원 정보를 저장하고 표시하는 방법을 보여드립니다. 예제 프로그램의 이름은 member_info_struct.c입니다.

소스 코드: member_info_struct.c

예제 프로그램의 전체 소스 코드는 다음과 같습니다:

/*
    구조체를 사용한 회원 정보 : member_info_struct.c 
*/
#include <stdio.h>

// 구조체 선언
typedef struct member
{
	char *name;
	char *addr;
	char *birth;
	char *tel;
} Member;

int main()
{
	// 구조체 형 변수 선언
	Member objMember;

	// 구조체 초기화
	objMember.name = "지호";
	objMember.addr = "서울";
	objMember.birth = "050527";
	objMember.tel = "114";

	// 구조체 참조
	printf("이름: %s\n", objMember.name);
	printf("주소: %s\n", objMember.addr);
	printf("생년월일: %s\n", objMember.birth);
	printf("전화번호: %s\n", objMember.tel);

	return 0;
}
이름: 지호
주소: 서울
생년월일: 050505
전화번호: 114

코드 설명

  1. typedef struct member를 사용하여 회원 정보를 저장할 구조체를 정의합니다. 이 구조체에는 이름, 주소, 생년월일, 전화번호를 저장하는 문자열 포인터 변수가 포함되어 있습니다.

  2. main() 함수에서 Member 타입의 변수 objMember를 선언합니다.

  3. objMember 변수의 각 필드를 초기화합니다. 문자열은 이 예제에서 직접 대입되지만, 실제 상황에서는 사용자로부터 입력을 받거나 파일에서 읽어올 수 있습니다.

  4. printf() 함수를 사용하여 objMember의 각 필드를 출력합니다.

이 프로그램은 구조체를 사용하여 회원 정보를 저장하고 출력하는 간단한 예제입니다. 구조체를 사용하면 관련 데이터를 그룹화하여 코드를 더 직관적이고 관리하기 쉽게 만들 수 있습니다.

구조체 배열

구조체에도 배열을 사용할 수 있습니다. 다음과 같이 구조체 배열을 사용하여 1000개의 명함구조체를 만들 수 있습니다.

명함구조체 명함배열[1000];

만들어진 구조체 배열은 다음과 같이 0번째 인덱스부터 999번째 인덱스까지 배열을 사용하여 이름, 주소, 전화번호 멤버에 접근해서 값을 할당하거나 값을 참조해서 사용할 수 있습니다.

이름 주소 전화번호
명함배열[0].이름 명함배열[0].주소 명함배열[0].전화번호
... ... ...
... ... ...
... ... ...
명함배열[999].이름 명함배열[999].주소 명함배열[999].전화번호

구조체 배열 선언하기

C 언어에서 구조체 배열을 선언하는 예제는 다음과 같습니다.

#include <stdio.h>

typedef struct {
  char name[100];
  int age;
} Person;

int main() {
  Person people[3];
  strcpy(people[0].name, "John Doe");
  people[0].age = 30;
  strcpy(people[1].name, "Jane Doe");
  people[1].age = 25;
  strcpy(people[2].name, "Jim Doe");
  people[2].age = 40;
  for (int i = 0; i < 3; i++) {
    printf("Name: %s\n", people[i].name);
    printf("Age: %d\n", people[i].age);
  }
  return 0;
}

위의 코드에서 Person people[3];Person 타입의 배열 people을 정의합니다. 그리고 각 요소에 접근할 때는 [i] 연산자를 사용합니다. for 루프를 사용하여 배열의 각 요소에 접근하여 값을 설정하고 출력할 수 있습니다.

구조체 배열을 사용해서 데이터 대입 및 출력하기

이번에는 변수와 배열을 사용할 때 이미 알고 있는 데이터 타입을 사용하지 않고 새롭게 만든 데이터 타입, 즉 구조체를 만들어 그 구조체 형식 변수 및 배열을 사용하는 방법을 알아보겠습니다.

코드: StructArray.c

#include <stdio.h>

//[!] 구조체 선언: 회원 관리
struct Member
{
    char* Name;	// 이름
    int		Age;	// 나이
    double	Weight;	// 몸무게
};

int main(void)
{
    int i;

    //[1] 구조체 배열 선언
    struct Member m[3]; // Member 형식이 3개가 준비

    //[2] 초기화
    m[0].Name = "홍길동";
    m[0].Age = 21;
    m[0].Weight = 100.05;

    m[1].Name = "백두산";
    m[1].Age = 100;
    m[1].Weight = 70.05;

    m[2].Name = "임꺽정";
    m[2].Age = 40;
    m[2].Weight = 150.05;

    //[3] 참조
    for (i = 0; i < 3; i++)
    {
        printf("%s, %3d, %6.2f\n", m[i].Name, m[i].Age, m[i].Weight);
    }

    return 0;
}
홍길동,  21, 100.05
백두산, 100,  70.05
임꺽정,  40, 150.05

Member 구조체를 사용하여 변수와 배열을 만들어 보았습니다.

구조체 배열 선언과 동시에 초기화

코드: StructArrayInitializer.c

#include <stdio.h>

//[!] 구조체 선언: 회원 관리
struct Member
{
    char* Name;	// 이름
    int		Age; // 나이
    double	Weight; // 몸무게
};

int main(void)
{
    //[1][2] 구조체 배열 선언과 동시에 초기화
    struct Member m[] =
    {
        {"홍길동", 21, 100.05}, {"백두산", 100, 70.05}, {"임꺽정", 40, 150.00}
    };

    //[3] 참조
    for (int i = 0; i < 3; i++)
    {
        printf("%s, %3d, %6.2f\n", m[i].Name, m[i].Age, m[i].Weight);
    }

    return 0;
}
홍길동,  21, 100.05
백두산, 100,  70.05
임꺽정,  40, 150.00

코드: 구조체_구조체배열.c

#include <stdio.h>

// 구조체 선언
struct member
{
	char* name;		// 이름
	int		age;		// 나이
	long	money;		// 연봉
};

int main(void)
{
	int i;

	//// 구조체 배열 선언
	//struct member objMembers[3];

	//// 구조체 배열 초기화
	//objMembers[0].name = "홍길동";
	//objMembers[0].age = 21;
	//objMembers[0].money = 1000;;

	//objMembers[1].name = "백두산";
	//objMembers[1].age = 31;
	//objMembers[1].money = 2000;;

	//objMembers[2].name = "임꺽정";
	//objMembers[2].age = 41;
	//objMembers[2].money = 3000;;

	// 구조체 배열 선언과 동시에 초기화
	struct member objMembers[] = {
		{"홍길동", 21, 1000}, {"백두산", 31, 2000}, {"임꺽정", 41, 3000}
	};

	// 출력
	for (i = 0; i < 3; i++)
	{
		printf("%8s %2d %4ld\n", objMembers[i].name, objMembers[i].age, objMembers[i].money);
	}
}
  홍길동 21 1000
  백두산 31 2000
  임꺽정 41 3000

[!INCLUDE 중첩 구조체 사용하기)]

중첩 구조체를 사용하여 성적 리스트 출력

이 글에서는 C 언어에서 중첩 구조체를 사용하여 성적 리스트를 출력하는 방법을 소개합니다. 아래 코드는 struct_practice.c 또는 StructPractice.c 파일로 작성됩니다.

코드: struct_practice.c, StructPractice.c

#include <stdio.h>

// 점수 구조체 선언
struct score {
    int kor; int eng;
};

// 학생 구조체 선언
struct student {
    int num;
    struct score scores;
};

int main(void)
{
    // 구조체 배열 선언과 동시에 초기화 
    struct student s[3] = { {1, {100, 90}}, {2, {90, 80}}, {3, {80, 70}} };

    // for 문으로 구조체 배열 참조
    for (int i = 0; i < 3; i++)
    {
        printf("%d: %3d, %3d\n", s[i].num, s[i].scores.kor, s[i].scores.eng);
    }

    return 0; 
}

이 코드를 실행하면 다음과 같은 출력 결과가 나옵니다.

1: 100,  90
2:  90,  80
3:  80,  70

본 예제에서는 점수 구조체를 선언하여 국어와 영어 성적을 저장하고, 학생 구조체를 선언하여 학생 번호와 점수 구조체를 포함시켰습니다. s[i].num, s[i].scores.kor, 그리고 s[i].scores.eng 코드를 사용하여 구조체 배열의 각 요소를 참조합니다. s[i].num은 학생 구조체의 학생 번호를 가져오는 데 사용되며, s[i].scores.kor는 국어 성적, 그리고 s[i].scores.eng는 영어 성적을 가져옵니다. 이렇게 각 구조체 요소를 참조하면서 for 문을 사용해 성적 리스트를 출력합니다. 이를 통해 중첩 구조체를 사용하여 데이터를 효율적으로 관리할 수 있습니다.

C 언어에서 중첩 구조체 사용하기

이 글에서는 C 언어에서 중첩 구조체를 사용해 회원 정보와 점수 정보를 저장하고 출력하는 방법을 보여드립니다. 예제 프로그램의 이름은 nested_struct_example.c입니다.

소스 코드: nested_struct_example.c

예제 프로그램의 전체 소스 코드는 다음과 같습니다:

/*
	중첩 구조체 : nested_struct_example.c
*/
#include <stdio.h>

typedef struct Subject
{
	int Kor;
	int Eng;
} Subject;

typedef struct Member
{
	int Num;
	char Name[25];
	Subject Score;
} Member;

int main()
{
	Member objMember = { 1, "홍길동", {100, 80} };

	Member* p;
	p = &objMember;

	printf("번호: %d\n", objMember.Num);
	printf("이름: %s\n", objMember.Name);
	printf("국어점수: %d\n", objMember.Score.Kor);
	printf("영어점수: %d\n", p->Score.Eng);

	return 0;
}
번호: 1
이름: 홍길동
국어점수: 100
영어점수: 80

코드 설명

Subject 구조체는 국어 점수와 영어 점수를 저장하기 위한 두 개의 정수형 변수를 포함합니다. Member 구조체는 회원 번호, 이름, 그리고 Subject 구조체를 이용한 점수 정보를 담습니다. 이렇게 중첩 구조체를 활용하면 관련 정보를 그룹화하여 코드를 더 명확하고 관리가 쉬워집니다.

main() 함수에서는 Member 타입의 변수 objMember를 선언하고 초기화합니다. 또한, Member 구조체 포인터 p를 선언한 후 objMember의 주소를 대입합니다. printf() 함수를 사용하여 objMember의 각 필드를 출력하며, 영어 점수는 포인터 p를 이용해 출력합니다.

이 프로그램은 중첩 구조체를 사용하여 회원 정보와 점수 정보를 저장하고 출력하는 간단한 예제를 보여줍니다. 중첩 구조체를 사용함으로써 코드의 가독성과 유지 보수성이 향상됩니다.

구조체 비트 필드

코드: 구조체비트필드.c

#include <stdio.h>

struct A
{
	int a : 8; // 0~255 : 2^8 = 256
	int b : 4; // 0~3 : 2^2 = 4
};

int main(void)
{
	struct A a;

	a.a = 100;
	a.b = 3;

	printf("%d %d \n", a.a, a.b);
	printf("Size : %d\n", sizeof(a));//8Byte : 64Bit

	system("pause");
}
100 3
Size : 4

코드: 구조체_구조체비트필드.c

#include <stdio.h>

// 멤버(필드)의 데이터 저장 범위
// i: 0~255
// j: 0~3
struct A
{
    int i;
    int j;
};

// 구조체 비트필드를 적용한 구조체.
struct B
{
    int i : 8;//2^8=256
    int j : 4;//2^4=8
};

void main()
{
    struct A a; struct B b;
    a.i = 100; a.j = 3; b.i = 100; b.j = 3;
    printf("%d %d\n", a.i, a.j);
    printf("%d\n", sizeof(a));//8Byte
    printf("%d %d\n", b.i, b.j);
    printf("%d\n", sizeof(b));//4Byte

    system("pause");
}
100 3
8
100 3
4

typedef 키워드와 함께 사용 - 구조체.c

코드: 구조체.c

#include <stdio.h>

struct _BizCard
{
	char* name;//문자열
	int age;//정수
};

typedef struct _BizCard BizCard;

int main(void)
{
	BizCard a;

	a.name = "홍길동";
	a.age = 21;

	printf("%s %d\n", a.name, a.age);
}
홍길동 21

C# 참고 - 구조체 매개 변수 - 함수의 매개 변수에 구조체 사용하기

이번에는 함수의 매개 변수로 구조체를 전달하는 구조체 매개 변수를 사용해보겠습니다.

코드: StructParameter.cs

using System;

// Member 구조체 선언
struct Member
{
    public string Name;
    public int Age;
}

class StructParameter
{
    static void Main()
    {
        //[1] 변수 사용
        string name = "홍길동";
        int age = 21;
        Print(name, age); // 매개 변수를 따로 선언

        //[2] 구조체 사용 
        Member m;
        m.Name = "백두산";
        m.Age = 100;
        Print(m); // 구조체 매개 변수를 사용하여 전달
    }

    static void Print(string name, int age) =>
        Console.WriteLine($"이름: {name}, 나이: {age}");

    static void Print(Member member) =>
        Console.WriteLine($"이름: {member.Name}, 나이: {member.Age}");
}
이름: 홍길동, 나이: 21
이름: 백두산, 나이: 100

변수를 사용하여 Print 함수에 nameage를 전달하는 모양과 구조체를 사용하여 Print 함수에 구조체 변수인 member를 전달하는 2가지 모양을 확인할 수 있습니다.

만약, 한번에 함수에 전달해야 하는 매개 변수가 많을 경우에는 이처럼 구조체에 묶어서 구조체 변수 하나로 전달해서 사용하면 복잡하지 않고 편리하게 매개 변수를 전달 할 수 있습니다.

장 요약

C 언어에서 구조체는 사용자 정의 데이터 타입을 만들어 내는 최상위 문법입니다. 기본 사용법을 간단히 익혔으니 또 다른 문법을 학습해 나가도록 하겠습니다.

포인터 배우고 나서(아직 안 배운 내용)

구조체를 포인터로 접근하기

C 언어에서 구조체를 포인터로 접근하는 예제는 다음과 같습니다:

#include <stdio.h>

struct point {
    int x;
    int y;
};

int main() {
    struct point p1 = { 10, 20 };
    struct point *p2 = &p1;

    printf("x: %d\n", p2->x);
    printf("y: %d\n", p2->y);

    return 0;
}

위 예제에서는 구조체 변수 p1을 선언하고, 구조체 포인터 변수 p2를 선언하여 구조체 변수 p1의 주소를 가리키게 합니다. 그리고 포인터 p2를 사용하여 구조체 변수 p1의 멤버 변수인 x와 y에 접근합니다. 포인터를 사용하여 구조체 멤버에 접근할 때는 화살표 연산자(->)를 사용합니다.

구조체 포인터를 선언 및 동적으로 메모리 할당하기

구조체 포인터를 선언하고 동적으로 메모리 할당하는 예제는 다음과 같습니다.

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

typedef struct {
  char name[100];
  int age;
} Person;

int main() {
  Person *person = (Person *)malloc(sizeof(Person));
  strcpy(person->name, "John Doe");
  person->age = 30;
  printf("Name: %s\n", person->name);
  printf("Age: %d\n", person->age);
  free(person);
  return 0;
}

위의 코드에서 Person *person = (Person *)malloc(sizeof(Person));Person 타입의 구조체를 가리키는 포인터 person을 만들고, malloc 함수를 사용하여 Person 타입의 메모리를 할당합니다. 그리고 구조체 포인터의 필드에 접근할 때는 -> 연산자를 사용합니다. 예제에서는 person->name, person->age처럼 접근하였습니다. 마지막으로 free 함수를 사용하여 할당한 메모리를 해제합니다.

구조체 별칭으로 포인터 선언 및 메모리 할당

C 언어에서 구조체 별칭으로 포인터 선언 및 메모리 할당하는 예제는 다음과 같습니다.

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

typedef struct {
  char name[100];
  int age;
} Person;

int main() {
  typedef Person* PPerson;
  PPerson person = (PPerson)malloc(sizeof(Person));
  strcpy(person->name, "John Doe");
  person->age = 30;
  printf("Name: %s\n", person->name);
  printf("Age: %d\n", person->age);
  free(person);
  return 0;
}

위의 코드에서 typedef Person* PPerson;Person 타입의 포인터를 가리키는 별칭 PPerson을 정의합니다. 이렇게 정의한 후, PPerson 타입으로 포인터 변수를 선언할 수 있습니다. 예제에서는 PPerson person = (PPerson)malloc(sizeof(Person));처럼 PPerson 타입의 포인터 변수 person을 선언하였습니다. 그리고 구조체 포인터의 필드에 접근할 때는 -> 연산자를 사용합니다. 마지막으로 free 함수를 사용하여 할당한 메모리를 해제합니다.

구조체 포인터 배열 선언하기

C 언어에서 구조체 포인터 배열을 선언하는 예제는 다음과 같습니다.

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

typedef struct {
  char name[100];
  int age;
} Person;

int main() {
  Person *people[3];
  for (int i = 0; i < 3; i++) {
    people[i] = (Person *) malloc(sizeof(Person));
  }
  strcpy(people[0]->name, "John Doe");
  people[0]->age = 30;
  strcpy(people[1]->name, "Jane Doe");
  people[1]->age = 25;
  strcpy(people[2]->name, "Jim Doe");
  people[2]->age = 40;
  for (int i = 0; i < 3; i++) {
    printf("Name: %s\n", people[i]->name);
    printf("Age: %d\n", people[i]->age);
    free(people[i]);
  }
  return 0;
}

위의 코드에서 Person *people[3];은 Person 타입의 포인터 배열 people을 정의합니다. for 루프를 사용하여 각 요소에 대해 메모리를 할당합니다. 각 요소에 접근할 때는 -> 연산자를 사용합니다. for 루프를 사용하여 각 요소에 접근하여 값을 설정하고 출력할 수 있습니다. 그리고 free 함수를 사용하여 할당한 메모리를 해제합니다.

구조체 사용 성적 처리 프로그램 작성

이번 강좌에서는 C언어의 구조체를 사용하여 성적 처리 프로그램을 작성하는 방법을 배워보겠습니다.

구조체란?

구조체(Structure)는 C언어에서 여러 개의 변수를 묶어서 하나의 데이터 형식으로 정의할 수 있는 기능입니다. 이를 통해 복잡한 데이터를 효율적으로 관리할 수 있습니다.

구조체는 struct 키워드와 함께 선언할 수 있습니다. 예를 들어, 아래와 같이 이름과 나이를 저장하는 구조체를 선언할 수 있습니다.

struct Person {
    char name[20];
    int age;
};

이 구조체를 사용하여 여러 개의 사람 정보를 저장할 수 있습니다.

struct Person p1 = {"Alice", 25};
struct Person p2 = {"Bob", 30};

구조체를 사용한 성적 처리 프로그램

이제 구조체를 사용하여 성적 처리 프로그램을 작성해보겠습니다. 먼저, 학생의 이름과 국어 점수, 영어 점수를 저장하는 구조체를 정의합니다.

typedef struct Score {
    char name[10];  // *name : 이름
    int kor;
    int eng;
} Score;

이 구조체는 학생의 이름과 국어 점수, 영어 점수를 저장할 수 있는 멤버 변수를 가지고 있습니다.

다음으로, main() 함수에서는 Score 구조체 형 배열을 선언합니다. 이 배열은 두 명의 학생에 대한 성적을 저장합니다.

int main() {
    int i = 0;
    Score objScore[2];
    // ...
}

for 루프를 사용하여 scanf() 함수를 통해 학생의 이름, 국어 점수, 영어 점수를 입력받습니다.

for (i = 0; i < 2; i++) {
    printf("\n%d번째 이름 : ", i + 1);
    scanf("%9s", objScore[i].name);
    printf("\n국어점수 : ");
    scanf("%d", &objScore[i].kor);
    printf("\n영어점수 : ");
    scanf("%d", &objScore[i].eng);
}

이때 %9s를 사용하여 이름을 입력받습니다. %9s는 문자열의 길이를 9로 제한하는 서식지정자입니다.

다음으로, for 루프를 사용하여 Score 배열의 각 요소에 대해 총점과 평균을 계산합니다. 총점은 koreng 멤버 변수의 합으로 계산되며, 평균은 tot 멤버 변수를 2.0으로 나눈 결과입니다.

// Process : 총점과 평균 구하기.
for (i = 0; i < 2; i++) {
    // 총점
    objScore[i].tot = objScore[i].kor + objScore[i].eng;
    // 평균
    objScore[i].avg = objScore[i].tot / 2.0;
}

마지막으로, for 루프를 사용하여 각 학생의 이름, 국어 점수, 영어 점수, 총점, 평균을 출력합니다.

printf("이름\t국어\t영어\t총점\t평균\t\n");
for (i = 0; i < 2; i++) {
    printf("%6s %4d %4d %4d %4.1f\n",
        objScore[i].name,
        objScore[i].kor,
        objScore[i].eng,
        objScore[i].tot,
        objScore[i].avg);
}

이렇게 구현된 성적 처리 프로그램은 두 명의 학생에 대한 성적을 입력받아 총점과 평균을 계산하고, 이를 출력합니다.

전체 소스는 다음과 같습니다.

코드: struct_score.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// 구조체 설계.
typedef struct Score
{
    char name[10];  // *name : 이름
    int kor;
    int eng;
    int tot;
    double avg;
} Score;

int main(void)
{
    int i = 0;
    Score score[2];

    // 구조체 형 배열 초기화 : scanf()
    for (i = 0; i < 2; i++)
    {
        printf("%d번째 이름: ", i + 1);
        scanf("%9s", score[i].name);
        printf("국어점수: ");
        scanf("%d", &score[i].kor);
        printf("영어점수: ");
        scanf("%d", &score[i].eng);
    }

    // Process : 총점과 평균 구하기.
    for (i = 0; i < 2; i++)
    {
        // 총점
        score[i].tot = score[i].kor + score[i].eng;
        // 평균
        score[i].avg = score[i].tot / 2.0;
    }

    // Output : 결과 출력
    printf("\n 이름  국어  영어  총점  평균\n");
    for (i = 0; i < 2; i++)
    {
        printf("%5s %5d %5d %5d %5.1f\n",
            score[i].name,
            score[i].kor,
            score[i].eng,
            score[i].tot,
            score[i].avg);
    }

    return 0;
}
1번째 이름: AAA
국어점수: 100
영어점수: 90
2번째 이름: BBB
국어점수: 95
영어점수: 85

 이름  국어  영어  총점  평균
  AAA   100    90   190  95.0
  BBB    95    85   180  90.0

마무리

이번 강좌에서는 C언어의 구조체를 사용하여 성적 처리 프로그램을 작성하는 방법을 배워보았습니다. 구조체는 여러 개의 변수를 묶어서 하나의 자료형으로 정의할 수 있는 기능으로, 복잡한 데이터를 효율적으로 관리할 수 있습니다. 구조체를 사용하여 성적 처리 프로그램을 구현하면, 입력한 학생의 성적을 효율적으로 저장하고 처리할 수 있습니다.

면접 및 코딩 테스트 준비

  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. typedef를 사용하여 구조체를 새로운 데이터 타입으로 정의하는 방법은 무엇인가요?
  26. 구조체를 포인터 배열로 정의하는 방법은 무엇인가요?
  27. 구조체의 멤버가 배열인 경우의 접근 방법은 무엇인가요?
  28. 구조체의 멤버가 함수 포인터인 경우의 접근 방법은 무엇인가요?
  29. 구조체 멤버에 대한 비트 필드를 사용하는 방법은 무엇인가요?
  30. 구조체를 사용하여 union을 구현하는 방법은 무엇인가요?
  31. 구조체 내부에 구조체를 정의하는 방법은 무엇인가요?
  32. 구조체의 크기를 계산하는 방법은 무엇인가요?
  33. 구조체의 정렬 방식을 변경하는 방법은 무엇인가요?
  34. 구조체 내부에 padding이 발생하는 이유는 무엇인가요?
  35. 구조체 멤버의 크기와 정렬에 영향을 주는 데이터 타입이 무엇인가요?
  36. attribute ((packed))를 사용하여 구조체의 패딩을 없애는 방법은 무엇인가요?
  37. 구조체에서 임의의 메모리 위치에 데이터를 저장하는 방법은 무엇인가요?
  38. 비트 필드를 사용하여 구조체의 크기를 최소화하는 방법은 무엇인가요?
  39. 비트 필드를 사용하여 여러 개의 데이터를 저장하는 방법은 무엇인가요?
  40. 비트 필드를 사용하여 상태 정보를 저장하는 방법은 무엇인가요?
  41. 구조체의 멤버에 대한 메모리 접근 방식은 무엇인가요?
  42. 구조체의 멤버에 대한 메모리 접근 방식을 변경하는 방법은 무엇인가요?
  43. 구조체를 사용하여 전체적인 메모리 구조를 설계하는 방법은 무엇인가요?
  44. 구조체의 멤버를 초기화하는 방법은 무엇인가요?
  45. 구조체에서 문자열을 저장하는 방법은 무엇인가요?
  46. 구조체에서 문자열을 복사하는 방법은 무엇인가요?
  47. 구조체에서 문자열을 비교하는 방법은 무엇인가요?
  48. 구조체에서 동적으로 메모리를 할당하는 방법은 무엇인가요?
  49. 구조체에서 메모리를 해제하는 방법은 무엇인가요?
  50. 구조체에서 메모리 관리를 위한 도구로서 메모리 풀을 사용하는 방법은 무엇인가요?

문제 풀이

정보처리기능사 실기 문제: 구조체 배열 초기화 및 멤버 값의 합 계산

이 문제에서는 C 언어를 사용하여 구조체 배열을 초기화하고, 특정 구조체 멤버들의 값을 계산하여 출력하는 프로그램을 작성하는 것이 목표입니다. 이 과정에서 구조체 배열의 정의, 초기화 방법, 그리고 구조체 멤버에 접근하여 연산을 수행하는 방법에 대해 이해해야 합니다.

문제: A라는 구조체가 있습니다. 이 구조체는 두 개의 정수 멤버 ng를 가집니다. 구조체 타입 A의 배열 st를 선언하고, 배열의 각 요소에 대해 n 멤버에는 배열의 인덱스 값을, g 멤버에는 인덱스 값에 1을 더한 값을 할당합니다. 이후, 배열의 첫 번째 요소의 n 값과 두 번째 요소의 g 값을 더한 결과를 출력하는 C 프로그램을 작성하시오.

#include <stdio.h>

struct A {
    int n;
    int g;
};

main() {
    struct A st[2]; // 구조체 A 타입의 배열 선언
    // 배열의 각 요소에 대해 n과 g를 초기화
    for (int i = 0; i < 2; i++) {
        st[i].n = i;
        st[i].g = i + 1;
    }
    // 첫 번째 요소의 n 값과 두 번째 요소의 g 값을 더하여 출력
    printf("%d", st[0].n + st[1].g);
}

해결 방법:

  1. #include <stdio.h>를 사용하여 표준 입출력 라이브러리를 포함합니다.
  2. A라는 이름의 구조체를 정의합니다. 이 구조체는 두 개의 정수 멤버 ng를 포함합니다.
  3. A 타입의 구조체 배열 st를 크기 2로 선언합니다.
  4. for 반복문을 사용하여 배열 st의 각 요소에 대해, 멤버 n에는 반복 변수 i의 값을, 멤버 g에는 i + 1의 값을 할당합니다.
  5. 배열 st의 첫 번째 요소의 n 멤버 값과 두 번째 요소의 g 멤버 값을 더한 결과를 printf 함수를 사용하여 출력합니다.

이 문제는 구조체 배열의 사용법과 각 요소의 멤버에 값을 할당하는 방법을 이해하는 데 중점을 둡니다. 또한, 구조체 멤버 값을 사용하여 간단한 수학 연산을 수행하고 그 결과를 출력하는 기본적인 프로그래밍 능력을 평가합니다.

VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com