c - 구조체

Development/C 2013. 4. 26. 09:13


프로그램을 만들면서 가장 중요하게 고려해야 할 사항은 데이터를 어떻게 구성해야 하는가입니다. 프로그래밍 언어들은 여러가지 방법으로 이를 지원하고 있으며, 그 중 가장 기초적이며 공통적인 것이 배열(array) 외에 구조체(structue)가 있습니다. 이번 포스트에서는 구조체를 정의하는 방법을 설명합니다.

 

이번 포스트의 주요 내용

1. 구조체(structure)란?

2. 구조체의 문법

3. 구조체 변수를 정의하기

4. 구조체 변수를 초기화하기

5. 구조체 변수의 멤버에 접근하기

6. 포인터로 구조체의 멤버에 접근하기

7. 데이터형의 이름을 새로 정의하기

8. 예제 코드

 

 

구조체(structure)란?

구조체(structure)란 서로 다른 데이터형의 변수들의 집합을 뜻합니다. 이것은 데이터를 통합적으로 사용할 수 있음을 뜻하며, 특정 범주의 데이터를 정의하고 사용할 때 매우 유용한 문법적 요소입니다.

 

성적 관리 프로그램을 만든다고 가정해 봅시다. 수많은 과목들의 점수가 존재하고, 여러 종류의 시험(예: 중간고사, 기말고사 등등)이 있다면, 성적을 나타내는 구조체를 정의할 수 있습니다. 이 구조체 안에는 과목들의 점수, 총점, 평균 등이 구조체의 멤버로 선언될 수 있습니다.

 

 

구조체의 문법

C언어에서 정의된 구조체의 문법은 다음과 같습니다.

 

struct-or-union identifieropt { struct-declaration-list }

 

struct-or-union에는 구조체를 선언하는데 필요한 키워드인 struct가 들어갑니다. identifier는 구조체의 종류를 식별하는데 필요하며, 구조체 태그(structure tag)라고도 부릅니다. 이것은 option이므로 생략할 수 있습니다. struct-declaration-list에는 구조체에 속하는 변수들의 집합을 의미합니다. 여기에 변수를 선언하는 것과 동일한 방법으로 구조체 내부의 변수들을 정의할 수 있습니다.

 

예를 들어 과목별 점수, 총점, 평균을 가지는 구조체를 정의하려면 아래와 같이 작성할 수 있습니다.

 

struct Score

{

    int korean;        /* 국어 점수 */

    int math;           /* 수학 점수 */

    int english;       /* 영어 점수 */

    int total;            /* 총점 */

    float average;    /* 평균 */

};

 

만약 구조체 태그를 생략한다면, 구조체를 식별할 수 있는 방법이 없습니다. 이 경우 구조체를 정의함과 동시에 변수를 선언해 줄 필요가 있습니다. 아래의 예는 위 예에서 구조체 태그를 생략하고 변수를 동시에 선언한 결과입니다.

 

struct

{

    int korean;        /* 국어 점수 */

    int math;           /* 수학 점수 */

    int english;       /* 영어 점수 */

    int total;            /* 총점 */

    float average;    /* 평균 */

} midterm_score;

 

 

구조체 변수를 정의하기

구조체를 정의할 때 위 문법의 identifier가 있으면, 'struct identifier'라는 이름으로 사용자 정의 데이터형이 만들어집니다. 구조체를 사용하기 위해서는 이러한 데이터형의 변수를 정의해야 합니다. 위 섹션에서 예로 작성된 구조체로부터 새로 정의된 데이터형의 이름은 struct Score입니다. 이 타입의 변수를 다음과 같이 선언할 수 있습니다.

 

struct Score midterm_score;

 

 

구조체 변수를 초기화하기

배열과 마찬가지로 구조체 변수도 초기화할 수 있습니다. 그 방법은 다음과 같습니다.

 

1. 변수 선언시 변수 이름 뒤에 대입 연산자 '='를 추가합니다.

2. 대괄호를 엽니다.

3. 구조체의 멤버들이 선언된 순서대로 초기화될 값들을 적습니다. 값 사이는 컴머(,)로 구별합니다.

4. 대괄호를 닫습니다.

 

이전 섹션에 정의된 구조체로 변수를 초기화하는 예를 들어보겠습니다.

 

struct Score midterm_score = { 69, 74, 81, 224, 74.67 };

 

멤버 korean, math, english, total, average에 각각 68, 74, 81, 224, 74.67이 대입됩니다.

 

 

구조체 변수의 멤버에 접근하기

구조체로 변수를 정의한 후 구조체의 멤버들에 접근하려면 멤버 연산자(.)를 사용합니다. 이것을 이용하여 멤버를 사용하는 방법은 다음과 같습니다.

 

1. 구조체 변수 이름을 작성합니다.

2. 변수 이름 뒤에 멤버 연산자를 추가합니다.

3. 멤버 연산자 뒤에 멤버의 이름을 작성합니다.

 

1~3을 따르면, 다음과 같은 형식이 됩니다.

 

변수명.멤버이름

 

이 방법으로 위의 예에서 정의된 midterm_score 변수의 멤버에 국어, 영어, 수학 점수를 정하고 총점을 계산할 수 있습니다.

 

midterm_score.korean = 76;

midterm_score.math = 88;

midterm_score.93;

midterm_score.total = midterm_score.korean + midterm_score.math + midterm_score.english;

midterm_score.average = (float)(midterm_score.total) / 3;

 

 

포인터로 구조체의 멤버에 접근하기

만약 포인터를 이용하여 구조체의 멤버에 접근하려면, 도트(.)가 아닌 ->를 이용합니다. 즉, 다음과 같은 형식을 따릅니다.

 

포인터변수명->멤버이름

 

이번 예는 midterm_score를 가리키는 포인터를 정의하고, 이것으로 점수를 대입하는 과정을 보여 줍니다.

 

struct Score midterm_score;

struct Score * pointer = &midterm_score;

 

pointer->korean = 76

pointer->math = 88;

pointer->english = 93;

 

 

데이터형의 이름을 새로 정의하기

struct identifier와 같은 방식으로 데이터형의 이름을 사용하는 것은 키워드 struct가 반복되므로 이는 번거로운 일입니다. typedef를 사용하면 축약된 데이터형의 이름을 새로 정의할 수 있습니다. 예를 들어, typedef로 struct Score 대신 Score를 구조체 데이터형의 이름으로 변수 정의가 가능해집니다.

 

typedef struct Score Score;

 

Score midterm_score;

 

구조체를 정의함과 동시에 typedef을 적용하는 것도 가능합니다. 키워드 struct의 앞에 typedef를 추가하고, 구조체 정의를 뒤이어 새 데이터형의 이름을 써 주시면 됩니다. 기 작성한 struct Score 코드에 이것을 적용하면 다음과 같이 코드가 변경됩니다.

 

typedef struct Score

{

    int korean;        /* 국어 점수 */

    int math;           /* 수학 점수 */

    int english;       /* 영어 점수 */

    int total;            /* 총점 */

    float average;    /* 평균 */

} Score;

 

 

예제 코드

이번 예제는 1학기의 중간 및 기말고사의 성적과 이들의 평균을 계산한 1학기 최종 성적 결과를 보여주는 프로그램입니다.

 

Ex-Structure.c

#include <stdio.h>

 

/* 성적을 나타내는 구조체 */

 

struct ExamScore
{
 int korean;  // 국어 점수
 int math;  // 수학 점수
 int english; // 영어 점수
 int total;  // 총점
 float average; // 평균
 char grade;  // 등급
};

 

typedef struct ExamScore ExamScore;    /* 구조체의 이름의 재정의 */

 

void main()
{
    /* 중간 및 기말고사 성적을 나타내는 구조체 변수들 */
    ExamScore mid_exam = {82, 76, 91, 249, (float)83.0, 'B'};
    ExamScore final_exam = {88, 96, 73, 257, (float)85.67, 'B'};
 
    /* 1학기 성적을 나타내는 구조체 변수 */
    ExamScore first_semester;

 

    /* 1학기 성적을 계산 (중간 및 기말고사 성적의 평균) */
    first_semester.korean = (mid_exam.korean + final_exam.korean) / 2;
    first_semester.math = (mid_exam.math + final_exam.math) / 2;
    first_semester.english = (mid_exam.english + final_exam.english) / 2;
    first_semester.total = first_semester.korean + first_semester.math + first_semester.english;
    first_semester.average = (float)first_semester.total / 3;

 

    /* 1학기 성적의 등급을 계산 */
    if (first_semester.average >= 90.0)
        first_semester.grade = 'A';
    else if (first_semester.average >= 80.0)
        first_semester.grade = 'B';
    else if (first_semester.average >= 70.0)
        first_semester.grade = 'C';
    else if (first_semester.average >= 60.0)
        first_semester.grade = 'D';
    else
        first_semester.grade = 'F';

 

    /* 성적표 출력 */
    printf("-------------------------- ");
    printf("과목 | 중간 | 기말 | 1학기 ");
    printf("-------------------------- ");
    printf("국어 | %4d | %4d | %4d ", mid_exam.korean, final_exam.korean, first_semester.korean);
    printf("수학 | %4d | %4d | %4d ", mid_exam.english, final_exam.english, first_semester.english);
    printf("영어 | %4d | %4d | %4d ", mid_exam.math, final_exam.math, first_semester.math);
    printf("-------------------------- ");
    printf("총점 | %4d | %4d | %4d ", mid_exam.total, final_exam.total, first_semester.total);
    printf("평균 | %2.1f | %2.1f | %2.1f ", mid_exam.average, final_exam.average, first_semester.average);
    printf("-------------------------- ");
}

 

실행 결과는 다음과 같습니다.

 

--------------------------
과목 | 중간 | 기말 | 1학기
--------------------------
국어 |   82 |   88 |   85
수학 |   91 |   73 |   82
영어 |   76 |   96 |   86
--------------------------
총점 |  249 |  257 |  253
평균 | 83.0 | 85.7 | 84.3
--------------------------

  


출처 - http://blog.naver.com/PostView.nhn?blogId=netrance&logNo=110051682671



Posted by linuxism
,